ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers test_dhcp.c Source File

test_dhcp.c

00001 #include "test_dhcp.h"
00002 
00003 #include "lwip/netif.h"
00004 #include "lwip/dhcp.h"
00005 #include "netif/etharp.h"
00006 
00007 struct netif net_test;
00008 
00009 static const u8_t broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
00010 
00011 static const u8_t magic_cookie[] = { 0x63, 0x82, 0x53, 0x63 };
00012 
00013 static u8_t dhcp_offer[] = {
00014     0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */
00015     0x00, 0x0F, 0xEE, 0x30, 0xAB, 0x22, /* From Remote host */
00016     0x08, 0x00, /* Protocol: IP */
00017     0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */
00018     0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */
00019 
00020     0x02, /* Type == Boot reply */
00021     0x01, 0x06, /* Hw Ethernet, 6 bytes addrlen */
00022     0x00, /* 0 hops */
00023     0xAA, 0xAA, 0xAA, 0xAA, /* Transaction id, will be overwritten */
00024     0x00, 0x00, /* 0 seconds elapsed */
00025     0x00, 0x00, /* Flags (unicast) */
00026     0x00, 0x00, 0x00, 0x00, /* Client ip */
00027     0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */
00028     0xc3, 0xaa, 0xbd, 0xab, /* DHCP server ip */
00029     0x00, 0x00, 0x00, 0x00, /* relay agent */
00030     0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MAC addr + padding */
00031 
00032     /* Empty server name and boot file name */
00033     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00034     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00035     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00036     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00037     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00038     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00039     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00040     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00041     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00042     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00043     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00044     0x00, 0x00, 0x00, 0x00,
00045 
00046     0x63, 0x82, 0x53, 0x63, /* Magic cookie */
00047     0x35, 0x01, 0x02, /* Message type: Offer */
00048     0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Server identifier (IP) */
00049     0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */
00050     0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */
00051     0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Subnet mask */
00052     0xff, /* End option */
00053     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00054     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */
00055 };
00056 
00057 static u8_t dhcp_ack[] = {
00058     0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */
00059     0x00, 0x0f, 0xEE, 0x30, 0xAB, 0x22, /* From remote host */
00060     0x08, 0x00, /* Proto IP */
00061     0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */
00062     0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */
00063     0x02, /* Bootp reply */
00064     0x01, 0x06, /* Hw type Eth, len 6 */
00065     0x00, /* 0 hops */
00066     0xAA, 0xAA, 0xAA, 0xAA,
00067     0x00, 0x00, /* 0 seconds elapsed */
00068     0x00, 0x00, /* Flags (unicast) */
00069     0x00, 0x00, 0x00, 0x00, /* Client IP */
00070     0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */
00071     0xc3, 0xaa, 0xbd, 0xab, /* DHCP server IP */
00072     0x00, 0x00, 0x00, 0x00, /* Relay agent */
00073     0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Macaddr + padding */
00074 
00075     /* Empty server name and boot file name */
00076     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00077     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00078     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00079     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00080     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00081     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00082     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00083     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00084     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00085     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00086     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00087     0x00, 0x00, 0x00, 0x00,
00088 
00089     0x63, 0x82, 0x53, 0x63, /* Magic cookie */
00090     0x35, 0x01, 0x05, /* Dhcp message type ack */
00091     0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server identifier */
00092     0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */
00093     0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */
00094     0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Netmask */
00095     0xff, /* End marker */
00096 
00097     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00098     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */
00099 };
00100 
00101 static const u8_t arpreply[] = {
00102     0x00, 0x23, 0xC1, 0xDE, 0xD0, 0x0D, /* dst mac */
00103     0x00, 0x32, 0x44, 0x20, 0x01, 0x02, /* src mac */
00104     0x08, 0x06, /* proto arp */
00105     0x00, 0x01, /* hw eth */
00106     0x08, 0x00, /* proto ip */
00107     0x06, /* hw addr len 6 */
00108     0x04, /* proto addr len 4 */
00109     0x00, 0x02, /* arp reply */
00110     0x00, 0x32, 0x44, 0x20, 0x01, 0x02, /* sender mac */
00111     0xc3, 0xaa, 0xbd, 0xc8, /* sender ip */
00112     0x00, 0x23, 0xC1, 0xDE, 0xD0, 0x0D, /* target mac */
00113     0x00, 0x00, 0x00, 0x00, /* target ip */
00114 };
00115 
00116 static int txpacket;
00117 static enum tcase {
00118   TEST_LWIP_DHCP,
00119   TEST_LWIP_DHCP_NAK,
00120   TEST_LWIP_DHCP_RELAY,
00121   TEST_LWIP_DHCP_NAK_NO_ENDMARKER,
00122   TEST_LWIP_DHCP_INVALID_OVERLOAD
00123 } tcase;
00124 
00125 static int debug = 0;
00126 static void setdebug(int a) {debug = a;}
00127 
00128 static int tick = 0;
00129 static void tick_lwip(void)
00130 {
00131   tick++;
00132   if (tick % 5 == 0) {
00133     dhcp_fine_tmr();
00134   }
00135   if (tick % 600 == 0) {
00136     dhcp_coarse_tmr();
00137   }
00138 }
00139 
00140 static void send_pkt(struct netif *netif, const u8_t *data, size_t len)
00141 {
00142   struct pbuf *p, *q;
00143   LWIP_ASSERT("pkt too big", len <= 0xFFFF);
00144   p = pbuf_alloc(PBUF_RAW, (u16_t)len, PBUF_POOL);
00145 
00146   if (debug) {
00147     /* Dump data */
00148     u32_t i;
00149     printf("RX data (len %d)", p->tot_len);
00150     for (i = 0; i < len; i++) {
00151       printf(" %02X", data[i]);
00152     }
00153     printf("\n");
00154   }
00155 
00156   fail_unless(p != NULL);
00157   for(q = p; q != NULL; q = q->next) {
00158     memcpy(q->payload, data, q->len);
00159     data += q->len;
00160   }
00161   netif->input(p, netif);
00162 }
00163 
00164 static err_t lwip_tx_func(struct netif *netif, struct pbuf *p);
00165 
00166 static err_t testif_init(struct netif *netif)
00167 {
00168   netif->name[0] = 'c';
00169   netif->name[1] = 'h';
00170   netif->output = etharp_output;
00171   netif->linkoutput = lwip_tx_func;
00172   netif->mtu = 1500;
00173   netif->hwaddr_len = 6;
00174   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
00175 
00176   netif->hwaddr[0] = 0x00;
00177   netif->hwaddr[1] = 0x23;
00178   netif->hwaddr[2] = 0xC1;
00179   netif->hwaddr[3] = 0xDE;
00180   netif->hwaddr[4] = 0xD0;
00181   netif->hwaddr[5] = 0x0D;
00182 
00183   return ERR_OK;
00184 }
00185 
00186 static void dhcp_setup(void)
00187 {
00188   txpacket = 0;
00189 }
00190 
00191 static void dhcp_teardown(void)
00192 {
00193 }
00194 
00195 static void check_pkt(struct pbuf *p, u32_t pos, const u8_t *mem, u32_t len)
00196 {
00197   u8_t *data;
00198 
00199   fail_if((pos + len) > p->tot_len);
00200   while (pos > p->len && p->next) {
00201     pos -= p->len;
00202     p = p->next;
00203   }
00204   fail_if(p == NULL);
00205   fail_unless(pos + len <= p->len); /* All data we seek within same pbuf */
00206 
00207   data = (u8_t*)p->payload;
00208   fail_if(memcmp(&data[pos], mem, len), "data at pos %d, len %d in packet %d did not match", pos, len, txpacket);
00209 }
00210 
00211 static void check_pkt_fuzzy(struct pbuf *p, u32_t startpos, const u8_t *mem, u32_t len)
00212 {
00213   int found;
00214   u32_t i;
00215   u8_t *data;
00216 
00217   fail_if((startpos + len) > p->tot_len);
00218   while (startpos > p->len && p->next) {
00219     startpos -= p->len;
00220     p = p->next;
00221   }
00222   fail_if(p == NULL);
00223   fail_unless(startpos + len <= p->len); /* All data we seek within same pbuf */
00224 
00225   found = 0;
00226   data = (u8_t*)p->payload;
00227   for (i = startpos; i <= (p->len - len); i++) {
00228     if (memcmp(&data[i], mem, len) == 0) {
00229       found = 1;
00230       break;
00231     }
00232   }
00233   fail_unless(found);
00234 }
00235 
00236 static err_t lwip_tx_func(struct netif *netif, struct pbuf *p)
00237 {
00238   fail_unless(netif == &net_test);
00239   txpacket++;
00240 
00241   if (debug) {
00242     struct pbuf *pp = p;
00243     /* Dump data */
00244     printf("TX data (pkt %d, len %d, tick %d)", txpacket, p->tot_len, tick);
00245     do {
00246       int i;
00247       for (i = 0; i < pp->len; i++) {
00248         printf(" %02X", ((u8_t *) pp->payload)[i]);
00249       }
00250       if (pp->next) {
00251         pp = pp->next;
00252       }
00253     } while (pp->next);
00254     printf("\n");
00255   }
00256 
00257   switch (tcase) {
00258   case TEST_LWIP_DHCP:
00259     switch (txpacket) {
00260     case 1:
00261     case 2:
00262       {
00263         const u8_t ipproto[] = { 0x08, 0x00 };
00264         const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */
00265         const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
00266 
00267         check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */
00268         check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */
00269 
00270         check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */
00271 
00272         check_pkt(p, 42, bootp_start, sizeof(bootp_start));
00273 
00274         check_pkt(p, 53, ipaddrs, sizeof(ipaddrs));
00275 
00276         check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */
00277 
00278         check_pkt(p, 278, magic_cookie, sizeof(magic_cookie));
00279 
00280         /* Check dchp message type, can be at different positions */
00281         if (txpacket == 1) {
00282           u8_t dhcp_discover_opt[] = { 0x35, 0x01, 0x01 };
00283           check_pkt_fuzzy(p, 282, dhcp_discover_opt, sizeof(dhcp_discover_opt));
00284         } else if (txpacket == 2) {
00285           u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 };
00286           u8_t requested_ipaddr[] = { 0x32, 0x04, 0xc3, 0xaa, 0xbd, 0xc8 }; /* Ask for offered IP */
00287 
00288           check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt));
00289           check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr));
00290         }
00291         break;
00292       }
00293     case 3:
00294     case 4:
00295     case 5:
00296       {
00297         const u8_t arpproto[] = { 0x08, 0x06 };
00298 
00299         check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */
00300         check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */
00301 
00302         check_pkt(p, 12, arpproto, sizeof(arpproto)); /* eth level proto: ip */
00303         break;
00304       }
00305       default:
00306         fail();
00307         break;
00308     }
00309     break;
00310 
00311   case TEST_LWIP_DHCP_NAK:
00312     {
00313       const u8_t ipproto[] = { 0x08, 0x00 };
00314       const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */
00315       const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
00316       const u8_t dhcp_nak_opt[] = { 0x35, 0x01, 0x04 };
00317       const u8_t requested_ipaddr[] = { 0x32, 0x04, 0xc3, 0xaa, 0xbd, 0xc8 }; /* offered IP */
00318 
00319       fail_unless(txpacket == 4);
00320       check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */
00321       check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */
00322 
00323       check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */
00324 
00325       check_pkt(p, 42, bootp_start, sizeof(bootp_start));
00326 
00327       check_pkt(p, 53, ipaddrs, sizeof(ipaddrs));
00328 
00329       check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */
00330 
00331       check_pkt(p, 278, magic_cookie, sizeof(magic_cookie));
00332 
00333       check_pkt_fuzzy(p, 282, dhcp_nak_opt, sizeof(dhcp_nak_opt)); /* NAK the ack */
00334 
00335       check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr));
00336       break;
00337     }
00338 
00339   case TEST_LWIP_DHCP_RELAY:
00340     switch (txpacket) {
00341     case 1:
00342     case 2:
00343       {
00344         const u8_t ipproto[] = { 0x08, 0x00 };
00345         const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */
00346         const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
00347 
00348         check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */
00349         check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */
00350 
00351         check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */
00352 
00353         check_pkt(p, 42, bootp_start, sizeof(bootp_start));
00354 
00355         check_pkt(p, 53, ipaddrs, sizeof(ipaddrs));
00356 
00357         check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */
00358 
00359         check_pkt(p, 278, magic_cookie, sizeof(magic_cookie));
00360 
00361         /* Check dchp message type, can be at different positions */
00362         if (txpacket == 1) {
00363           u8_t dhcp_discover_opt[] = { 0x35, 0x01, 0x01 };
00364           check_pkt_fuzzy(p, 282, dhcp_discover_opt, sizeof(dhcp_discover_opt));
00365         } else if (txpacket == 2) {
00366           u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 };
00367           u8_t requested_ipaddr[] = { 0x32, 0x04, 0x4f, 0x8a, 0x33, 0x05 }; /* Ask for offered IP */
00368 
00369           check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt));
00370           check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr));
00371         }
00372         break;
00373       }
00374     case 3:
00375     case 4:
00376     case 5:
00377     case 6:
00378       {
00379         const u8_t arpproto[] = { 0x08, 0x06 };
00380 
00381         check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */
00382         check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */
00383 
00384         check_pkt(p, 12, arpproto, sizeof(arpproto)); /* eth level proto: ip */
00385         break;
00386       }
00387     case 7:
00388       {
00389         const u8_t fake_arp[6] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xab };
00390         const u8_t ipproto[] = { 0x08, 0x00 };
00391         const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */
00392         const u8_t ipaddrs[] = { 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
00393         const u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 };
00394 
00395         check_pkt(p, 0, fake_arp, 6); /* eth level dest: broadcast */
00396         check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */
00397 
00398         check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */
00399 
00400         check_pkt(p, 42, bootp_start, sizeof(bootp_start));
00401 
00402         check_pkt(p, 53, ipaddrs, sizeof(ipaddrs));
00403 
00404         check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */
00405 
00406         check_pkt(p, 278, magic_cookie, sizeof(magic_cookie));
00407 
00408         /* Check dchp message type, can be at different positions */
00409         check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt));
00410         break;
00411       }
00412     default:
00413       fail();
00414       break;
00415     }
00416     break;
00417 
00418   default:
00419     break;
00420   }
00421 
00422   return ERR_OK;
00423 }
00424 
00425 /*
00426  * Test basic happy flow DHCP session.
00427  * Validate that xid is checked.
00428  */
00429 START_TEST(test_dhcp)
00430 {
00431   ip4_addr_t addr;
00432   ip4_addr_t netmask;
00433   ip4_addr_t gw;
00434   int i;
00435   u32_t xid;
00436   LWIP_UNUSED_ARG(_i);
00437 
00438   tcase = TEST_LWIP_DHCP;
00439   setdebug(0);
00440 
00441   IP4_ADDR(&addr, 0, 0, 0, 0);
00442   IP4_ADDR(&netmask, 0, 0, 0, 0);
00443   IP4_ADDR(&gw, 0, 0, 0, 0);
00444 
00445   netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
00446   netif_set_up(&net_test);
00447 
00448   dhcp_start(&net_test);
00449 
00450   fail_unless(txpacket == 1); /* DHCP discover sent */
00451   xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */
00452   memcpy(&dhcp_offer[46], &xid, 4);
00453   send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer));
00454 
00455   /* IP addresses should be zero */
00456   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
00457   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
00458   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
00459 
00460   fail_unless(txpacket == 1, "TX %d packets, expected 1", txpacket); /* Nothing more sent */
00461   xid = htonl(net_test.dhcp->xid);
00462   memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */
00463   send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer));
00464 
00465   fail_unless(txpacket == 2, "TX %d packets, expected 2", txpacket); /* DHCP request sent */
00466   xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */
00467   memcpy(&dhcp_ack[46], &xid, 4);
00468   send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack));
00469 
00470   fail_unless(txpacket == 2, "TX %d packets, still expected 2", txpacket); /* No more sent */
00471   xid = htonl(net_test.dhcp->xid); /* xid updated */
00472   memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */
00473   send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack));
00474 
00475   for (i = 0; i < 20; i++) {
00476     tick_lwip();
00477   }
00478   fail_unless(txpacket == 5, "TX %d packets, expected 5", txpacket); /* ARP requests sent */
00479 
00480   /* Interface up */
00481   fail_unless(netif_is_up(&net_test));
00482 
00483   /* Now it should have taken the IP */
00484   IP4_ADDR(&addr, 195, 170, 189, 200);
00485   IP4_ADDR(&netmask, 255, 255, 255, 0);
00486   IP4_ADDR(&gw, 195, 170, 189, 171);
00487   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
00488   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
00489   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
00490 
00491   netif_remove(&net_test);
00492 }
00493 END_TEST
00494 
00495 /*
00496  * Test that IP address is not taken and NAK is sent if someone
00497  * replies to ARP requests for the offered address.
00498  */
00499 START_TEST(test_dhcp_nak)
00500 {
00501   ip4_addr_t addr;
00502   ip4_addr_t netmask;
00503   ip4_addr_t gw;
00504   u32_t xid;
00505   LWIP_UNUSED_ARG(_i);
00506 
00507   tcase = TEST_LWIP_DHCP;
00508   setdebug(0);
00509 
00510   IP4_ADDR(&addr, 0, 0, 0, 0);
00511   IP4_ADDR(&netmask, 0, 0, 0, 0);
00512   IP4_ADDR(&gw, 0, 0, 0, 0);
00513 
00514   netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
00515   netif_set_up(&net_test);
00516 
00517   dhcp_start(&net_test);
00518 
00519   fail_unless(txpacket == 1); /* DHCP discover sent */
00520   xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */
00521   memcpy(&dhcp_offer[46], &xid, 4);
00522   send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer));
00523 
00524   /* IP addresses should be zero */
00525   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
00526   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
00527   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
00528 
00529   fail_unless(txpacket == 1); /* Nothing more sent */
00530   xid = htonl(net_test.dhcp->xid);
00531   memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */
00532   send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer));
00533 
00534   fail_unless(txpacket == 2); /* DHCP request sent */
00535   xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */
00536   memcpy(&dhcp_ack[46], &xid, 4);
00537   send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack));
00538 
00539   fail_unless(txpacket == 2); /* No more sent */
00540   xid = htonl(net_test.dhcp->xid); /* xid updated */
00541   memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */
00542   send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack));
00543 
00544   fail_unless(txpacket == 3); /* ARP request sent */
00545 
00546   tcase = TEST_LWIP_DHCP_NAK; /* Switch testcase */
00547 
00548   /* Send arp reply, mark offered IP as taken */
00549   send_pkt(&net_test, arpreply, sizeof(arpreply));
00550 
00551   fail_unless(txpacket == 4); /* DHCP nak sent */
00552 
00553   netif_remove(&net_test);
00554 }
00555 END_TEST
00556 
00557 /*
00558  * Test case based on captured data where
00559  * replies are sent from a different IP than the
00560  * one the client unicasted to.
00561  */
00562 START_TEST(test_dhcp_relayed)
00563 {
00564   u8_t relay_offer[] = {
00565   0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d,
00566   0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60,
00567   0x08, 0x00, 0x45, 0x00,
00568   0x01, 0x38, 0xfd, 0x53, 0x00, 0x00, 0x40, 0x11,
00569   0x78, 0x46, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a,
00570   0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24,
00571   0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x51, 0x35,
00572   0xb6, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00573   0x00, 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00,
00574   0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23,
00575   0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00,
00576   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00577   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00578   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00579   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00580   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00581   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00582   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00583   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00584   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00585   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00586   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00587   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00588   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00589   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00590   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00591   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00592   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00593   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00594   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00595   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00596   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00597   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00598   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00599   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00600   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82,
00601   0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00,
00602   0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08,
00603   0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1,
00604   0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04,
00605   0x00, 0x00, 0x54, 0x49, 0x35, 0x01, 0x02, 0x36,
00606   0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff
00607   };
00608 
00609   u8_t relay_ack1[] = {
00610   0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x22,
00611   0x93, 0x5a, 0xf7, 0x60, 0x08, 0x00, 0x45, 0x00,
00612   0x01, 0x38, 0xfd, 0x55, 0x00, 0x00, 0x40, 0x11,
00613   0x78, 0x44, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a,
00614   0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24,
00615   0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x51, 0x35,
00616   0xb6, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00617   0x00, 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00,
00618   0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23,
00619   0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00,
00620   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00621   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00622   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00623   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00624   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00625   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00626   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00627   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00628   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00629   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00630   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00631   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00632   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00633   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00634   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00635   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00636   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00637   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00638   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00639   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00640   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00641   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00642   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00643   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00644   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82,
00645   0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00,
00646   0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08,
00647   0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1,
00648   0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04,
00649   0x00, 0x00, 0x54, 0x49, 0x35, 0x01, 0x05, 0x36,
00650   0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff
00651   };
00652 
00653   u8_t relay_ack2[] = {
00654   0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d,
00655   0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60,
00656   0x08, 0x00, 0x45, 0x00,
00657   0x01, 0x38, 0xfa, 0x18, 0x00, 0x00, 0x40, 0x11,
00658   0x7b, 0x81, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a,
00659   0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24,
00660   0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x49, 0x8b,
00661   0x6e, 0xab, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x8a,
00662   0x33, 0x05, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00,
00663   0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23,
00664   0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00,
00665   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00666   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00667   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00668   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00669   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00670   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00671   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00672   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00673   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00674   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00675   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00676   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00677   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00678   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00679   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00680   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00681   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00682   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00683   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00684   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00685   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00686   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00687   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00688   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00689   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82,
00690   0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00,
00691   0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08,
00692   0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1,
00693   0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04,
00694   0x00, 0x00, 0x54, 0x60, 0x35, 0x01, 0x05, 0x36,
00695   0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff };
00696 
00697   const u8_t arp_resp[] = {
00698   0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* DEST */
00699   0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, /* SRC */
00700   0x08, 0x06, /* Type: ARP */
00701   0x00, 0x01, /* HW: Ethernet */
00702   0x08, 0x00, /* PROTO: IP */
00703   0x06, /* HW size */
00704   0x04, /* PROTO size */
00705   0x00, 0x02, /* OPCODE: Reply */
00706 
00707   0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, /* Target MAC */
00708   0x4f, 0x8a, 0x32, 0x01, /* Target IP */
00709 
00710   0x00, 0x23, 0xc1, 0x00, 0x06, 0x50, /* src mac */
00711   0x4f, 0x8a, 0x33, 0x05, /* src ip */
00712 
00713   /* Padding follows.. */
00714   0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00715   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00716   0x00, 0x00, 0x00, 0x00 };
00717 
00718   ip4_addr_t addr;
00719   ip4_addr_t netmask;
00720   ip4_addr_t gw;
00721   int i;
00722   u32_t xid;
00723   LWIP_UNUSED_ARG(_i);
00724 
00725   tcase = TEST_LWIP_DHCP_RELAY;
00726   setdebug(0);
00727 
00728   IP4_ADDR(&addr, 0, 0, 0, 0);
00729   IP4_ADDR(&netmask, 0, 0, 0, 0);
00730   IP4_ADDR(&gw, 0, 0, 0, 0);
00731 
00732   netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
00733   netif_set_up(&net_test);
00734 
00735   dhcp_start(&net_test);
00736 
00737   fail_unless(txpacket == 1); /* DHCP discover sent */
00738 
00739   /* IP addresses should be zero */
00740   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
00741   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
00742   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
00743 
00744   fail_unless(txpacket == 1); /* Nothing more sent */
00745   xid = htonl(net_test.dhcp->xid);
00746   memcpy(&relay_offer[46], &xid, 4); /* insert correct transaction id */
00747   send_pkt(&net_test, relay_offer, sizeof(relay_offer));
00748 
00749   /* request sent? */
00750   fail_unless(txpacket == 2, "txpkt = %d, should be 2", txpacket);
00751   xid = htonl(net_test.dhcp->xid); /* xid updated */
00752   memcpy(&relay_ack1[46], &xid, 4); /* insert transaction id */
00753   send_pkt(&net_test, relay_ack1, sizeof(relay_ack1));
00754 
00755   for (i = 0; i < 25; i++) {
00756     tick_lwip();
00757   }
00758   fail_unless(txpacket == 5, "txpkt should be 5, is %d", txpacket); /* ARP requests sent */
00759 
00760   /* Interface up */
00761   fail_unless(netif_is_up(&net_test));
00762 
00763   /* Now it should have taken the IP */
00764   IP4_ADDR(&addr, 79, 138, 51, 5);
00765   IP4_ADDR(&netmask, 255, 255, 254, 0);
00766   IP4_ADDR(&gw, 79, 138, 50, 1);
00767   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
00768   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
00769   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
00770 
00771   fail_unless(txpacket == 5, "txpacket = %d", txpacket);
00772 
00773   for (i = 0; i < 108000 - 25; i++) {
00774     tick_lwip();
00775   }
00776 
00777   fail_unless(netif_is_up(&net_test));
00778   fail_unless(txpacket == 6, "txpacket = %d", txpacket);
00779 
00780   /* We need to send arp response here.. */
00781 
00782   send_pkt(&net_test, arp_resp, sizeof(arp_resp));
00783 
00784   fail_unless(txpacket == 7, "txpacket = %d", txpacket);
00785   fail_unless(netif_is_up(&net_test));
00786 
00787   xid = htonl(net_test.dhcp->xid); /* xid updated */
00788   memcpy(&relay_ack2[46], &xid, 4); /* insert transaction id */
00789   send_pkt(&net_test, relay_ack2, sizeof(relay_ack2));
00790 
00791   for (i = 0; i < 100000; i++) {
00792     tick_lwip();
00793   }
00794 
00795   fail_unless(txpacket == 7, "txpacket = %d", txpacket);
00796 
00797   netif_remove(&net_test);
00798 
00799 }
00800 END_TEST
00801 
00802 START_TEST(test_dhcp_nak_no_endmarker)
00803 {
00804   ip4_addr_t addr;
00805   ip4_addr_t netmask;
00806   ip4_addr_t gw;
00807 
00808   u8_t dhcp_nack_no_endmarker[] = {
00809     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x54, 0x75,
00810     0xd0, 0x26, 0xd0, 0x0d, 0x08, 0x00, 0x45, 0x00,
00811     0x01, 0x15, 0x38, 0x86, 0x00, 0x00, 0xff, 0x11,
00812     0xc0, 0xa8, 0xc0, 0xa8, 0x01, 0x01, 0xff, 0xff,
00813     0xff, 0xff, 0x00, 0x43, 0x00, 0x44, 0x01, 0x01,
00814     0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x7a, 0xcb,
00815     0xba, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00816     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00817     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23,
00818     0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00,
00819     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00820     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00821     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00822     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00823     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00824     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00825     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00826     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00827     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00828     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00829     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00830     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00831     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00832     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00833     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00834     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00835     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00836     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00837     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00838     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00839     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00840     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00841     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00842     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00843     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82,
00844     0x53, 0x63, 0x35, 0x01, 0x06, 0x36, 0x04, 0xc0,
00845     0xa8, 0x01, 0x01, 0x31, 0xef, 0xad, 0x72, 0x31,
00846     0x43, 0x4e, 0x44, 0x30, 0x32, 0x35, 0x30, 0x43,
00847     0x52, 0x47, 0x44, 0x38, 0x35, 0x36, 0x3c, 0x08,
00848     0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30,
00849     0x37, 0x0d, 0x01, 0x0f, 0x03, 0x06, 0x2c, 0x2e,
00850     0x2f, 0x1f, 0x21, 0x79, 0xf9, 0x2b, 0xfc, 0xff,
00851     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x71,
00852     0xf3, 0x5b, 0xe2, 0x71, 0x2e, 0x01, 0x08, 0x03,
00853     0x04, 0xc0, 0xa8, 0x01, 0x01, 0xff, 0xeb, 0x1e,
00854     0x44, 0xec, 0xeb, 0x1e, 0x30, 0x37, 0x0c, 0x01,
00855     0x0f, 0x03, 0x06, 0x2c, 0x2e, 0x2f, 0x1f, 0x21,
00856     0x79, 0xf9, 0x2b, 0xff, 0x25, 0xc0, 0x09, 0xd6,
00857     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00858     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
00859   };
00860   u32_t xid;
00861   LWIP_UNUSED_ARG(_i);
00862 
00863   tcase = TEST_LWIP_DHCP_NAK_NO_ENDMARKER;
00864   setdebug(0);
00865 
00866   IP4_ADDR(&addr, 0, 0, 0, 0);
00867   IP4_ADDR(&netmask, 0, 0, 0, 0);
00868   IP4_ADDR(&gw, 0, 0, 0, 0);
00869 
00870   netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
00871   netif_set_up(&net_test);
00872 
00873   dhcp_start(&net_test);
00874 
00875   fail_unless(txpacket == 1); /* DHCP discover sent */
00876   xid = net_test.dhcp->xid; /* Write bad xid, not using htonl! */
00877   memcpy(&dhcp_offer[46], &xid, 4);
00878   send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer));
00879 
00880   /* IP addresses should be zero */
00881   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
00882   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
00883   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
00884 
00885   fail_unless(txpacket == 1); /* Nothing more sent */
00886   xid = htonl(net_test.dhcp->xid);
00887   memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */
00888   send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer));
00889   
00890   fail_unless(net_test.dhcp->state == DHCP_STATE_REQUESTING);
00891 
00892   fail_unless(txpacket == 2); /* No more sent */
00893   xid = htonl(net_test.dhcp->xid); /* xid updated */
00894   memcpy(&dhcp_nack_no_endmarker[46], &xid, 4); /* insert transaction id */
00895   send_pkt(&net_test, dhcp_nack_no_endmarker, sizeof(dhcp_nack_no_endmarker));
00896 
00897   /* NAK should put us in another state for a while, no other way detecting it */
00898   fail_unless(net_test.dhcp->state != DHCP_STATE_REQUESTING);
00899 
00900   netif_remove(&net_test);
00901 }
00902 END_TEST
00903 
00904 START_TEST(test_dhcp_invalid_overload)
00905 {
00906   u8_t dhcp_offer_invalid_overload[] = {
00907       0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */
00908       0x00, 0x0F, 0xEE, 0x30, 0xAB, 0x22, /* From Remote host */
00909       0x08, 0x00, /* Protocol: IP */
00910       0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */
00911       0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */
00912 
00913       0x02, /* Type == Boot reply */
00914       0x01, 0x06, /* Hw Ethernet, 6 bytes addrlen */
00915       0x00, /* 0 hops */
00916       0xAA, 0xAA, 0xAA, 0xAA, /* Transaction id, will be overwritten */
00917       0x00, 0x00, /* 0 seconds elapsed */
00918       0x00, 0x00, /* Flags (unicast) */
00919       0x00, 0x00, 0x00, 0x00, /* Client ip */
00920       0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */
00921       0xc3, 0xaa, 0xbd, 0xab, /* DHCP server ip */
00922       0x00, 0x00, 0x00, 0x00, /* relay agent */
00923       0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MAC addr + padding */
00924 
00925       /* Empty server name */
00926       0x34, 0x01, 0x02, 0xff, /* Overload: SNAME + END */
00927       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00928       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00929       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00930       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00931       /* Empty boot file name */
00932       0x34, 0x01, 0x01, 0xff, /* Overload FILE + END */
00933       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00934       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00935       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00936       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00937       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00938       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00939       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00940       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00941 
00942       0x63, 0x82, 0x53, 0x63, /* Magic cookie */
00943       0x35, 0x01, 0x02, /* Message type: Offer */
00944       0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Server identifier (IP) */
00945       0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */
00946       0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */
00947       0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Subnet mask */
00948       0x34, 0x01, 0x03, /* Overload: FILE + SNAME */
00949       0xff, /* End option */
00950       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00951       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */
00952   };
00953   ip4_addr_t addr;
00954   ip4_addr_t netmask;
00955   ip4_addr_t gw;
00956   u32_t xid;
00957   LWIP_UNUSED_ARG(_i);
00958 
00959   tcase = TEST_LWIP_DHCP_INVALID_OVERLOAD;
00960   setdebug(0);
00961 
00962   IP4_ADDR(&addr, 0, 0, 0, 0);
00963   IP4_ADDR(&netmask, 0, 0, 0, 0);
00964   IP4_ADDR(&gw, 0, 0, 0, 0);
00965 
00966   netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
00967   netif_set_up(&net_test);
00968 
00969   dhcp_start(&net_test);
00970 
00971   fail_unless(txpacket == 1); /* DHCP discover sent */
00972   xid = htonl(netif_dhcp_data(&net_test)->xid);
00973   memcpy(&dhcp_offer_invalid_overload[46], &xid, 4); /* insert correct transaction id */
00974   dhcp_offer_invalid_overload[311] = 3;
00975   send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload));
00976   /* IP addresses should be zero */
00977   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
00978   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
00979   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
00980   fail_unless(txpacket == 1); /* Nothing more sent */
00981 
00982   dhcp_offer_invalid_overload[311] = 2;
00983   send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload));
00984   /* IP addresses should be zero */
00985   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
00986   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
00987   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
00988   fail_unless(txpacket == 1); /* Nothing more sent */
00989 
00990   dhcp_offer_invalid_overload[311] = 1;
00991   send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload));
00992   /* IP addresses should be zero */
00993   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
00994   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
00995   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
00996   fail_unless(txpacket == 1); /* Nothing more sent */
00997 
00998   dhcp_offer_invalid_overload[311] = 0;
00999   send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer));
01000 
01001   fail_unless(netif_dhcp_data(&net_test)->state == DHCP_STATE_REQUESTING);
01002 
01003   fail_unless(txpacket == 2); /* No more sent */
01004   xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */
01005 
01006   netif_remove(&net_test);
01007 }
01008 END_TEST
01009 
01010 /** Create the suite including all tests for this module */
01011 Suite *
01012 dhcp_suite(void)
01013 {
01014   testfunc tests[] = {
01015     TESTFUNC(test_dhcp),
01016     TESTFUNC(test_dhcp_nak),
01017     TESTFUNC(test_dhcp_relayed),
01018     TESTFUNC(test_dhcp_nak_no_endmarker),
01019     TESTFUNC(test_dhcp_invalid_overload)
01020   };
01021   return create_suite("DHCP", tests, sizeof(tests)/sizeof(testfunc), dhcp_setup, dhcp_teardown);
01022 }