Rtos API example

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