Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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