📄 tcpip.c
字号:
//Wakeup sender thread message[0] = 2; OS_MQueueSend(IPMQueue, message); }}static void IPSendPacket(IPSocket *socket, IPFrame *frame, int length){ int checksum, length2=length; unsigned char pseudo[12], *packet=frame->packet; frame->length = (uint16)length; //Calculate checksums if(packet[ETHERNET_FRAME_TYPE+1] == 0x00) //IP { length2 = length - IP_VERSION_LENGTH; packet[IP_LENGTH] = (uint8)(length2 >> 8); packet[IP_LENGTH+1] = (uint8)length2; memset(packet+IP_CHECKSUM, 0, 2); checksum = IPChecksum(0xffff, packet+IP_VERSION_LENGTH, 20); packet[IP_CHECKSUM] = (unsigned char)(checksum >> 8); packet[IP_CHECKSUM+1] = (unsigned char)checksum; if(packet[IP_PROTOCOL] == 0x01) //PING { memset(packet+PING_CHECKSUM, 0, 2); checksum = IPChecksum(0xffff, packet+PING_TYPE, length-PING_TYPE); packet[PING_CHECKSUM] = (unsigned char)(checksum >> 8); packet[PING_CHECKSUM+1] = (unsigned char)checksum; } else if(packet[IP_PROTOCOL] == 0x11) //UDP { length2 = length - UDP_SOURCE_PORT; packet[UDP_LENGTH] = (uint8)(length2 >> 8); packet[UDP_LENGTH+1] = (uint8)length2; memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4); memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4); pseudo[PSEUDO_ZERO] = 0; pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL]; memcpy(pseudo+PSEUDO_LENGTH, packet+UDP_LENGTH, 2); checksum = IPChecksum(0xffff, pseudo, 12); memset(packet+UDP_CHECKSUM, 0, 2); length2 = (packet[UDP_LENGTH] << 8) + packet[UDP_LENGTH+1]; checksum = IPChecksum(checksum, packet+UDP_SOURCE_PORT, length2); packet[UDP_CHECKSUM] = (unsigned char)(checksum >> 8); packet[UDP_CHECKSUM+1] = (unsigned char)checksum; } else if(packet[IP_PROTOCOL] == 0x06) //TCP { memcpy(pseudo+PSEUDO_IP_SOURCE, packet+IP_SOURCE, 4); memcpy(pseudo+PSEUDO_IP_DEST, packet+IP_DEST, 4); pseudo[PSEUDO_ZERO] = 0; pseudo[PSEUDO_IP_PROTOCOL] = packet[IP_PROTOCOL]; length2 = (packet[IP_LENGTH] << 8) + packet[IP_LENGTH+1]; length2 = length2 - 20; pseudo[PSEUDO_LENGTH] = (unsigned char)(length2 >> 8); pseudo[PSEUDO_LENGTH+1] = (unsigned char)length2; checksum = IPChecksum(0xffff, pseudo, 12); memset(packet+TCP_CHECKSUM, 0, 2); checksum = IPChecksum(checksum, packet+TCP_SOURCE_PORT, length2); packet[TCP_CHECKSUM] = (unsigned char)(checksum >> 8); packet[TCP_CHECKSUM+1] = (unsigned char)checksum; } } length2 = length - TCP_DATA; if(socket && (packet[TCP_FLAGS] & (TCP_FLAGS_FIN | TCP_FLAGS_SYN))) length2 = 1; frame->socket = socket; frame->timeout = 0; frame->retryCnt = 0; if(socket) frame->seqEnd = socket->seq + length2; IPSendFrame(frame);}static void TCPSendPacket(IPSocket *socket, IPFrame *frame, int length){ uint8 *packet = frame->packet; int flags, count; flags = packet[TCP_FLAGS]; memcpy(packet, socket->headerSend, TCP_SEQ); packet[TCP_FLAGS] = (uint8)flags | (socket->headerSend[TCP_FLAGS] & TCP_FLAGS_PSH); if(flags & TCP_FLAGS_SYN) packet[TCP_HEADER_LENGTH] = 0x60; //set maximum segment size else packet[TCP_HEADER_LENGTH] = 0x50; packet[TCP_SEQ] = (uint8)(socket->seq >> 24); packet[TCP_SEQ+1] = (uint8)(socket->seq >> 16); packet[TCP_SEQ+2] = (uint8)(socket->seq >> 8); packet[TCP_SEQ+3] = (uint8)socket->seq; packet[TCP_ACK] = (uint8)(socket->ack >> 24); packet[TCP_ACK+1] = (uint8)(socket->ack >> 16); packet[TCP_ACK+2] = (uint8)(socket->ack >> 8); packet[TCP_ACK+3] = (uint8)socket->ack; count = FrameFreeCount - FRAME_COUNT_WINDOW; if(count < 1) count = 1; if(count > 4) count = 4; count *= 512; packet[TCP_WINDOW_SIZE] = (uint8)(count >> 8); packet[TCP_WINDOW_SIZE+1] = (uint8)count; packet[TCP_URGENT_POINTER] = 0; packet[TCP_URGENT_POINTER+1] = 0; IPSendPacket(socket, frame, length);}static void EthernetCreateResponse(unsigned char *packetOut, const unsigned char *packet, int length){ //Swap destination and source fields memcpy(packetOut, packet, length); memcpy(packetOut+ETHERNET_DEST, packet+ETHERNET_SOURCE, 6); memcpy(packetOut+ETHERNET_SOURCE, packet+ETHERNET_DEST, 6); if(packet[ETHERNET_FRAME_TYPE+1] == 0x00) //IP { memcpy(packetOut+IP_SOURCE, packet+IP_DEST, 4); memcpy(packetOut+IP_DEST, packet+IP_SOURCE, 4); if(packet[IP_PROTOCOL] == 0x06 || packet[IP_PROTOCOL] == 0x11) //TCP/UDP { memcpy(packetOut+TCP_SOURCE_PORT, packet+TCP_DEST_PORT, 2); memcpy(packetOut+TCP_DEST_PORT, packet+TCP_SOURCE_PORT, 2); } }}static void IPDhcp(const unsigned char *packet, int length, int state){ uint8 *packetOut, *ptr; const uint8 *ptr2; IPFrame *frame; static int request=0; if(state == 1) { //Create DHCP Discover frame = IPFrameGet(0); if(frame == NULL) return; packetOut = frame->packet; memset(packetOut, 0, 512); memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover)); memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6); memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6); memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions)); memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6); IPSendPacket(NULL, frame, 400); request = DHCP_DISCOVER; DhcpRetrySeconds = RETRANSMIT_TIME; } else if(state == 2 && memcmp(packet+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6) == 0) { if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_OFFER && request == DHCP_DISCOVER) { //Process DHCP Offer and send DHCP Request frame = IPFrameGet(0); if(frame == NULL) return; packetOut = frame->packet; memset(packetOut, 0, 512); memcpy(packetOut, dhcpDiscover, sizeof(dhcpDiscover)); memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6); memcpy(packetOut+DHCP_CLIENT_ETHERNET, ethernetAddressPlasma, 6); memcpy(packetOut+DHCP_MAGIC_COOKIE, dhcpOptions, sizeof(dhcpOptions)); memcpy(packetOut+DHCP_MAGIC_COOKIE+10, ethernetAddressPlasma, 6); request = DHCP_REQUEST; packetOut[DHCP_MAGIC_COOKIE+6] = DHCP_REQUEST; ptr = packetOut+DHCP_MAGIC_COOKIE+sizeof(dhcpOptions)-1; ptr[0] = DHCP_REQUEST_IP; ptr[1] = 4; memcpy(ptr+2, packet+DHCP_YOUR_IP, 4); ptr[6] = DHCP_REQUEST_SERV_IP; ptr[7] = 4; memcpy(ptr+8, packet+DHCP_SERVER_IP, 4); ptr[12] = DHCP_END_OPTION; IPSendPacket(NULL, frame, 400); } else if(packet[DHCP_MAGIC_COOKIE+6] == DHCP_ACK && request == DHCP_REQUEST) { //Process DHCP Ack request = 0; DhcpRetrySeconds = 3600*4; memcpy(ipAddressPlasma, packet+DHCP_YOUR_IP, 4); printf("IP=%d.%d.%d.%d ", ipAddressPlasma[0], ipAddressPlasma[1], ipAddressPlasma[2], ipAddressPlasma[3]); memcpy(ipAddressGateway, packet+DHCP_GATEWAY_IP, 4); if(ipAddressGateway[0] == 0 && ipAddressGateway[1] == 0 && ipAddressGateway[2] == 0 && ipAddressGateway[3] == 0) memcpy(ipAddressGateway, packet+DHCP_SERVER_IP, 4); printf("GW=%d.%d.%d.%d ", ipAddressGateway[0], ipAddressGateway[1], ipAddressGateway[2], ipAddressGateway[3]); memcpy(ethernetAddressGateway, packet+ETHERNET_SOURCE, 6); ptr2 = packet+DHCP_MAGIC_COOKIE+4; while(ptr2[0] != DHCP_END_OPTION && (int)(ptr2 - packet) < length) { if(ptr2[0] == DHCP_PARAM_DNS) { ipAddressDns = (ptr2[2] << 24) | (ptr2[3] << 16) | (ptr2[4] << 8) | ptr2[5]; printf("DNS=%d.%d.%d.%d ", ptr2[2], ptr2[3], ptr2[4], ptr2[5]); } ptr2 += ptr2[1] + 2; } //Check if DHCP reply came from gateway if(memcmp(packet+IP_SOURCE, ipAddressGateway, 4)) { //Send ARP to gateway frame = IPFrameGet(0); if(frame == NULL) return; packetOut = frame->packet; memset(packetOut, 0, 512); memset(packetOut+ETHERNET_DEST, 0xff, 6); memcpy(packetOut+ETHERNET_SOURCE, ethernetAddressPlasma, 6); packetOut[ETHERNET_FRAME_TYPE] = 0x08; packetOut[ETHERNET_FRAME_TYPE+1] = 0x06; packetOut[ARP_HARD_TYPE+1] = 0x01; packetOut[ARP_PROT_TYPE] = 0x08; packetOut[ARP_HARD_SIZE] = 0x06; packetOut[ARP_PROT_SIZE] = 0x04; packetOut[ARP_OP+1] = 1; memcpy(packetOut+ARP_ETHERNET_SENDER, ethernetAddressPlasma, 6); memcpy(packetOut+ARP_IP_SENDER, ipAddressPlasma, 4); memcpy(packetOut+ARP_IP_TARGET, ipAddressGateway, 4); IPSendPacket(NULL, frame, 60); } } }}uint32 IPAddressSelf(void){ return (ipAddressPlasma[0] << 24) | (ipAddressPlasma[1] << 16) | (ipAddressPlasma[2] << 8) | ipAddressPlasma[3];}static int IPProcessTCPPacket(IPFrame *frameIn){ uint32 seq, ack; int length, ip_length, bytes; IPSocket *socket, *socketNew; IPFrame *frameOut, *frame2, *framePrev; uint8 *packet, *packetOut; packet = frameIn->packet; length = frameIn->length; ip_length = (packet[IP_LENGTH] << 8) | packet[IP_LENGTH+1]; seq = (packet[TCP_SEQ] << 24) | (packet[TCP_SEQ+1] << 16) | (packet[TCP_SEQ+2] << 8) | packet[TCP_SEQ+3]; ack = (packet[TCP_ACK] << 24) | (packet[TCP_ACK+1] << 16) | (packet[TCP_ACK+2] << 8) | packet[TCP_ACK+3]; //Check if start of connection if((packet[TCP_FLAGS] & (TCP_FLAGS_SYN | TCP_FLAGS_ACK)) == TCP_FLAGS_SYN) { if(IPVerbose) printf("S"); //Check if duplicate SYN for(socket = SocketHead; socket; socket = socket->next) { if(socket->state != IP_LISTEN && packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] && memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 && memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0) { if(IPVerbose) printf("s"); return 0; } } //Find an open port for(socket = SocketHead; socket; socket = socket->next) { if(socket->state == IP_LISTEN && packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] && memcmp(packet+TCP_DEST_PORT, socket->headerRcv+TCP_DEST_PORT, 2) == 0) { //Create a new socket frameOut = IPFrameGet(FRAME_COUNT_SYNC); if(frameOut == NULL) return 0; socketNew = (IPSocket*)malloc(sizeof(IPSocket)); if(socketNew == NULL) return 0; memcpy(socketNew, socket, sizeof(IPSocket)); socketNew->state = IP_TCP; socketNew->timeout = RETRANSMIT_TIME * 3; socketNew->ack = seq; socketNew->seq = socketNew->ack + 0x12345678; socketNew->seqReceived = socketNew->seq; //Send ACK packetOut = frameOut->packet; EthernetCreateResponse(packetOut, packet, length); memcpy(socketNew->headerRcv, packet, TCP_SEQ); memcpy(socketNew->headerSend, packetOut, TCP_SEQ); packetOut[TCP_FLAGS] = TCP_FLAGS_SYN | TCP_FLAGS_ACK; ++socketNew->ack; packetOut[TCP_DATA] = 2; //maximum segment size = 536 packetOut[TCP_DATA+1] = 4; packetOut[TCP_DATA+2] = 2; packetOut[TCP_DATA+3] = 24; TCPSendPacket(socketNew, frameOut, TCP_DATA+4); ++socketNew->seq; //Add socket to linked list OS_MutexPend(IPMutex); socketNew->next = SocketHead; socketNew->prev = NULL; if(SocketHead) SocketHead->prev = socketNew; SocketHead = socketNew; OS_MutexPost(IPMutex); return 0; } } return 0; } //Find an open socket for(socket = SocketHead; socket; socket = socket->next) { if(packet[IP_PROTOCOL] == socket->headerRcv[IP_PROTOCOL] && memcmp(packet+IP_SOURCE, socket->headerRcv+IP_SOURCE, 8) == 0 && memcmp(packet+TCP_SOURCE_PORT, socket->headerRcv+TCP_SOURCE_PORT, 4) == 0) { break; } } if(socket == NULL) return 0; //Check if FIN flag set if(packet[TCP_FLAGS] & TCP_FLAGS_FIN) { socket->timeout = SOCKET_TIMEOUT; if(IPVerbose) printf("F"); frameOut = IPFrameGet(0); if(frameOut == NULL) return 0; packetOut = frameOut->packet; packetOut[TCP_FLAGS] = TCP_FLAGS_ACK; ++socket->ack; TCPSendPacket(socket, frameOut, TCP_DATA); if(socket->state == IP_FIN_SERVER) IPClose2(socket); else { socket->state = IP_FIN_CLIENT; if(socket->funcPtr) socket->funcPtr(socket); } } else if(packet[TCP_FLAGS] & TCP_FLAGS_RST) { if(socket->state == IP_FIN_SERVER) IPClose2(socket); else { socket->state = IP_FIN_CLIENT; if(socket->funcPtr) socket->funcPtr(socket); } } else { //Check if packets can be removed from retransmition list if(ack != socket->seqReceived) { OS_MutexPend(IPMutex); for(frame2 = FrameResendHead; frame2; ) { framePrev = frame2; frame2 = frame2->next; if(framePrev->socket == socket && (int)(ack - framePrev->seqEnd) >= 0) { //Remove packet from retransmition queue if(socket->timeout) socket->timeout = SOCKET_TIMEOUT; FrameRemove(&FrameResendHead, &FrameResendTail, framePrev); FrameFree(framePrev); } } OS_MutexPost(IPMutex); socket->seqReceived = ack;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -