thread test_ip(bool verbose) { #if NETHER struct netaddr dst; struct netaddr src; struct netaddr mask; struct netif *netptr; struct pcap_file_header pcap; struct pcap_pkthdr phdr; struct packet *pktA; struct packet *pktB; uchar *data; uchar buf[500]; int i; int nproc; int wait; bool passed = TRUE; src.type = NETADDR_IPv4; src.len = IPv4_ADDR_LEN; dst.type = NETADDR_IPv4; dst.len = IPv4_ADDR_LEN; mask.type = NETADDR_IPv4; mask.len = IPv4_ADDR_LEN; src.addr[0] = 192; src.addr[1] = 168; src.addr[2] = 1; src.addr[3] = 6; dst.addr[0] = 192; dst.addr[1] = 168; dst.addr[2] = 1; dst.addr[3] = 1; mask.addr[0] = 255; mask.addr[1] = 255; mask.addr[2] = 255; mask.addr[3] = 0; testPrint(verbose, "Initialization"); sleep(500); if (SYSERR == open(ELOOP)) { failif(TRUE, "Open returned SYSERR"); } else { if (SYSERR == netUp(ELOOP, &src, &mask, &dst)) { failif(TRUE, "netUp returned SYSERR"); } else { netptr = NULL; for (i = 0; i < NNETIF; i++) { if (ELOOP == netiftab[i].dev) { netptr = &netiftab[i]; break; } } pktA = netGetbuf(); pktB = netGetbuf(); failif(((NULL == netptr) || (SYSERR == (int)pktA) || (SYSERR == (int)pktB)), "Buffer allocation failed"); } } if (!passed) { testFail(TRUE, ""); return OK; } data = (uchar *)(&_binary_data_testip_pcap_start); memcpy(&pcap, data, sizeof(pcap)); data += sizeof(pcap); testPrint(verbose, "Ipv4Send"); /* Get 1st Packet */ memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(10); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Get 2nd Packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } memcpy(pktA->data, data, phdr.caplen); pktA->len = phdr.caplen; pktA->nif = netptr; pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; pktB->curr -= UDP_HDR_LEN + 4; pktB->len += UDP_HDR_LEN + 4; memcpy(pktB->curr, pktA->curr, pktB->len); control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); if (OK != ipv4Send(pktB, &src, &dst, IPv4_PROTO_UDP)) { failif(TRUE, "ipv4Send didn't return okay"); } else { control(ELOOP, ELOOP_CTRL_GETHOLD, (long)buf, 500); failif(0 != memcmp(buf, pktA->linkhdr, pktA->len), ""); } } /* ipv4Recv Testing */ //TODO: Finish ipv4Recv /* testPrint(verbose, "ipv4Recv"); pktA->curr -= IPv4_HDR_LEN; if (SYSERR == rawOpen(RAW0, IPv4_PROTO_UDP, )) { failif(TRUE, "Open returned SYSERR"); } if (OK != ipv4Recv(pktA)) { failif(TRUE, "Didn't return okay"); } else { } */ netDown(ELOOP); close(ELOOP); /* always print out the overall tests status */ if (passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } #else /* NETHER */ testSkip(TRUE, ""); #endif /* NETHER == 0 */ return OK; }
/** * Test for snoop. */ thread test_snoop(bool verbose) { bool passed = TRUE; struct snoop cap; struct netaddr dst; struct netaddr src; struct netaddr mask; struct netif *netptr; struct pcap_file_header pcap; struct pcap_pkthdr phdr; struct packet *pktA; struct packet *pktB; uchar *data; int i; uint nmatch; src.len = IPv4_ADDR_LEN; src.type = NETADDR_IPv4; dst.len = IPv4_ADDR_LEN; dst.type = NETADDR_IPv4; mask.len = IPv4_ADDR_LEN; mask.type = NETADDR_IPv4; src.addr[0] = 192; src.addr[1] = 168; src.addr[2] = 1; src.addr[3] = 6; dst.addr[0] = 192; dst.addr[1] = 168; dst.addr[2] = 1; dst.addr[3] = 1; /* Initialization */ testPrint(verbose, "Test case initialization"); pktA = netGetbuf(); failif((SYSERR == (int)pktA), "Failed get buffer"); if (!passed) { testFail(TRUE, ""); return OK; } /* Test filter */ /* Filter type */ testPrint(verbose, "Filter type"); bzero(&cap, sizeof(struct snoop)); cap.caplen = USHRT_MAX; cap.type = SNOOP_FILTER_ARP; failif((7 != filterTest(&cap, pktA)), ""); /* Test open */ testPrint(verbose, "Open capture (bad params)"); bzero(&cap, sizeof(struct snoop)); failif((SYSERR != snoopOpen(NULL, NULL)), ""); testPrint(verbose, "Open capture (bad device)"); failif((SYSERR != snoopOpen(&cap, "crap")), ""); testPrint(verbose, "Open capture all (no netif)"); failif((SYSERR != snoopOpen(&cap, "ALL")), ""); src.addr[0] = 192; src.addr[1] = 168; src.addr[2] = 1; src.addr[3] = 6; dst.addr[0] = 192; dst.addr[1] = 168; dst.addr[2] = 1; dst.addr[3] = 1; mask.addr[0] = 192; mask.addr[1] = 168; mask.addr[2] = 1; mask.addr[3] = 1; open(ELOOP); netUp(ELOOP, &src, &dst, &mask); testPrint(verbose, "Open capture all"); if (SYSERR == snoopOpen(&cap, "ALL")) { failif(TRUE, "Returned SYSERR"); } else { for (i = 0; i < NNETIF; i++) { if ((NET_ALLOC == netiftab[i].state) && (NULL == netiftab[i].capture)) { break; } } failif((i < NNETIF), "Not attached to all"); } testPrint(verbose, "Close capture (bad params)"); failif((SYSERR != snoopClose(NULL)), ""); testPrint(verbose, "Close capture"); if (SYSERR == snoopClose(&cap)) { failif(TRUE, "Returned SYSERR"); } else { for (i = 0; i < NNETIF; i++) { if (&cap == netiftab[i].capture) { break; } } failif((i < NNETIF), "Not removed from all"); } testPrint(verbose, "Open capture on ELOOP"); bzero(&cap, sizeof(struct snoop)); netptr = NULL; if (SYSERR == snoopOpen(&cap, "ELOOP")) { failif(TRUE, "Returned SYSERR"); } else { for (i = 0; i < NNETIF; i++) { if (ELOOP == netiftab[i].dev) { netptr = &netiftab[i]; break; } } failif(((NULL == netptr) || (&cap != netptr->capture)), "Not attached to ELOOP"); } testPrint(verbose, "Capture (bad params)"); failif((SYSERR != snoopCapture(NULL, NULL)), ""); /* Reset data stream to beginning of PCAP file */ data = (uchar *)(&_binary_data_testsnoop_pcap_start); memcpy(&pcap, data, sizeof(pcap)); data += sizeof(pcap); memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } testPrint(verbose, "Capture no match"); memcpy(pktA->data, data, phdr.caplen); pktA->len = phdr.caplen; pktA->nif = netptr; pktA->curr = pktA->data; cap.caplen = USHRT_MAX; cap.type = SNOOP_FILTER_IPv4; failif(((SYSERR == snoopCapture(&cap, pktA)) || (0 != cap.nmatch) || (mailboxCount(cap.queue) > 0)), ""); testPrint(verbose, "Capture match"); cap.type = SNOOP_FILTER_ALL; nmatch = cap.nmatch; if (SYSERR == snoopCapture(&cap, pktA)) { failif(TRUE, "Returned SYSERR"); } else if (1 != cap.nmatch) { failif(TRUE, "Packet did not match"); } else if (mailboxCount(cap.queue) != 1) { failif(TRUE, "Packet not enqueued"); } else { pktB = (struct packet *)mailboxReceive(cap.queue); failif((0 != memcmp(pktB->data, pktA->data, phdr.caplen)), "Dequeued packet doesn't match"); } testPrint(verbose, "Capture overrun"); cap.type = SNOOP_FILTER_ALL; for (i = 0; i < SNOOP_QLEN; i++) { if (SYSERR == snoopCapture(&cap, pktA)) { break; } } if (i < SNOOP_QLEN) { failif(TRUE, "Returned SYSERR"); } else { failif(((SYSERR != snoopCapture(&cap, pktA)) || (1 != cap.novrn)), "Packet did not overrun"); } testPrint(verbose, "Close capture"); failif((SYSERR == snoopClose(&cap)), "Returned SYSERR"); /* TODO: RESUME HERE */ netDown(ELOOP); close(ELOOP); /* always print out the overall tests status */ if (passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } return OK; }
/** * Shell command (netup) to start a network interface. * @param nargs number of arguments in args array * @param args array of arguments * @return OK for success, SYSERR for syntax error */ shellcmd xsh_netup(int nargs, char *args[]) { int descrp; struct netaddr ip; struct netaddr mask; struct netaddr gateway; char *str_ip, *str_mask, *str_gateway; char nvramLookup[DEVMAXNAME + NVRAM_STRMAX]; /* Enable interrupts */ enable(); /* Help */ if ((2 == nargs) && (0 == strncmp(args[1], "--help", 7))) { usage(args[0]); return SHELL_OK; } /* Parse device */ if (nargs > 1) { descrp = getdev(args[1]); if (SYSERR == descrp) { fprintf(stderr, "%s is not a valid device.\n", args[1]); return SHELL_ERROR; } } else { /* assume first ethernet interface */ descrp = (ethertab[0].dev)->num; } if (5 == nargs) { /* grab string data */ str_ip = args[2]; str_mask = args[3]; str_gateway = args[4]; } else if (nargs < 3) { /* lookup information in nvram */ bzero(nvramLookup, DEVMAXNAME + NVRAM_STRMAX); sprintf(nvramLookup, "%s_%s", (ethertab[0].dev)->name, NET_LAN_IPADDR); #if NVRAM str_ip = nvramGet(nvramLookup); if (NULL == str_ip) { str_ip = nvramGet("lan_ipaddr"); } #else str_ip = NULL; #endif /* NVRAM */ bzero(nvramLookup, DEVMAXNAME + NVRAM_STRMAX); sprintf(nvramLookup, "%s_%s", (ethertab[0].dev)->name, NET_SUBNET_MASK); #if NVRAM str_mask = nvramGet(nvramLookup); if (NULL == str_mask) { str_mask = nvramGet("lan_netmask"); } #else str_mask = NULL; #endif /* NVRAM */ #if NVRAM str_gateway = nvramGet(NET_GATEWAY); if (NULL == str_gateway) { str_gateway = nvramGet("lan_gateway"); } #else str_gateway = NULL; #endif /* NVRAM */ } else { fprintf(stderr, "Invalid number of arguments\n"); return SHELL_ERROR; } /* Make sure we have valid IPv4 style parameters */ if (NULL == str_ip) { str_ip = "0.0.0.0"; } if (NULL == str_mask) { str_mask = "0.0.0.0"; } if (NULL == str_gateway) { str_gateway = "0.0.0.0"; } /* Parse IP */ if (SYSERR == dot2ipv4(str_ip, &ip)) { fprintf(stderr, "%s is not a valid IPv4 address.\n", str_ip); return SHELL_ERROR; } /* Parse Mask */ if (SYSERR == dot2ipv4(str_mask, &mask)) { fprintf(stderr, "%s is not a valid IPv4 address mask.\n", str_mask); return SHELL_ERROR; } /* Parse Gateway */ if (SYSERR == dot2ipv4(str_gateway, &gateway)) { fprintf(stderr, "%s is not a valid IPv4 address.\n", str_gateway); return SHELL_ERROR; } if (SYSERR == netUp(descrp, &ip, &mask, &gateway)) { fprintf(stderr, "Failed to start network interface on %s\n", args[1]); return SHELL_ERROR; } printf("%s is %s with netmask %s (gateway: %s)\n", devtab[descrp].name, str_ip, str_mask, str_gateway); return SHELL_OK; }
/** * Tests raw sockets. * @return OK when testing is complete */ thread test_raw(bool verbose) { #if RAW0 /* the failif macro depends on 'passed' and 'verbose' vars */ bool passed = TRUE; device *devptr; struct raw *rawptr; struct netif *netptr; struct netaddr lip; struct netaddr rip; struct netaddr mask; struct packet *pkt; struct packet *pktA; struct pcap_pkthdr phdr; struct pcap_file_header pcap; uchar *data; uchar buf[500]; int nproc; int wait; int i; lip.type = NETADDR_IPv4; lip.len = IPv4_ADDR_LEN; lip.addr[0] = 192; lip.addr[1] = 168; lip.addr[2] = 1; lip.addr[3] = 6; rip.type = NETADDR_IPv4; rip.len = IPv4_ADDR_LEN; rip.addr[0] = 192; rip.addr[1] = 168; rip.addr[2] = 1; rip.addr[3] = 1; 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; /* Initialization */ testPrint(verbose, "Test case initialization"); data = (uchar *)(&_binary_data_testraw_pcap_start); memcpy(&pcap, data, sizeof(pcap)); data += sizeof(pcap); if (SYSERR == open(ELOOP)) { failif(TRUE, ""); } else { if (SYSERR == netUp(ELOOP, &lip, &mask, NULL)) { close(ELOOP); failif(TRUE, ""); } else { netptr = NULL; for (i = 0; i < NNETIF; i++) { if (ELOOP == netiftab[i].dev) { netptr = &netiftab[i]; break; } } pkt = netGetbuf(); failif(((NULL == netptr) || (SYSERR == (int)pkt)), ""); } } if (!passed) { testFail(TRUE, ""); return OK; } /* Test Open */ testPrint(verbose, "Open RAW (Proto Only)"); rawptr = NULL; if (SYSERR == open(RAW0, NULL, NULL, IPv4_PROTO_ICMP)) { failif(TRUE, "Returned SYSERR"); } else { devptr = (device *)&devtab[RAW0]; rawptr = &rawtab[devptr->minor]; failif(((rawptr->state != RAW_ALLOC) || (rawptr->dev != devptr) || (rawptr->proto != IPv4_PROTO_ICMP) || (rawptr->localip.type != NULL) || (rawptr->remoteip.type != NULL) || (rawptr->icount != 0) || (rawptr->istart != 0) || (semcount(rawptr->isema) != 0) || (rawptr->flags != 0)), "Incorrect control block"); } testPrint(verbose, "Open RAW (Already Open)"); failif((SYSERR != open(RAW0, NULL, NULL, IPv4_PROTO_ICMP)), "Double open() succeeded"); /* Test Control */ testPrint(verbose, "Control (Closed Socket)"); failif((control(RAW1, RAW_CTRL_SETFLAG, NULL, NULL) != SYSERR), ""); testPrint(verbose, "Control (Bad Params)"); failif((control(RAW0, -1, NULL, NULL) != SYSERR), ""); testPrint(verbose, "Control (Set Flag)"); failif(((NULL != control(RAW0, RAW_CTRL_SETFLAG, (RAW_IACCEPT | RAW_IHDR), NULL)) || (0 == (rawptr->flags & RAW_IACCEPT)) || (0 == (rawptr->flags & RAW_IHDR))), ""); testPrint(verbose, "Control (Clear Flag)"); failif(((RAW_IHDR != control(RAW0, RAW_CTRL_CLRFLAG, RAW_IHDR, NULL)) || (0 == (rawptr->flags & RAW_IACCEPT)) || (1 == (rawptr->flags & RAW_IHDR))), ""); /* Test Close */ testPrint(verbose, "Close RAW"); if (SYSERR == close(RAW0)) { failif(TRUE, "Returned SYSERR"); } else { devptr = (device *)&devtab[RAW0]; rawptr = &rawtab[devptr->minor]; failif(((rawptr->state != RAW_FREE) || (rawptr->dev != NULL)), "Control block not clear"); } testPrint(verbose, "Close RAW (Already Closed)"); failif((SYSERR != close(RAW0)), "Did not SYSERR"); /* Test demux */ testPrint(verbose, "Demulitplexing (No sockets)"); failif((NULL != rawDemux(&rip, &lip, IPv4_PROTO_ICMP)), ""); testPrint(verbose, "Demulitplexing (All Protos)"); if ((SYSERR == open(RAW0, &lip, &rip, IPv4_PROTO_IGMP)) || (SYSERR == open(RAW1, NULL, NULL, NULL))) { failif(TRUE, "Open failed"); } else { devptr = (device *)&devtab[RAW1]; rawptr = &rawtab[devptr->minor]; if (rawptr != rawDemux(&rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Incorrect socket"); } else { failif(((SYSERR == close(RAW0)) || (SYSERR == close(RAW1))), "Close failed"); } } testPrint(verbose, "Demulitplexing (Proto)"); if ((SYSERR == open(RAW0, NULL, NULL, IPv4_PROTO_ICMP)) || (SYSERR == open(RAW1, NULL, NULL, IPv4_PROTO_IGMP))) { failif(TRUE, "Open failed"); } else { devptr = (device *)&devtab[RAW0]; rawptr = &rawtab[devptr->minor]; if (rawptr != rawDemux(&rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Incorrect socket"); } else { failif(((SYSERR == close(RAW0)) || (SYSERR == close(RAW1))), "Close failed"); } } testPrint(verbose, "Demulitplexing (Remote IP)"); if ((SYSERR == open(RAW0, NULL, NULL, IPv4_PROTO_ICMP)) || (SYSERR == open(RAW1, NULL, &rip, IPv4_PROTO_ICMP))) { failif(TRUE, "Open failed"); } else { devptr = (device *)&devtab[RAW1]; rawptr = &rawtab[devptr->minor]; if (rawptr != rawDemux(&rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Incorrect socket"); } else { failif(((SYSERR == close(RAW0)) || (SYSERR == close(RAW1))), "Close failed"); } } testPrint(verbose, "Demulitplexing (Local IP)"); if ((SYSERR == open(RAW0, NULL, &rip, IPv4_PROTO_ICMP)) || (SYSERR == open(RAW1, &lip, &rip, IPv4_PROTO_ICMP))) { failif(TRUE, "Open failed"); } else { devptr = (device *)&devtab[RAW1]; rawptr = &rawtab[devptr->minor]; if (rawptr != rawDemux(&rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Incorrect socket"); } else { failif(((SYSERR == close(RAW0)) || (SYSERR == close(RAW1))), "Close failed"); } } /* Test Open */ testPrint(verbose, "Open RAW (Full Spec)"); if (SYSERR == open(RAW0, &lip, &rip, IPv4_PROTO_ICMP)) { failif(TRUE, "Returned SYSERR"); } else { devptr = (device *)&devtab[RAW0]; rawptr = &rawtab[devptr->minor]; failif(((rawptr->state != RAW_ALLOC) || (rawptr->dev != devptr) || (rawptr->proto != IPv4_PROTO_ICMP) || (FALSE == netaddrequal(&lip, &rawptr->localip)) || (FALSE == netaddrequal(&rip, &rawptr->remoteip)) || (rawptr->icount != 0) || (rawptr->istart != 0) || (semcount(rawptr->isema) != 0) || (rawptr->flags != 0)), "Incorrect control block"); } /* Test receive */ testPrint(verbose, "Receive (Bad Params)"); /* Get 1st packet */ memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } pkt->len = phdr.caplen; memcpy(pkt->data, data, phdr.caplen); pkt->linkhdr = pkt->data; pkt->nethdr = pkt->linkhdr + ETH_HDR_LEN; pkt->curr = pkt->nethdr + IPv4_HDR_LEN; failif(((SYSERR != rawRecv(NULL, NULL, NULL, NULL)) || (SYSERR != rawRecv(pkt, &rip, NULL, NULL))), ""); testPrint(verbose, "Receive (No Match)"); pktA = netGetbuf(); memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; if (SYSERR == rawRecv(pktA, &rip, &lip, IPv4_PROTO_IGMP)) { failif(TRUE, "Returned SYSERR"); } else { failif(((rawptr->icount != 0) || (semcount(rawptr->isema) != 0) || (TRUE == netaddrequal(&rawptr->src[0], &rip)) || (rawptr->in[0] == pktA)), "Packet enqueued"); } testPrint(verbose, "Receive (One Pkt)"); pktA = netGetbuf(); memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; if (SYSERR == rawRecv(pktA, &rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Returned SYSERR"); } else { failif(((rawptr->istart != 0) || (rawptr->icount != 1) || (semcount(rawptr->isema) != 1) || (FALSE == netaddrequal(&rawptr->src[0], &rip)) || (rawptr->in[0] != pktA)), "Incorrectly enqueued"); } testPrint(verbose, "Read (Closed socket)"); failif((SYSERR != read(RAW1, buf, 500)), ""); testPrint(verbose, "Read (One Pkt)"); failif(((read(RAW0, buf, 500) != 8) || (memcmp(buf, (pkt->data + ETH_HDR_LEN + IPv4_HDR_LEN), 8) != 0) || (rawptr->icount != 0) || (rawptr->istart != 1) || (semcount(rawptr->isema) != 0) || (rawptr->in[0] != NULL)), ""); testPrint(verbose, "Read (Include header)"); pktA = netGetbuf(); memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; rawptr->flags = RAW_IHDR; if (SYSERR == rawRecv(pktA, &rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Recv returned SYSERR"); } else { failif(((read(RAW0, buf, 500) != (IPv4_HDR_LEN + 8)) || (memcmp(buf, (pkt->data + ETH_HDR_LEN), IPv4_HDR_LEN + 8) != 0) || (rawptr->icount != 0) || (rawptr->istart != 2) || (semcount(rawptr->isema) != 0) || (rawptr->in[0] != NULL)), ""); } testPrint(verbose, "Read (Accept)"); pktA = netGetbuf(); memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; rawptr->flags = RAW_IACCEPT; rawptr->remoteip.type = NULL; if (SYSERR == rawRecv(pktA, &rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Recv returned SYSERR"); } else { failif(((read(RAW0, buf, 500) != 8) || (FALSE == netaddrequal(&rawptr->remoteip, &rip))), ""); } testPrint(verbose, "Read (Small buf)"); pktA = netGetbuf(); memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; if (SYSERR == rawRecv(pktA, &rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Recv returned SYSERR"); } else { failif(((read(RAW0, buf, 2) != 2) || (memcmp(buf, (pkt->data + ETH_HDR_LEN + IPv4_HDR_LEN), 2) != 0)), ""); } testPrint(verbose, "Receive (Full buf)"); for (i = 0; i < RAW_IBLEN; i++) { memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; if (SYSERR == rawRecv(pktA, &rip, &lip, IPv4_PROTO_ICMP)) { break; } } if (i < RAW_IBLEN) { failif(TRUE, "Unable to fill buffer"); } else { memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; failif((SYSERR != rawRecv(pktA, &rip, &lip, IPv4_PROTO_ICMP)), "Did not return SYSERR"); } testPrint(verbose, "Close RAW"); failif((SYSERR == close(RAW0)), ""); /* Test Write/Send */ testPrint(verbose, "Open RAW"); if (SYSERR == open(RAW0, &lip, NULL, IPv4_PROTO_ICMP)) { failif(TRUE, "Returned SYSERR"); } else { devptr = (device *)&devtab[RAW0]; rawptr = &rawtab[devptr->minor]; failif(FALSE, ""); } testPrint(verbose, "Send (Bad Params)"); failif((rawSend(NULL, NULL, 0) != SYSERR), ""); testPrint(verbose, "Send (Incomplete Spec)"); failif((rawSend(rawptr, pkt->curr, 8) != SYSERR), ""); testPrint(verbose, "Send (Incomplete Spec Hdr Inc)"); rawptr->flags = RAW_OHDR; failif((rawSend(rawptr, pkt->curr, 8) != SYSERR), ""); testPrint(verbose, "Send (Net Hdr Included)"); /* Add ARP entry */ /* Get 2nd Packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Get 3rd Packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } memcpy(pkt->data, data, phdr.caplen); pkt->len = phdr.caplen; pkt->linkhdr = pkt->data; pkt->nethdr = pkt->linkhdr + ETH_HDR_LEN; pkt->curr = pkt->nethdr + IPv4_HDR_LEN; /* Wait for ARP entry to be added */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(10); } if (MAX_WAIT == wait) { failif(MAX_WAIT, "ARP entry failed"); } else { netaddrcpy(&rawptr->remoteip, &rip); control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); if (SYSERR == rawSend(rawptr, pkt->nethdr, IPv4_HDR_LEN + 8)) { failif(TRUE, "Returned SYSERR"); } else { control(ELOOP, ELOOP_CTRL_GETHOLD, (long)buf, 500); failif((memcmp(pkt->data, buf, pkt->len) != 0), "Incorrect Packet"); } } testPrint(verbose, "Send"); rawptr->flags = NULL; netaddrcpy(&rawptr->remoteip, &rip); control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); if (SYSERR == rawSend(rawptr, pkt->curr, 8)) { failif(TRUE, "Returned SYSERR"); } else { control(ELOOP, ELOOP_CTRL_GETHOLD, (long)buf, 500); failif((memcmp(pkt->data, buf, pkt->len) != 0), "Incorrect Packet"); } testPrint(verbose, "Write"); control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); if (SYSERR == write(RAW0, pkt->curr, 8)) { failif(TRUE, "Returned SYSERR"); } else { control(ELOOP, ELOOP_CTRL_GETHOLD, (long)buf, 500); failif((memcmp(pkt->data, buf, pkt->len) != 0), "Incorrect Packet"); } close(RAW0); netDown(ELOOP); close(ELOOP); /* always print out the overall tests status */ if (passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } #endif /* RAW0 */ return OK; }
/** * Tests ARP. * @return OK when testing is complete */ thread test_arp(bool verbose) { bool passed = TRUE; int i = 0; struct netaddr ip; struct netaddr mask; struct netaddr praddr; struct netaddr hwaddr; struct netaddr addrbuf; struct pcap_file_header pcap; struct pcap_pkthdr phdr; struct packet *pkt; struct netif *netptr; struct ethloop *pelp; uchar *data; uchar *request; struct arpPkt *arp; struct arpEntry *entry; uchar buf[ELOOP_BUFSIZE]; int nproc; int nout; int wait; tid_typ tids[ARP_NTHRWAIT]; tid_typ tid; irqmask im; enable(); ip.type = NETADDR_IPv4; ip.len = IPv4_ADDR_LEN; ip.addr[0] = 192; ip.addr[1] = 168; ip.addr[2] = 1; ip.addr[3] = 6; 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; /* Initialize loopback ethernet and network interface */ testPrint(verbose, "Test case initialization"); data = (uchar *)(&_binary_data_testarp_pcap_start); memcpy(&pcap, data, sizeof(pcap)); data += sizeof(pcap); if (SYSERR == open(ELOOP)) { failif(TRUE, ""); } else { failif((SYSERR == netUp(ELOOP, &ip, &mask, NULL)), ""); } if (!passed) { testFail(TRUE, ""); return OK; } /* Setup pointers to underlying structures */ #if NNETIF for (i = 0; i < NNETIF; i++) { if ((NET_ALLOC == netiftab[i].state) && (ELOOP == netiftab[i].dev)) { break; } } #endif netptr = &netiftab[i]; pelp = &elooptab[devtab[ELOOP].minor]; pkt = netGetbuf(); if ((int)pkt != SYSERR) { pkt->nif = netptr; } praddr.type = NETADDR_IPv4; praddr.len = IPv4_ADDR_LEN; praddr.addr[0] = 192; praddr.addr[1] = 168; praddr.addr[2] = 1; praddr.addr[3] = 3; hwaddr.type = NETADDR_ETHERNET; hwaddr.len = ETH_ADDR_LEN; hwaddr.addr[0] = 0xAA; hwaddr.addr[1] = 0xBB; hwaddr.addr[2] = 0xCC; hwaddr.addr[3] = 0xDD; hwaddr.addr[4] = 0xEE; hwaddr.addr[5] = 0xFF; /* Test arpPkt structure */ testPrint(verbose, "Header structure (Request)"); /* Get 1st packet */ memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } pkt = netGetbuf(); pkt->len += ARP_CONST_HDR_LEN + (2 * IPv4_ADDR_LEN) + (2 * ETH_ADDR_LEN); pkt->curr -= pkt->len; arp = (struct arpPkt *)pkt->curr; arp->hwtype = hs2net(ARP_HWTYPE_ETHERNET); arp->prtype = hs2net(ARP_PRTYPE_IPv4); arp->hwalen = ETH_ADDR_LEN; arp->pralen = IPv4_ADDR_LEN; arp->op = hs2net(ARP_OP_RQST); memcpy(&arp->addrs[ARP_ADDR_SHA(arp)], netptr->hwaddr.addr, arp->hwalen); memcpy(&arp->addrs[ARP_ADDR_SPA(arp)], netptr->ip.addr, arp->pralen); memcpy(&arp->addrs[ARP_ADDR_DPA(arp)], praddr.addr, arp->pralen); failif((0 != memcmp(data + ELOOP_LINKHDRSIZE, arp, pkt->len)), ""); /* Test arpPkt structure */ testPrint(verbose, "Header structure (Reply)"); /* Get 2nd packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } arp->op = hs2net(ARP_OP_REPLY); memcpy(&arp->addrs[ARP_ADDR_DHA(arp)], &arp->addrs[ARP_ADDR_SHA(arp)], arp->hwalen); arp->addrs[ARP_ADDR_DHA(arp) + ETH_ADDR_LEN - 1] = 0xCC; memcpy(&arp->addrs[ARP_ADDR_DPA(arp)], praddr.addr, arp->pralen); memcpy(&arp->addrs[ARP_ADDR_SHA(arp)], netptr->hwaddr.addr, arp->hwalen); memcpy(&arp->addrs[ARP_ADDR_SPA(arp)], netptr->ip.addr, arp->pralen); failif((0 != memcmp(data + ELOOP_LINKHDRSIZE, arp, pkt->len)), ""); /* Test arpAlloc, free entry exists */ testPrint(verbose, "Allocate free entry"); /* Make first entry used */ arptab[0].state = ARP_USED; arptab[0].expires = clktime + ARP_TTL_UNRESOLVED; entry = arpAlloc(); failif(((NULL == entry) || (entry == &arptab[0]) || (0 == (entry->state & ARP_USED))), ""); /* Test arpAlloc, free entry exists */ testPrint(verbose, "Allocate used entry"); arptab[1].state = ARP_USED; arptab[1].expires = clktime + 1; /* Make all entries (except the first 2) have ARP_TTL_RESOLVED */ for (i = 2; i < ARP_NENTRY; i++) { arptab[i].state = ARP_USED; arptab[i].expires = clktime + ARP_TTL_RESOLVED; } entry = arpAlloc(); failif(((NULL == entry) || (entry != &arptab[1]) || (0 == (entry->state & ARP_USED))), ""); /* Test arpNotify */ testPrint(verbose, "Notify waiting threads (bad params)"); failif((SYSERR != arpNotify(NULL, TIMEOUT)), ""); /* Test arpNotify */ testPrint(verbose, "Notify waiting threads"); entry = &arptab[0]; entry->state = ARP_UNRESOLVED; for (i = 0; i < ARP_NTHRWAIT; i++) { tid = create((void *)notifyTest, INITSTK, INITPRIO, "notifyTest", 0); tids[i] = tid; entry->waiting[i] = tid; entry->count++; ready(tid, RESCHED_NO); } recvclr(); arpNotify(entry, ARP_MSG_RESOLVED); nout = FALSE; nproc = 0; tid = recvtime(100); while ((tid != TIMEOUT) && (nproc < ARP_NTHRWAIT)) { for (i = 0; i < ARP_NTHRWAIT; i++) { if (tid == tids[i]) { tids[i] = NULL; } } nproc++; tid = recvtime(100); } for (i = 0; i < ARP_NTHRWAIT; i++) { if (tids[i] != NULL) { kill(tids[i]); nout = TRUE; } } failif(nout || (entry->count != 0), ""); /* Test arpFree */ testPrint(verbose, "Free entry (bad params)"); failif((SYSERR != arpFree(NULL)), ""); /* Test arpFree */ testPrint(verbose, "Free resolved entry"); entry = &arptab[0]; entry->state = ARP_RESOLVED; entry->expires = clktime; failif(((SYSERR == arpFree(entry)) || (entry->expires != 0)), ""); /* Test arpFree */ testPrint(verbose, "Free unresolved entry"); entry = &arptab[0]; entry->state = ARP_UNRESOLVED; for (i = 0; i < ARP_NTHRWAIT; i++) { tid = create((void *)freeTest, INITSTK, INITPRIO, "freeTest", 0); tids[i] = tid; entry->waiting[i] = tid; entry->count++; ready(tid, RESCHED_NO); } recvclr(); if (SYSERR == arpFree(entry)) { failif(TRUE, "Returned SYSERR"); } else { nout = FALSE; nproc = 0; tid = recvtime(100); while ((tid != TIMEOUT) && (nproc < ARP_NTHRWAIT)) { for (i = 0; i < ARP_NTHRWAIT; i++) { if (tid == tids[i]) { tids[i] = NULL; } } nproc++; tid = recvtime(100); } for (i = 0; i < ARP_NTHRWAIT; i++) { if (tids[i] != NULL) { kill(tids[i]); nout = TRUE; } } failif(nout || (entry->count != 0), ""); } /* Test arpGetEntry */ testPrint(verbose, "Get entry"); for (i = 0; i < ARP_NENTRY; i++) { arpFree(&arptab[i]); } nout = 4; if (ARP_NENTRY < nout) { nout = ARP_NENTRY; } for (i = 1; i < nout; i++) { entry = &arptab[i]; entry->state = ARP_RESOLVED; entry->nif = netptr; praddr.addr[3] = i + 1; hwaddr.addr[5] = ((i + 0xA) << 4) + (i + 0xA); netaddrcpy(&entry->hwaddr, &hwaddr); netaddrcpy(&entry->praddr, &praddr); entry->expires = clktime + ARP_TTL_RESOLVED; } for (i = 1; i < nout; i++) { praddr.addr[3] = i + 1; entry = arpGetEntry(&praddr); if (entry != &arptab[i]) { break; } } failif((i != nout), ""); /* Test arpGetEntry with timeout */ testPrint(verbose, "Get entry (timeout entries)"); arptab[i].expires = clktime - 1; praddr.addr[3] = 2; entry = arpGetEntry(&praddr); if (entry != &arptab[1]) { failif(TRUE, "Incorrect entry"); } else { failif((arptab[0].state != ARP_FREE), "Did not free expired entry"); } for (i = 0; i < ARP_NENTRY; i++) { arpFree(&arptab[i]); } /* Test receive reply for non-existing ARP table entry */ testPrint(verbose, "Receive ARP reply, new entry"); /* Get 3rd packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 3; hwaddr.addr[5] = 0xCC; nout = pelp->nout; nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(10); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Check entry and ensure reply was not sent */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if (ARP_RESOLVED == arptab[i].state) { entry = &arptab[i]; break; } } if (NULL == entry) { failif(TRUE, "No entry inserted"); } else if ((FALSE == netaddrequal(&praddr, &entry->praddr)) || (FALSE == netaddrequal(&hwaddr, &entry->hwaddr)) || (entry->nif != netptr) || (entry->count != 0)) { failif(TRUE, "Entry incorrect"); } else if (pelp->nout > (nout + 1)) { failif(TRUE, "Reply sent to reply"); } else { failif(FALSE, ""); } } /* Test receive request for non-existing ARP table entry */ testPrint(verbose, "Receive ARP request, new entry"); /* Get 4th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 1; hwaddr.addr[5] = 0xAA; nout = pelp->nout; nproc = netptr->nproc; im = disable(); write(ELOOP, data, phdr.caplen); control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); restore(im); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Check entry and ensure reply was not sent */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } if (NULL == entry) { failif(TRUE, "No entry inserted"); } else if ((FALSE == netaddrequal(&praddr, &entry->praddr)) || (FALSE == netaddrequal(&hwaddr, &entry->hwaddr)) || (entry->nif != netptr) || (entry->count != 0)) { failif(TRUE, "Entry incorrect"); } else { control(ELOOP, ELOOP_CTRL_GETHOLD, (int)buf, ELOOP_BUFSIZE); /* Get 5th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } failif((memcmp(data, buf, phdr.caplen) != 0), "Invalid reply"); } } /* Test receive request for non-supported hardware type */ testPrint(verbose, "Receive ARP request, bad HW type"); /* Get 6th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 2; hwaddr.addr[5] = 0xBB; nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Ensure entry was not added */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } failif((entry != NULL), "Entry inserted"); } /* Test receive reply for non-supported protocol type */ testPrint(verbose, "Receive ARP reply, bad protocol type"); /* Get 7th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Ensure entry was not added */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } failif((entry != NULL), "Entry inserted"); } /* Test receive reply for existing resolved ARP table entry */ testPrint(verbose, "Receive ARP reply, resolved entry"); /* Get 8th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 3; hwaddr.addr[5] = 0x0C; nout = pelp->nout; nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Check entry */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } failif((FALSE == netaddrequal(&hwaddr, &entry->hwaddr)), "Entry incorrect"); } /* Test receive request not for me */ testPrint(verbose, "Receive ARP request, not mine"); /* Get 9th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 4; hwaddr.addr[5] = 0xDD; nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Ensure entry was not added */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } failif((entry != NULL), "Entry inserted"); } /* Test arpSendRequest */ testPrint(verbose, "Send ARP request (bad params)"); failif((SYSERR != arpSendRqst(NULL)), ""); /* Test arpSendRequest */ testPrint(verbose, "Send ARP request"); /* Get 10th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } entry = &arptab[0]; entry->state = ARP_UNRESOLVED; entry->nif = netptr; praddr.addr[3] = 2; hwaddr.addr[5] = 0xBB; netaddrcpy(&entry->hwaddr, &hwaddr); netaddrcpy(&entry->praddr, &praddr); entry->expires = clktime + ARP_TTL_UNRESOLVED; control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); if (SYSERR == arpSendRqst(entry)) { failif(TRUE, "Returned SYSERR"); } else { control(ELOOP, ELOOP_CTRL_GETHOLD, (int)buf, ELOOP_BUFSIZE); failif((memcmp(buf, data, phdr.caplen) != 0), ""); } /* Test arpLookup */ testPrint(verbose, "Lookup address (bad params)"); failif((SYSERR != arpLookup(NULL, NULL, NULL)), ""); /* Test arpLookup */ testPrint(verbose, "Lookup existing resolved address"); for (i = 0; i < ARP_NENTRY; i++) { arpFree(&arptab[i]); } entry = &arptab[0]; entry->state = ARP_RESOLVED; entry->nif = netptr; praddr.addr[3] = 1; hwaddr.addr[5] = 0xAA; netaddrcpy(&entry->hwaddr, &hwaddr); netaddrcpy(&entry->praddr, &praddr); entry->expires = clktime + ARP_TTL_UNRESOLVED; i = arpLookup(netptr, &praddr, &addrbuf); if ((SYSERR == i) || (TIMEOUT == i)) { failif(TRUE, "Returned SYSERR or TIMEOUT"); } else { failif((FALSE == netaddrequal(&addrbuf, &hwaddr)), "Wrong address"); } /* Test arpLookup */ testPrint(verbose, "Lookup existing unresolved address"); entry = &arptab[1]; entry->state = ARP_UNRESOLVED; entry->nif = netptr; praddr.addr[3] = 2; hwaddr.addr[5] = 0xBB; netaddrcpy(&entry->hwaddr, &hwaddr); netaddrcpy(&entry->praddr, &praddr); entry->expires = clktime + ARP_TTL_UNRESOLVED; control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); request = data; wait = phdr.caplen; /* Get 11th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } tid = ready(create ((void *)lookupTest, INITSTK, INITPRIO, "lookupTest", 4, request, wait, data, phdr.caplen), RESCHED_NO); i = arpLookup(netptr, &praddr, &addrbuf); if ((SYSERR == i) || (TIMEOUT == i)) { kill(tid); failif(TRUE, "Returned SYSERR or TIMEOUT"); } else { failif((FALSE == netaddrequal(&addrbuf, &hwaddr)), "Wrong address"); } /* Test arpLookup */ testPrint(verbose, "Lookup max threads wait for resolve"); entry->state = ARP_UNRESOLVED; entry->count = ARP_NTHRWAIT; failif((arpLookup(netptr, &praddr, &addrbuf) != SYSERR), ""); /* Test arpLookup */ testPrint(verbose, "Lookup non-existing unresolved addr"); praddr.addr[3] = 3; hwaddr.addr[5] = 0xCC; control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); request = data; wait = phdr.caplen; /* Get 12th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } request = data; wait = phdr.caplen; /* Get 13th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } tid = ready(create ((void *)lookupTest, INITSTK, INITPRIO, "lookupTest", 4, request, wait, data, phdr.caplen), RESCHED_NO); i = arpLookup(netptr, &praddr, &addrbuf); if ((SYSERR == i) || (TIMEOUT == i)) { kill(tid); failif(TRUE, "Returned SYSERR or TIMEOUT"); } else { failif((FALSE == netaddrequal(&addrbuf, &hwaddr)), "Wrong address"); } /* Test arpLookup */ testPrint(verbose, "Lookup timeout"); praddr.addr[3] = 4; hwaddr.addr[5] = 0xDD; control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_DROPALL, NULL); failif((SYSERR != arpLookup(netptr, &praddr, &addrbuf)), ""); /* Stop loopback ethernet and network interface */ testPrint(verbose, "Test case cleanup"); for (i = 0; i < ARP_NENTRY; i++) { arpFree(&arptab[i]); } failif(((SYSERR == netFreebuf(pkt)) || (SYSERR == netDown(ELOOP)) || (SYSERR == close(ELOOP))), ""); if (passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } return OK; }
/** * Tests the network interfaces. * @return OK when testing is complete */ thread test_netif(bool verbose) { bool passed = TRUE; int i = 0; struct netaddr ip; struct netaddr mask; struct netaddr gate; struct netaddr hw; struct netaddr brc; struct pcap_file_header pcap; struct pcap_pkthdr phdr; struct packet *pkt; struct netif *netptr; uchar *data; enable(); ip.type = NETADDR_IPv4; ip.len = IPv4_ADDR_LEN; ip.addr[0] = 192; ip.addr[1] = 168; ip.addr[2] = 1; ip.addr[3] = 6; 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; gate.type = NETADDR_IPv4; gate.len = IPv4_ADDR_LEN; gate.addr[0] = 192; gate.addr[1] = 168; gate.addr[2] = 1; gate.addr[3] = 1; brc.type = NETADDR_IPv4; brc.len = IPv4_ADDR_LEN; brc.addr[0] = 255; brc.addr[1] = 255; brc.addr[2] = 255; brc.addr[3] = 255; testPrint(verbose, "Open loopback ethernet device"); failif((SYSERR == open(ELOOP)), ""); testPrint(verbose, "Start network interface"); if (SYSERR == netUp(ELOOP, &ip, &mask, &gate)) { failif(TRUE, "Returned SYSERR"); } else { for (i = 0; i < NNETIF; i++) { if ((NET_ALLOC == netiftab[i].state) && (ELOOP == netiftab[i].dev)) { break; } } netptr = &netiftab[i]; if ((i >= NNETIF) || (netptr->state != NET_ALLOC) || (netptr->mtu != ELOOP_MTU) || (netptr->linkhdrlen != ELOOP_LINKHDRSIZE) || (FALSE == netaddrequal(&netptr->ip, &ip)) || (FALSE == netaddrequal(&netptr->mask, &mask)) || (FALSE == netaddrequal(&netptr->gateway, &gate))) { failif(TRUE, "Incorrect structure setup"); } else { for (i = 0; i < NET_NTHR; i++) { if (isbadtid(netptr->recvthr[i])) { failif(TRUE, "Bad recvthr"); break; } } if (NET_NTHR == i) { failif(FALSE, ""); } } } testPrint(verbose, "Stop network interface"); failif((SYSERR == netDown(ELOOP)), ""); testPrint(verbose, "Start network interface (no gateway)"); failif((SYSERR == netUp(ELOOP, &ip, &mask, NULL)), ""); for (i = 0; i < NNETIF; i++) { if ((NET_ALLOC == netiftab[i].state) && (ELOOP == netiftab[i].dev)) { break; } } /* Kill receiver threads */ netptr = &netiftab[i]; for (i = 0; i < NET_NTHR; i++) { kill(netptr->recvthr[i]); netptr->recvthr[i] = BADTID; } testPrint(verbose, "Get packet buffer"); pkt = netGetbuf(); failif((SYSERR == (int)pkt), ""); data = (uchar *)&_binary_data_testnetif_pcap_start; memcpy(&pcap, data, sizeof(pcap)); data += sizeof(pcap); memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } pkt->nif = netptr; pkt->len = phdr.caplen - netptr->linkhdrlen; pkt->curr = pkt->curr - pkt->len; memcpy(pkt->curr, data + netptr->linkhdrlen, pkt->len); hw.type = NETADDR_ETHERNET; hw.len = ETH_ADDR_LEN; hw.addr[0] = 0xAA; hw.addr[1] = 0xBB; hw.addr[2] = 0xCC; hw.addr[3] = 0xDD; hw.addr[4] = 0xEE; hw.addr[5] = 0xAA; testPrint(verbose, "Send packet (known hardware address)"); if (SYSERR == netSend(pkt, &hw, NULL, ETHER_TYPE_ARP)) { failif(TRUE, "Returned SYSERR"); } else { if ((SYSERR == read(netptr->dev, pkt, phdr.caplen)) || (memcmp(pkt, data, phdr.caplen) != 0)) { failif(TRUE, "Packet did not match"); } else { failif(FALSE, ""); } } testPrint(verbose, "Free packet buffer"); failif((SYSERR == netFreebuf(pkt)), ""); testPrint(verbose, "Stop network interface"); failif(((SYSERR == netDown(ELOOP)) || (SYSERR == close(ELOOP))), ""); if (passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } return OK; }
/** * Shell command for VoIP functionality. * @param nargs number of arguments * @param args array of arguments * @return OK for success, SYSERR for syntax error */ shellcmd xsh_voip(int nargs, char *args[]) { int i, rxPort = UDP_PORT, txPort = UDP_PORT; ushort uart = NULL, udpRx = NULL, udpTx = NULL; ushort mode = MODE_SERIAL, check = CHECK_BASIC; struct netaddr *localhost; struct netaddr host; #ifdef ELOOP struct netaddr mask; #endif struct netif *netptr; struct thrent *thrptr; if (nargs < 2) { fprintf(stderr, "%s: too few arguments\n", args[0]); fprintf(stderr, "Try '%s --help' for more information\n", args[0]); return SYSERR; } else if (nargs == 2 && strncmp(args[1], "--help", 6) == 0) { printf ("\nUsage: %s [-p <rx port> <tx port>] [-s] [serial] [localhost] [IP address]\n", args[0]); printf("Description:\n"); printf("\tUses the second serial port and the network to "); printf("transmit and receive audio.\n"); printf("Options:\n"); printf ("\t-p\t\tSpecify UDP receive and transmit port numbers.\n"); printf("\t-s\t\tEmbed sequence information in each packet.\n"); printf("\tserial\t\tOperate in serial loopback mode.\n"); printf("\tlocalhost\tOperate in network loopback mode.\n"); printf("\tIP address\tSend and receive from this IP address.\n"); return OK; } else { for (i = 1; i < nargs; i++) { if (strncmp(args[i], "-s", 2) == 0) { check = CHECK_SEQ; } else if (strncmp(args[i], "-p", 2) == 0) { if ((i + 2) < nargs) { i++; rxPort = atol(args[i]); i++; txPort = atol(args[i]); } else { fprintf(stderr, "Insufficient number of arguments for port numbers.\n"); return SYSERR; } } else if (strncmp(args[i], "serial", 6) == 0) { mode = MODE_SERIAL; } else if (strncmp(args[i], "localhost", 9) == 0) { mode = MODE_LOCAL; } else if (SYSERR != dot2ipv4(args[i], &host)) { mode = MODE_IP; } else { fprintf(stderr, "Failed to parse destination IP address.\n"); return SYSERR; } } } enable(); #ifdef TTY1 /* Kill the SHELL1 thread */ for (i = 0; i < NTHREAD; i++) { thrptr = &thrtab[i]; if (thrptr->state == THRFREE) { continue; } if (0 == strncmp(thrptr->name, "SHELL1", 6)) { kill(i); } } /* Close TTY1 so we can use SERIAL1 */ close(TTY1); #else thrptr = NULL; #endif /* TTY1 */ #ifdef SERIAL1 uart = SERIAL1; #else uart = SYSERR; #endif /* SERIAL1 */ if (SYSERR == (short)uart) { fprintf(stderr, "Failed to select a uart device."); return SYSERR; } switch (mode) { case MODE_SERIAL: ready(create ((void *)serial_loop, INITSTK, 20, "voip-serial", 1, uart), RESCHED_YES); return OK; #ifdef ELOOP case MODE_LOCAL: if (SYSERR == open(ELOOP)) { fprintf(stderr, "Failed to open loopback device."); return SYSERR; } dot2ipv4("127.0.0.1", &host); localhost = &host; dot2ipv4("255.255.255.0", &mask); if (SYSERR == netUp(ELOOP, &host, &mask, NULL)) { close(ELOOP); fprintf(stderr, "Failed to bring up network on loopback device.\n"); return SYSERR; } break; #endif /* ELOOP */ case MODE_IP: netptr = netLookup((ethertab[0].dev)->num); if (NULL == netptr) { fprintf(stderr, "No network interface found.\n"); return SYSERR; } localhost = &(netptr->ip); srand(localhost->addr[3]); /* Seed the random number generator */ break; default: return SYSERR; } #ifdef NUDP if (UDP_PORT == rxPort && UDP_PORT == txPort) { /* If both ports are the default, use one UDP device */ udpRx = udpAlloc(); udpTx = udpRx; } else { /* Otherwise, use two UDP devices */ udpRx = udpAlloc(); udpTx = udpAlloc(); } #else udpRx = SYSERR; udpTx = SYSERR; #endif /* NUDP */ if (SYSERR == (short)udpRx || SYSERR == (short)udpTx) { fprintf(stderr, "Unable to allocate a UDP device.\n"); return SYSERR; } if (udpRx == udpTx) { if (SYSERR == open(udpRx, localhost, &host, rxPort, txPort)) { fprintf(stderr, "Failed to open UDP device.\n"); return SYSERR; } printf("Opened a single UDP device.\n"); } else { if (SYSERR == open(udpRx, localhost, NULL, rxPort, NULL)) { fprintf(stderr, "Failed to open UDP device.\n"); return SYSERR; } if (SYSERR == open(udpTx, localhost, &host, NULL, txPort)) { fprintf(stderr, "Failed to open UDP device.\n"); return SYSERR; } printf("Opened two UDP devices.\n"); } switch (check) { case CHECK_BASIC: ready(create ((void *)basic_send, INITSTK, 20, "voip-send", 2, uart, udpTx), RESCHED_YES); ready(create ((void *)basic_receive, INITSTK, 20, "voip-receive", 2, uart, udpRx), RESCHED_YES); break; case CHECK_SEQ: #ifdef NUDP control(udpRx, UDP_CTRL_SETFLAG, UDP_FLAG_NOBLOCK, NULL); control(udpTx, UDP_CTRL_SETFLAG, UDP_FLAG_NOBLOCK, NULL); #endif /* NUDP */ ready(create ((void *)seq_send, INITSTK, 20, "voip-send", 2, uart, udpTx), RESCHED_YES); ready(create ((void *)seq_receive, INITSTK, 20, "voip-receive", 2, uart, udpRx), RESCHED_YES); break; } return OK; }
static void kexec_from_network(int netdev, char *boot) { #if defined(WITH_DHCPC) && NETHER != 0 struct dhcpData data; int result; const struct netaddr *gatewayptr; struct netif *nif; void *kernel; uint size; char str_ip[20]; char str_mask[20]; char str_gateway[20]; const char *netdevname = devtab[netdev].name; /* Bring network interface (if any) down. */ netDown(netdev); /* Run DHCP client on the device for at most 10 seconds. */ printf("Running DHCP on %s\n", netdevname); result = dhcpClient(netdev, 10, &data); if (OK != result) { fprintf(stderr, "ERROR: DHCP failed.\n"); return; } /* Ensure the DHCP server provided the boot filename and TFTP server IP * address. */ if (('\0' == data.bootfile[0] || 0 == data.next_server.type) && boot == NULL) { fprintf(stderr, "ERROR: DHCP server did not provide boot file " "and TFTP server address.\n"); return; } /* Bring up the network interface. */ netaddrsprintf(str_ip, &data.ip); netaddrsprintf(str_mask, &data.mask); if (0 != data.gateway.len) { netaddrsprintf(str_gateway, &data.gateway); printf("Bringing up %s as %s with mask %s (gateway %s)\n", netdevname, str_ip, str_mask, str_gateway); gatewayptr = &data.gateway; } else { printf("Bringing up %s as %s with mask %s (no gateway)\n", netdevname, str_ip, str_mask); gatewayptr = NULL; } result = netUp(netdev, &data.ip, &data.mask, gatewayptr); if (OK != result) { fprintf(stderr, "ERROR: failed to bring up %s.\n", netdevname); return; } nif = netLookup(netdev); /* Download new kernel using TFTP. */ netaddrsprintf(str_ip, &data.next_server); if (boot == NULL) { printf("Downloading bootfile \"%s\" from TFTP server %s\n", data.bootfile, str_ip); kernel = (void*)tftpGetIntoBuffer(data.bootfile, &nif->ip, &data.next_server, &size); }else { printf("Downloading bootfile \"%s\" from TFTP server %s\n", boot, str_ip); kernel = (void*)tftpGetIntoBuffer(boot, &nif->ip, &data.next_server, &size); } if (SYSERR == (int)kernel) { fprintf(stderr, "ERROR: TFTP failed.\n"); return; } /* Execute the new kernel. */ printf("Executing new kernel (size=%u)\n", size); sleep(100); /* Wait just a fraction of a second for printf()s to finish (no guarantees though). */ kexec(kernel, size); fprintf(stderr, "ERROR: kexec() returned!\n"); #else /* WITH_DHCPC && NETHER != 0 */ fprintf(stderr, "ERROR: Network boot is not supported in this configuration.\n" " Please make sure you have enabled one or more network\n" " devices, along with the DHCP and TFTP clients.\n"); #endif /* !(WITH_DHCPC && NETHER != 0) */ }