static void* udpThread(void* data) { UNUSED(data); int n = 0; while (workerRunning) { n = udpRecv(&stateLink, &fdmPkt, sizeof(fdm_packet), 100); if (n == sizeof(fdm_packet)) { // printf("[data]new fdm %d\n", n); updateState(&fdmPkt); } } printf("udpThread end!!\n"); return NULL; }
/** * Tests UDP * @return OK when testing is complete */ thread test_udp(bool verbose) { #ifdef UDP1 struct udp *udpptr = NULL; ushort pta; ushort ptb; struct netaddr ipc; struct netaddr ipd; struct netaddr ipl; struct netaddr src; struct netaddr dst; struct netaddr mask; struct netaddr ipzero; struct packet *pkt[10]; struct udpPkt *udppkt; struct udpPseudoHdr *pseudo; uchar buffera[12]; uchar bufferb[12]; uchar bufferc[12]; uchar bufferd[12]; uchar bufferp[40]; bool passed = TRUE; /* struct pcap_pkthdr phdr; struct netif *netptr; int nproc; int i; int wait; struct packet *pktA; uchar buf[100]; uchar *data; uchar *buffer; */ pta = 20000; ptb = 30000; /* IP address "C" */ ipc.type = NETADDR_IPv4; ipc.len = IPv4_ADDR_LEN; ipc.addr[0] = 192; ipc.addr[1] = 168; ipc.addr[2] = 1; ipc.addr[3] = 5; /* IP address "D" */ ipd.type = NETADDR_IPv4; ipd.len = IPv4_ADDR_LEN; ipd.addr[0] = 192; ipd.addr[1] = 168; ipd.addr[2] = 1; ipd.addr[3] = 7; /* "Local" IP address */ ipl.type = NETADDR_IPv4; ipl.len = IPv4_ADDR_LEN; ipl.addr[0] = 192; ipl.addr[1] = 168; ipl.addr[2] = 1; ipl.addr[3] = 8; /* Source IP address */ src.type = NETADDR_IPv4; src.len = IPv4_ADDR_LEN; src.addr[0] = 192; src.addr[1] = 168; src.addr[2] = 1; src.addr[3] = 6; /* Destination IP address */ dst.type = NETADDR_IPv4; dst.len = IPv4_ADDR_LEN; dst.addr[0] = 192; dst.addr[1] = 168; dst.addr[2] = 1; dst.addr[3] = 1; /* Mask */ mask.type = NETADDR_IPv4; mask.len = IPv4_ADDR_LEN; mask.addr[0] = 255; mask.addr[1] = 255; mask.addr[2] = 255; mask.addr[3] = 0; /* Empty address */ ipzero.type = 0; ipzero.len = 0; ipzero.addr[0] = 0; ipzero.addr[1] = 0; ipzero.addr[2] = 0; ipzero.addr[3] = 0; ipzero.addr[4] = 0; ipzero.addr[5] = 0; /* Test udpPkt structure */ //testPrint(verbose, "Header structure"); /* TODO: Figure out how this should be done */ /* Test udpOpen */ testPrint(verbose, "Open UDP devices (NULL local port)"); if (SYSERR == open(UDP0, &ipl, &ipd, NULL, ptb)) { failif(TRUE, ""); } if (SYSERR == open(UDP1, &ipl, &ipc, NULL, pta)) { failif(TRUE, ""); } failif((udptab[0].localpt == udptab[1].localpt) || (udptab[0].localpt < UDP_PSTART) || (udptab[0].localpt > UDP_PMAX) || (udptab[1].localpt < UDP_PSTART) || (udptab[1].localpt > UDP_PMAX), ""); if (SYSERR == close(UDP0)) { failif(TRUE, ""); } if (SYSERR == close(UDP1)) { failif(TRUE, ""); } /* Test udpOpen */ testPrint(verbose, "Open UDP device (NULL remote port)"); if (SYSERR == open(UDP0, &ipl, &ipd, pta, NULL)) { failif(TRUE, ""); } failif(udptab[0].remotept != NULL, ""); if (SYSERR == close(UDP0)) { failif(TRUE, ""); } /* Test udpOpen */ testPrint(verbose, "Open UDP device (NULL remote ip)"); if (SYSERR == open(UDP0, &ipl, NULL, pta, ptb)) { failif(TRUE, ""); } failif(0 == netaddrequal(&udptab[0].remoteip, &ipzero), ""); if (SYSERR == close(UDP0)) { failif(TRUE, ""); } /* Test udpOpen */ testPrint(verbose, "Open UDP devices (same local port)"); if (SYSERR == open(UDP0, &ipl, &ipd, pta, ptb)) { failif(TRUE, ""); } if (SYSERR == open(UDP1, &ipl, &ipd, pta, pta)) { failif(TRUE, ""); } failif(udptab[0].localpt != udptab[1].localpt, ""); /* Only close the second UDP device this time, we want to test close * using UDP0 */ if (SYSERR == close(UDP1)) { failif(TRUE, ""); } /* Test udpClose */ testPrint(verbose, "Close UDP device"); if (SYSERR == close(UDP0)) { failif(TRUE, ""); } failif((udptab[0].dev != 0) || (udptab[0].icount != 0) || (udptab[0].istart != 0) || (udptab[0].isem != 0) || (udptab[0].localpt != 0) || (udptab[0].remotept != 0) || (FALSE == netaddrequal(&udptab[0].localip, &ipzero)) || (FALSE == netaddrequal(&udptab[0].remoteip, &ipzero)) || (udptab[0].state != 0) || (udptab[0].flags != 0), ""); /* Test udpControl */ testPrint(verbose, "UDP Control: Binding"); /* Open UDP device to resume testing of that device */ if (SYSERR == open(UDP0, &ipl, NULL, NULL, NULL)) { failif(TRUE, ""); } control(UDP0, UDP_CTRL_ACCEPT, pta, (long)&ipl); control(UDP0, UDP_CTRL_BIND, ptb, (long)&ipc); failif((udptab[0].localpt != pta) || (FALSE == netaddrequal(&udptab[0].localip, &ipl)) || (udptab[0].remotept != ptb) || (FALSE == netaddrequal(&udptab[0].remoteip, &ipc)), ""); /* Test udpControl */ testPrint(verbose, "UDP Control: Flags"); control(UDP0, UDP_CTRL_SETFLAG, UDP_FLAG_PASSIVE | UDP_FLAG_NOBLOCK | UDP_FLAG_BINDFIRST, NULL); control(UDP0, UDP_CTRL_CLRFLAG, UDP_FLAG_NOBLOCK, NULL); /* At this point NOBLOCK should be the only flag that is off */ failif((FALSE == (udptab[0].flags & UDP_FLAG_PASSIVE)) || (udptab[0].flags & UDP_FLAG_NOBLOCK) || (FALSE == (udptab[0].flags & UDP_FLAG_BINDFIRST)), ""); /* Test udpDemux */ testPrint(verbose, "UDP Demux (2 sockets)"); open(UDP1, &ipl, NULL, pta, NULL); udpptr = udpDemux(pta, ptb, &ipl, &ipc); failif((udpptr == &udptab[1]) || (NULL == udpptr), ""); /* Test udpRecv and udpRead */ testPrint(verbose, "Receive and read UDP packets"); control(UDP0, UDP_CTRL_CLRFLAG, UDP_FLAG_PASSIVE | UDP_FLAG_BINDFIRST, NULL); control(UDP0, UDP_CTRL_ACCEPT, pta, (long)&ipl); control(UDP0, UDP_CTRL_BIND, ptb, (long)&ipc); pkt[0] = makePkt(ptb, pta, &ipl, &ipc, 5, "ABCDE"); pkt[1] = makePkt(ptb, pta, &ipl, &ipc, 4, "FGHI"); pkt[2] = makePkt(ptb, pta, &ipl, &ipc, 3, "JKL"); pkt[3] = makePkt(ptb, pta, &ipl, &ipc, 2, "MN"); if (SYSERR == udpRecv(pkt[0], &ipc, &ipl)) { failif(TRUE, "recva"); } if (SYSERR == udpRecv(pkt[1], &ipc, &ipl)) { failif(TRUE, "recvb"); } if (SYSERR == udpRecv(pkt[2], &ipc, &ipl)) { failif(TRUE, "recvc"); } if (SYSERR == udpRecv(pkt[3], &ipc, &ipl)) { failif(TRUE, "recvd"); } if (SYSERR == read(UDP0, buffera, 5)) { failif(TRUE, "reada"); } if (SYSERR == read(UDP0, bufferb, 5)) { failif(TRUE, "readb"); } if (SYSERR == read(UDP0, bufferc, 5)) { failif(TRUE, "readc"); } if (SYSERR == read(UDP0, bufferd, 5)) { failif(TRUE, "readd"); } failif((0 != strncmp((char *)buffera, "ABCDE", 5)) || (0 != strncmp((char *)bufferb, "FGHI", 4)) || (0 != strncmp((char *)bufferc, "JKL", 3)) || (0 != strncmp((char *)bufferd, "MN", 2)), ""); /* Test udpRecv and udpRead */ testPrint(verbose, "Two UDP sockets"); pkt[0] = makePkt(pta, pta, &ipc, &ipl, 9, "ABCDEFGHI"); udpRecv(pkt[0], &ipc, &ipl); read(UDP1, bufferc, 9); failif(0 != strncmp((char *)bufferc, "ABCDEFGHI", 9), ""); /* Test udpRecv and udpRead */ testPrint(verbose, "Receive and read UDP packets (again)"); control(UDP0, UDP_CTRL_CLRFLAG, UDP_FLAG_PASSIVE | UDP_FLAG_BINDFIRST, NULL); control(UDP0, UDP_CTRL_ACCEPT, pta, (long)&ipl); control(UDP0, UDP_CTRL_BIND, ptb, (long)&ipc); pkt[0] = makePkt(ptb, pta, &ipl, &ipc, 5, "OPQRS"); pkt[1] = makePkt(ptb, pta, &ipl, &ipc, 3, "TUV"); pkt[2] = makePkt(ptb, pta, &ipl, &ipc, 2, "WX"); pkt[3] = makePkt(ptb, pta, &ipl, &ipc, 2, "YZ"); udpRecv(pkt[0], &ipc, &ipl); udpRecv(pkt[1], &ipc, &ipl); udpRecv(pkt[2], &ipc, &ipl); udpRecv(pkt[3], &ipc, &ipl); if (SYSERR == read(UDP0, buffera, 5)) { failif(TRUE, "reada"); } if (SYSERR == read(UDP0, bufferb, 3)) { failif(TRUE, "readb"); } if (SYSERR == read(UDP0, bufferc, 2)) { failif(TRUE, "readc"); } if (SYSERR == read(UDP0, bufferd, 2)) { failif(TRUE, "readd"); } failif(0 != strncmp((char *)buffera, "OPQRS", 5) || (0 != strncmp((char *)bufferb, "TUV", 3)) || (0 != strncmp((char *)bufferc, "WX", 2)) || (0 != strncmp((char *)bufferd, "YZ", 2)), ""); /* Test udpRecv and udpRead on multiple sockets */ testPrint(verbose, "Recv/read with varying sockets (1)"); /* Test 1 */ control(UDP0, UDP_CTRL_ACCEPT, pta, (long)&ipl); control(UDP0, UDP_CTRL_BIND, NULL, NULL); pkt[0] = makePkt(ptb, pta, &ipc, &ipl, 5, "test1"); udpRecv(pkt[0], &ipc, &ipl); read(UDP0, buffera, 5); failif(strncmp((char *)buffera, "test1", 5), ""); /* Test 2 */ testPrint(verbose, "Recv/read socket test 2"); control(UDP0, UDP_CTRL_ACCEPT, pta, (long)&ipl); control(UDP0, UDP_CTRL_BIND, ptb, NULL); control(UDP1, UDP_CTRL_ACCEPT, pta, (long)&ipl); control(UDP1, UDP_CTRL_BIND, 0, NULL); pkt[0] = makePkt(ptb, pta, &ipc, &ipl, 6, "test2a"); pkt[1] = makePkt(pta, pta, &ipc, &ipl, 6, "test2b"); udpRecv(pkt[0], &ipc, &ipl); udpRecv(pkt[1], &ipc, &ipl); read(UDP0, buffera, 6); read(UDP1, bufferb, 6); failif(0 != strncmp((char *)buffera, "test2a", 6) || (0 != strncmp((char *)bufferb, "test2b", 6)), ""); /* Test 3 */ testPrint(verbose, "Recv/read socket test 3"); control(UDP0, UDP_CTRL_BIND, ptb, (long)&ipc); control(UDP1, UDP_CTRL_BIND, ptb, NULL); pkt[0] = makePkt(ptb, pta, &ipc, &ipl, 6, "test3a"); pkt[1] = makePkt(ptb, pta, &ipd, &ipl, 6, "test3b"); udpRecv(pkt[0], &ipc, &ipl); udpRecv(pkt[1], &ipd, &ipl); read(UDP0, buffera, 6); read(UDP1, bufferb, 6); failif((0 != strncmp((char *)buffera, "test3a", 6)) || (0 != strncmp((char *)bufferb, "test3b", 6)), ""); /* Test 4 */ testPrint(verbose, "Recv/read socket test 4"); control(UDP0, UDP_CTRL_BIND, ptb, (long)&ipc); control(UDP1, UDP_CTRL_BIND, ptb, (long)&ipd); pkt[0] = makePkt(ptb, pta, &ipc, &ipl, 6, "test4a"); pkt[1] = makePkt(ptb, pta, &ipd, &ipl, 6, "test4b"); udpRecv(pkt[0], &ipc, &ipl); udpRecv(pkt[1], &ipd, &ipl); read(UDP0, buffera, 6); read(UDP1, bufferb, 6); failif((0 != strncmp((char *)buffera, "test4a", 6)) || (0 != strncmp((char *)bufferb, "test4b", 6)), ""); /* Test 5 */ testPrint(verbose, "Recv/read socket test 5"); control(UDP0, UDP_CTRL_BIND, 0, NULL); control(UDP1, UDP_CTRL_ACCEPT, ptb, (long)&ipl); control(UDP1, UDP_CTRL_BIND, 0, NULL); pkt[0] = makePkt(ptb, pta, &ipc, &ipl, 6, "test5a"); pkt[1] = makePkt(pta, ptb, &ipc, &ipl, 6, "test5b"); udpRecv(pkt[0], &ipc, &ipl); udpRecv(pkt[1], &ipc, &ipl); read(UDP0, buffera, 6); read(UDP1, bufferb, 6); failif((0 != strncmp((char *)buffera, "test5a", 6)) || (0 != strncmp((char *)bufferb, "test5b", 6)), ""); /* Read entire UDP packet */ testPrint(verbose, "Read entire UDP packet"); control(UDP0, UDP_CTRL_SETFLAG, UDP_FLAG_PASSIVE, NULL); pkt[0] = makePkt(ptb, pta, &ipc, &ipl, 7, "passive"); udpRecv(pkt[0], &ipc, &ipl); read(UDP0, bufferp, UDP_HDR_LEN + 7 + sizeof(struct udpPseudoHdr)); pseudo = (struct udpPseudoHdr *)bufferp; udppkt = (struct udpPkt *)(pseudo + 1); failif((0 != memcmp(pseudo->srcIp, ipc.addr, IPv4_ADDR_LEN)) || (0 != memcmp(pseudo->dstIp, ipl.addr, IPv4_ADDR_LEN)) || (udppkt->srcPort != ptb) || (udppkt->dstPort != pta) || (udppkt->len != UDP_HDR_LEN + 7) || (0 != strncmp((char *)udppkt->data, "passive", 7)), ""); /* Done testing, attempt to close all UDP devices (MAKE SURE BOTH * DEVICES ARE OPEN BEFORE YOU CLOSE THEM!!!) */ close(UDP0); close(UDP1); /* Print out the overall test's status (pass or fail) */ if (passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } #else /* UDP1 */ testSkip(TRUE, ""); #endif /* !UDP1 */ return OK; }
/** * Process an incoming IPv4 packet. * @param pkt pointer to the incoming packet * @return OK if packet was processed succesfully, otherwise SYSERR */ syscall ipv4Recv(struct packet *pkt) { struct ipv4Pkt *ip; struct netaddr dst; struct netaddr src; ushort iplen; /* Error check pointers */ if (NULL == pkt) { return SYSERR; } /* Setup pointer to IPv4 header */ pkt->nethdr = pkt->curr; ip = (struct ipv4Pkt *)pkt->curr; /* Verify the IP packet is valid */ if (FALSE == ipv4RecvValid(ip)) { IPv4_TRACE("Invalid packet"); netFreebuf(pkt); return SYSERR; } /* Obtain destination and source IP addresses */ dst.type = NETADDR_IPv4; dst.len = IPv4_ADDR_LEN; memcpy(dst.addr, ip->dst, dst.len); src.type = NETADDR_IPv4; src.len = IPv4_ADDR_LEN; memcpy(src.addr, ip->src, src.len); /* If packet is not destined for one of our network interfaces, * then attempt to route the packet */ if (FALSE == ipv4RecvDemux(&dst)) { IPv4_TRACE("Packet sent to routing subsystem"); #if NETEMU /* Run the packet through the network emulator if enabled */ return netemu(pkt); #else return rtRecv(pkt); #endif } /* Check if packet is fragmented */ if ((IPv4_FLAG_MF & net2hs(ip->flags_froff)) || (0 != (net2hs(ip->flags_froff) & IPv4_FROFF))) { // TODO: Handle fragmenting of packet // TODO: Should send icmp time exceeded // return ipRecvSendFrag(pkt, &dst); IPv4_TRACE("Packet fragmented"); netFreebuf(pkt); return SYSERR; } /* The Ethernet driver pads packets less than 60 bytes in length. * If the packet length returned from the Ethernet driver (pkt->len) * does not agree with the packet headers, adjust the packet length * to remove padding. */ iplen = net2hs(ip->len); if ((pkt->len - pkt->nif->linkhdrlen) > iplen) { pkt->len = pkt->nif->linkhdrlen + iplen; } /* Move current pointer to application level header */ pkt->curr += ((ip->ver_ihl & IPv4_IHL) << 2); IPv4_TRACE("IPv4 proto %d", ip->proto); /* Switch on packet protocol */ switch (ip->proto) { /* ICMP Packet */ case IPv4_PROTO_ICMP: icmpRecv(pkt); break; /* UDP Packet */ case IPv4_PROTO_UDP: #if NUDP udpRecv(pkt, &src, &dst); #endif /* NUDP */ break; /* TCP Packet */ case IPv4_PROTO_TCP: #if NTCP tcpRecv(pkt, &src, &dst); #endif /* NTCP */ break; /* Unknown IP packet protocol */ default: #if NRAW rawRecv(pkt, &src, &dst, ip->proto); #endif /* NRAW */ break; } return OK; }