1 #include "test_dhcp.h"
2 
3 #include "lwip/netif.h"
4 #include "lwip/dhcp.h"
5 #include "lwip/prot/dhcp.h"
6 #include "lwip/etharp.h"
7 #include "netif/ethernet.h"
8 
9 struct netif net_test;
10 
11 static const u8_t broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
12 
13 static const u8_t magic_cookie[] = { 0x63, 0x82, 0x53, 0x63 };
14 
15 static u8_t dhcp_offer[] = {
16     0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */
17     0x00, 0x0F, 0xEE, 0x30, 0xAB, 0x22, /* From Remote host */
18     0x08, 0x00, /* Protocol: IP */
19     0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */
20     0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */
21 
22     0x02, /* Type == Boot reply */
23     0x01, 0x06, /* Hw Ethernet, 6 bytes addrlen */
24     0x00, /* 0 hops */
25     0xAA, 0xAA, 0xAA, 0xAA, /* Transaction id, will be overwritten */
26     0x00, 0x00, /* 0 seconds elapsed */
27     0x00, 0x00, /* Flags (unicast) */
28     0x00, 0x00, 0x00, 0x00, /* Client ip */
29     0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */
30     0xc3, 0xaa, 0xbd, 0xab, /* DHCP server ip */
31     0x00, 0x00, 0x00, 0x00, /* relay agent */
32     0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MAC addr + padding */
33 
34     /* Empty server name and boot file name */
35     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
36     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
38     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
39     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46     0x00, 0x00, 0x00, 0x00,
47 
48     0x63, 0x82, 0x53, 0x63, /* Magic cookie */
49     0x35, 0x01, 0x02, /* Message type: Offer */
50     0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Server identifier (IP) */
51     0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */
52     0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */
53     0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Subnet mask */
54     0xff, /* End option */
55     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */
57 };
58 
59 static u8_t dhcp_ack[] = {
60     0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */
61     0x00, 0x0f, 0xEE, 0x30, 0xAB, 0x22, /* From remote host */
62     0x08, 0x00, /* Proto IP */
63     0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */
64     0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */
65     0x02, /* Bootp reply */
66     0x01, 0x06, /* Hw type Eth, len 6 */
67     0x00, /* 0 hops */
68     0xAA, 0xAA, 0xAA, 0xAA,
69     0x00, 0x00, /* 0 seconds elapsed */
70     0x00, 0x00, /* Flags (unicast) */
71     0x00, 0x00, 0x00, 0x00, /* Client IP */
72     0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */
73     0xc3, 0xaa, 0xbd, 0xab, /* DHCP server IP */
74     0x00, 0x00, 0x00, 0x00, /* Relay agent */
75     0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Macaddr + padding */
76 
77     /* Empty server name and boot file name */
78     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89     0x00, 0x00, 0x00, 0x00,
90 
91     0x63, 0x82, 0x53, 0x63, /* Magic cookie */
92     0x35, 0x01, 0x05, /* Dhcp message type ack */
93     0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* DHCP server identifier */
94     0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */
95     0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */
96     0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Netmask */
97     0xff, /* End marker */
98 
99     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */
101 };
102 
103 static const u8_t arpreply[] = {
104     0x00, 0x23, 0xC1, 0xDE, 0xD0, 0x0D, /* dst mac */
105     0x00, 0x32, 0x44, 0x20, 0x01, 0x02, /* src mac */
106     0x08, 0x06, /* proto arp */
107     0x00, 0x01, /* hw eth */
108     0x08, 0x00, /* proto ip */
109     0x06, /* hw addr len 6 */
110     0x04, /* proto addr len 4 */
111     0x00, 0x02, /* arp reply */
112     0x00, 0x32, 0x44, 0x20, 0x01, 0x02, /* sender mac */
113     0xc3, 0xaa, 0xbd, 0xc8, /* sender ip */
114     0x00, 0x23, 0xC1, 0xDE, 0xD0, 0x0D, /* target mac */
115     0x00, 0x00, 0x00, 0x00, /* target ip */
116 };
117 
118 static int txpacket;
119 static enum tcase {
120   TEST_LWIP_DHCP,
121   TEST_LWIP_DHCP_NAK,
122   TEST_LWIP_DHCP_RELAY,
123   TEST_LWIP_DHCP_NAK_NO_ENDMARKER,
124   TEST_LWIP_DHCP_INVALID_OVERLOAD
125 } tcase;
126 
127 static int debug = 0;
128 static void setdebug(int a) {debug = a;}
129 
130 static int tick = 0;
131 static void tick_lwip(void)
132 {
133   tick++;
134   if (tick % 5 == 0) {
135     dhcp_fine_tmr();
136   }
137   if (tick % 600 == 0) {
138     dhcp_coarse_tmr();
139   }
140 }
141 
142 static void send_pkt(struct netif *netif, const u8_t *data, size_t len)
143 {
144   struct pbuf *p, *q;
145   LWIP_ASSERT("pkt too big", len <= 0xFFFF);
146   p = pbuf_alloc(PBUF_RAW, (u16_t)len, PBUF_POOL);
147 
148   if (debug) {
149     /* Dump data */
150     u32_t i;
151     printf("RX data (len %d)", p->tot_len);
152     for (i = 0; i < len; i++) {
153       printf(" %02X", data[i]);
154     }
155     printf("\n");
156   }
157 
158   fail_unless(p != NULL);
159   for(q = p; q != NULL; q = q->next) {
160     memcpy(q->payload, data, q->len);
161     data += q->len;
162   }
163   netif->input(p, netif);
164 }
165 
166 static err_t lwip_tx_func(struct netif *netif, struct pbuf *p);
167 
168 static err_t testif_init(struct netif *netif)
169 {
170   netif->name[0] = 'c';
171   netif->name[1] = 'h';
172   netif->output = etharp_output;
173   netif->linkoutput = lwip_tx_func;
174   netif->mtu = 1500;
175   netif->hwaddr_len = 6;
176   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
177 
178   netif->hwaddr[0] = 0x00;
179   netif->hwaddr[1] = 0x23;
180   netif->hwaddr[2] = 0xC1;
181   netif->hwaddr[3] = 0xDE;
182   netif->hwaddr[4] = 0xD0;
183   netif->hwaddr[5] = 0x0D;
184 
185   return ERR_OK;
186 }
187 
188 static void dhcp_setup(void)
189 {
190   txpacket = 0;
191 }
192 
193 static void dhcp_teardown(void)
194 {
195 }
196 
197 static void check_pkt(struct pbuf *p, u32_t pos, const u8_t *mem, u32_t len)
198 {
199   u8_t *data;
200 
201   fail_if((pos + len) > p->tot_len);
202   while (pos > p->len && p->next) {
203     pos -= p->len;
204     p = p->next;
205   }
206   fail_if(p == NULL);
207   fail_unless(pos + len <= p->len); /* All data we seek within same pbuf */
208 
209   data = (u8_t*)p->payload;
210   fail_if(memcmp(&data[pos], mem, len), "data at pos %d, len %d in packet %d did not match", pos, len, txpacket);
211 }
212 
213 static void check_pkt_fuzzy(struct pbuf *p, u32_t startpos, const u8_t *mem, u32_t len)
214 {
215   int found;
216   u32_t i;
217   u8_t *data;
218 
219   fail_if((startpos + len) > p->tot_len);
220   while (startpos > p->len && p->next) {
221     startpos -= p->len;
222     p = p->next;
223   }
224   fail_if(p == NULL);
225   fail_unless(startpos + len <= p->len); /* All data we seek within same pbuf */
226 
227   found = 0;
228   data = (u8_t*)p->payload;
229   for (i = startpos; i <= (p->len - len); i++) {
230     if (memcmp(&data[i], mem, len) == 0) {
231       found = 1;
232       break;
233     }
234   }
235   fail_unless(found);
236 }
237 
238 static err_t lwip_tx_func(struct netif *netif, struct pbuf *p)
239 {
240   fail_unless(netif == &net_test);
241   txpacket++;
242 
243   if (debug) {
244     struct pbuf *pp = p;
245     /* Dump data */
246     printf("TX data (pkt %d, len %d, tick %d)", txpacket, p->tot_len, tick);
247     do {
248       int i;
249       for (i = 0; i < pp->len; i++) {
250         printf(" %02X", ((u8_t *) pp->payload)[i]);
251       }
252       if (pp->next) {
253         pp = pp->next;
254       }
255     } while (pp->next);
256     printf("\n");
257   }
258 
259   switch (tcase) {
260   case TEST_LWIP_DHCP:
261     switch (txpacket) {
262     case 1:
263     case 2:
264       {
265         const u8_t ipproto[] = { 0x08, 0x00 };
266         const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */
267         const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
268 
269         check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */
270         check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */
271 
272         check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */
273 
274         check_pkt(p, 42, bootp_start, sizeof(bootp_start));
275 
276         check_pkt(p, 53, ipaddrs, sizeof(ipaddrs));
277 
278         check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */
279 
280         check_pkt(p, 278, magic_cookie, sizeof(magic_cookie));
281 
282         /* Check dchp message type, can be at different positions */
283         if (txpacket == 1) {
284           u8_t dhcp_discover_opt[] = { 0x35, 0x01, 0x01 };
285           check_pkt_fuzzy(p, 282, dhcp_discover_opt, sizeof(dhcp_discover_opt));
286         } else if (txpacket == 2) {
287           u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 };
288           u8_t requested_ipaddr[] = { 0x32, 0x04, 0xc3, 0xaa, 0xbd, 0xc8 }; /* Ask for offered IP */
289 
290           check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt));
291           check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr));
292         }
293         break;
294       }
295     case 3:
296     case 4:
297     case 5:
298       {
299         const u8_t arpproto[] = { 0x08, 0x06 };
300 
301         check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */
302         check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */
303 
304         check_pkt(p, 12, arpproto, sizeof(arpproto)); /* eth level proto: ip */
305         break;
306       }
307       default:
308         fail();
309         break;
310     }
311     break;
312 
313   case TEST_LWIP_DHCP_NAK:
314     {
315       const u8_t ipproto[] = { 0x08, 0x00 };
316       const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */
317       const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
318       const u8_t dhcp_nak_opt[] = { 0x35, 0x01, 0x04 };
319       const u8_t requested_ipaddr[] = { 0x32, 0x04, 0xc3, 0xaa, 0xbd, 0xc8 }; /* offered IP */
320 
321       fail_unless(txpacket == 4);
322       check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */
323       check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */
324 
325       check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */
326 
327       check_pkt(p, 42, bootp_start, sizeof(bootp_start));
328 
329       check_pkt(p, 53, ipaddrs, sizeof(ipaddrs));
330 
331       check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */
332 
333       check_pkt(p, 278, magic_cookie, sizeof(magic_cookie));
334 
335       check_pkt_fuzzy(p, 282, dhcp_nak_opt, sizeof(dhcp_nak_opt)); /* NAK the ack */
336 
337       check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr));
338       break;
339     }
340 
341   case TEST_LWIP_DHCP_RELAY:
342     switch (txpacket) {
343     case 1:
344     case 2:
345       {
346         const u8_t ipproto[] = { 0x08, 0x00 };
347         const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */
348         const u8_t ipaddrs[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
349 
350         check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */
351         check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */
352 
353         check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */
354 
355         check_pkt(p, 42, bootp_start, sizeof(bootp_start));
356 
357         check_pkt(p, 53, ipaddrs, sizeof(ipaddrs));
358 
359         check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */
360 
361         check_pkt(p, 278, magic_cookie, sizeof(magic_cookie));
362 
363         /* Check dchp message type, can be at different positions */
364         if (txpacket == 1) {
365           u8_t dhcp_discover_opt[] = { 0x35, 0x01, 0x01 };
366           check_pkt_fuzzy(p, 282, dhcp_discover_opt, sizeof(dhcp_discover_opt));
367         } else if (txpacket == 2) {
368           u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 };
369           u8_t requested_ipaddr[] = { 0x32, 0x04, 0x4f, 0x8a, 0x33, 0x05 }; /* Ask for offered IP */
370 
371           check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt));
372           check_pkt_fuzzy(p, 282, requested_ipaddr, sizeof(requested_ipaddr));
373         }
374         break;
375       }
376     case 3:
377     case 4:
378     case 5:
379     case 6:
380       {
381         const u8_t arpproto[] = { 0x08, 0x06 };
382 
383         check_pkt(p, 0, broadcast, 6); /* eth level dest: broadcast */
384         check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */
385 
386         check_pkt(p, 12, arpproto, sizeof(arpproto)); /* eth level proto: ip */
387         break;
388       }
389     case 7:
390       {
391         const u8_t fake_arp[6] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xab };
392         const u8_t ipproto[] = { 0x08, 0x00 };
393         const u8_t bootp_start[] = { 0x01, 0x01, 0x06, 0x00}; /* bootp request, eth, hwaddr len 6, 0 hops */
394         const u8_t ipaddrs[] = { 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
395         const u8_t dhcp_request_opt[] = { 0x35, 0x01, 0x03 };
396 
397         check_pkt(p, 0, fake_arp, 6); /* eth level dest: broadcast */
398         check_pkt(p, 6, netif->hwaddr, 6); /* eth level src: unit mac */
399 
400         check_pkt(p, 12, ipproto, sizeof(ipproto)); /* eth level proto: ip */
401 
402         check_pkt(p, 42, bootp_start, sizeof(bootp_start));
403 
404         check_pkt(p, 53, ipaddrs, sizeof(ipaddrs));
405 
406         check_pkt(p, 70, netif->hwaddr, 6); /* mac addr inside bootp */
407 
408         check_pkt(p, 278, magic_cookie, sizeof(magic_cookie));
409 
410         /* Check dchp message type, can be at different positions */
411         check_pkt_fuzzy(p, 282, dhcp_request_opt, sizeof(dhcp_request_opt));
412         break;
413       }
414     default:
415       fail();
416       break;
417     }
418     break;
419 
420   default:
421     break;
422   }
423 
424   return ERR_OK;
425 }
426 
427 /*
428  * Test basic happy flow DHCP session.
429  * Validate that xid is checked.
430  */
431 START_TEST(test_dhcp)
432 {
433   ip4_addr_t addr;
434   ip4_addr_t netmask;
435   ip4_addr_t gw;
436   int i;
437   u32_t xid;
438   LWIP_UNUSED_ARG(_i);
439 
440   tcase = TEST_LWIP_DHCP;
441   setdebug(0);
442 
443   IP4_ADDR(&addr, 0, 0, 0, 0);
444   IP4_ADDR(&netmask, 0, 0, 0, 0);
445   IP4_ADDR(&gw, 0, 0, 0, 0);
446 
447   netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
448   netif_set_up(&net_test);
449 
450   dhcp_start(&net_test);
451 
452   fail_unless(txpacket == 1); /* DHCP discover sent */
453   xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */
454   memcpy(&dhcp_offer[46], &xid, 4);
455   send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer));
456 
457   /* IP addresses should be zero */
458   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
459   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
460   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
461 
462   fail_unless(txpacket == 1, "TX %d packets, expected 1", txpacket); /* Nothing more sent */
463   xid = htonl(netif_dhcp_data(&net_test)->xid);
464   memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */
465   send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer));
466 
467   fail_unless(txpacket == 2, "TX %d packets, expected 2", txpacket); /* DHCP request sent */
468   xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */
469   memcpy(&dhcp_ack[46], &xid, 4);
470   send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack));
471 
472   fail_unless(txpacket == 2, "TX %d packets, still expected 2", txpacket); /* No more sent */
473   xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */
474   memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */
475   send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack));
476 
477   for (i = 0; i < 20; i++) {
478     tick_lwip();
479   }
480   fail_unless(txpacket == 5, "TX %d packets, expected 5", txpacket); /* ARP requests sent */
481 
482   /* Interface up */
483   fail_unless(netif_is_up(&net_test));
484 
485   /* Now it should have taken the IP */
486   IP4_ADDR(&addr, 195, 170, 189, 200);
487   IP4_ADDR(&netmask, 255, 255, 255, 0);
488   IP4_ADDR(&gw, 195, 170, 189, 171);
489   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
490   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
491   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
492 
493   netif_remove(&net_test);
494 }
495 END_TEST
496 
497 /*
498  * Test that IP address is not taken and NAK is sent if someone
499  * replies to ARP requests for the offered address.
500  */
501 START_TEST(test_dhcp_nak)
502 {
503   ip4_addr_t addr;
504   ip4_addr_t netmask;
505   ip4_addr_t gw;
506   u32_t xid;
507   LWIP_UNUSED_ARG(_i);
508 
509   tcase = TEST_LWIP_DHCP;
510   setdebug(0);
511 
512   IP4_ADDR(&addr, 0, 0, 0, 0);
513   IP4_ADDR(&netmask, 0, 0, 0, 0);
514   IP4_ADDR(&gw, 0, 0, 0, 0);
515 
516   netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
517   netif_set_up(&net_test);
518 
519   dhcp_start(&net_test);
520 
521   fail_unless(txpacket == 1); /* DHCP discover sent */
522   xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */
523   memcpy(&dhcp_offer[46], &xid, 4);
524   send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer));
525 
526   /* IP addresses should be zero */
527   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
528   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
529   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
530 
531   fail_unless(txpacket == 1); /* Nothing more sent */
532   xid = htonl(netif_dhcp_data(&net_test)->xid);
533   memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */
534   send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer));
535 
536   fail_unless(txpacket == 2); /* DHCP request sent */
537   xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */
538   memcpy(&dhcp_ack[46], &xid, 4);
539   send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack));
540 
541   fail_unless(txpacket == 2); /* No more sent */
542   xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */
543   memcpy(&dhcp_ack[46], &xid, 4); /* insert transaction id */
544   send_pkt(&net_test, dhcp_ack, sizeof(dhcp_ack));
545 
546   fail_unless(txpacket == 3); /* ARP request sent */
547 
548   tcase = TEST_LWIP_DHCP_NAK; /* Switch testcase */
549 
550   /* Send arp reply, mark offered IP as taken */
551   send_pkt(&net_test, arpreply, sizeof(arpreply));
552 
553   fail_unless(txpacket == 4); /* DHCP nak sent */
554 
555   netif_remove(&net_test);
556 }
557 END_TEST
558 
559 /*
560  * Test case based on captured data where
561  * replies are sent from a different IP than the
562  * one the client unicasted to.
563  */
564 START_TEST(test_dhcp_relayed)
565 {
566   u8_t relay_offer[] = {
567   0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d,
568   0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60,
569   0x08, 0x00, 0x45, 0x00,
570   0x01, 0x38, 0xfd, 0x53, 0x00, 0x00, 0x40, 0x11,
571   0x78, 0x46, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a,
572   0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24,
573   0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x51, 0x35,
574   0xb6, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
575   0x00, 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00,
576   0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23,
577   0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00,
578   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
579   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
580   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
581   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
582   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
583   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
584   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
585   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
586   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
587   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
588   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
589   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
590   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
591   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
592   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
593   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
594   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
595   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
596   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
597   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
598   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
599   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
600   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
601   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
602   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82,
603   0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00,
604   0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08,
605   0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1,
606   0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04,
607   0x00, 0x00, 0x54, 0x49, 0x35, 0x01, 0x02, 0x36,
608   0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff
609   };
610 
611   u8_t relay_ack1[] = {
612   0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x22,
613   0x93, 0x5a, 0xf7, 0x60, 0x08, 0x00, 0x45, 0x00,
614   0x01, 0x38, 0xfd, 0x55, 0x00, 0x00, 0x40, 0x11,
615   0x78, 0x44, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a,
616   0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24,
617   0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x51, 0x35,
618   0xb6, 0xa1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
619   0x00, 0x00, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00,
620   0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23,
621   0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00,
622   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
623   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
625   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
626   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
627   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
628   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
629   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
630   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
631   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
632   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
633   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
634   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
635   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
636   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
637   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
638   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
639   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
640   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
641   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
642   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
643   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
644   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
645   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
646   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82,
647   0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00,
648   0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08,
649   0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1,
650   0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04,
651   0x00, 0x00, 0x54, 0x49, 0x35, 0x01, 0x05, 0x36,
652   0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff
653   };
654 
655   u8_t relay_ack2[] = {
656   0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d,
657   0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60,
658   0x08, 0x00, 0x45, 0x00,
659   0x01, 0x38, 0xfa, 0x18, 0x00, 0x00, 0x40, 0x11,
660   0x7b, 0x81, 0x4f, 0x8a, 0x32, 0x02, 0x4f, 0x8a,
661   0x33, 0x05, 0x00, 0x43, 0x00, 0x44, 0x01, 0x24,
662   0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x49, 0x8b,
663   0x6e, 0xab, 0x00, 0x00, 0x00, 0x00, 0x4f, 0x8a,
664   0x33, 0x05, 0x4f, 0x8a, 0x33, 0x05, 0x00, 0x00,
665   0x00, 0x00, 0x0a, 0xb5, 0x04, 0x01, 0x00, 0x23,
666   0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00,
667   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
668   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
669   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
670   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
671   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
672   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
674   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
676   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
677   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
678   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
680   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
681   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
682   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
684   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
686   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
688   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
691   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82,
692   0x53, 0x63, 0x01, 0x04, 0xff, 0xff, 0xfe, 0x00,
693   0x03, 0x04, 0x4f, 0x8a, 0x32, 0x01, 0x06, 0x08,
694   0x4f, 0x8a, 0x00, 0xb4, 0x55, 0x08, 0x1f, 0xd1,
695   0x1c, 0x04, 0x4f, 0x8a, 0x33, 0xff, 0x33, 0x04,
696   0x00, 0x00, 0x54, 0x60, 0x35, 0x01, 0x05, 0x36,
697   0x04, 0x0a, 0xb5, 0x04, 0x01, 0xff };
698 
699   const u8_t arp_resp[] = {
700   0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* DEST */
701   0x00, 0x22, 0x93, 0x5a, 0xf7, 0x60, /* SRC */
702   0x08, 0x06, /* Type: ARP */
703   0x00, 0x01, /* HW: Ethernet */
704   0x08, 0x00, /* PROTO: IP */
705   0x06, /* HW size */
706   0x04, /* PROTO size */
707   0x00, 0x02, /* OPCODE: Reply */
708 
709   0x12, 0x34, 0x56, 0x78, 0x9a, 0xab, /* Target MAC */
710   0x4f, 0x8a, 0x32, 0x01, /* Target IP */
711 
712   0x00, 0x23, 0xc1, 0x00, 0x06, 0x50, /* src mac */
713   0x4f, 0x8a, 0x33, 0x05, /* src ip */
714 
715   /* Padding follows.. */
716   0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
717   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
718   0x00, 0x00, 0x00, 0x00 };
719 
720   ip4_addr_t addr;
721   ip4_addr_t netmask;
722   ip4_addr_t gw;
723   int i;
724   u32_t xid;
725   LWIP_UNUSED_ARG(_i);
726 
727   tcase = TEST_LWIP_DHCP_RELAY;
728   setdebug(0);
729 
730   IP4_ADDR(&addr, 0, 0, 0, 0);
731   IP4_ADDR(&netmask, 0, 0, 0, 0);
732   IP4_ADDR(&gw, 0, 0, 0, 0);
733 
734   netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
735   netif_set_up(&net_test);
736 
737   dhcp_start(&net_test);
738 
739   fail_unless(txpacket == 1); /* DHCP discover sent */
740 
741   /* IP addresses should be zero */
742   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
743   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
744   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
745 
746   fail_unless(txpacket == 1); /* Nothing more sent */
747   xid = htonl(netif_dhcp_data(&net_test)->xid);
748   memcpy(&relay_offer[46], &xid, 4); /* insert correct transaction id */
749   send_pkt(&net_test, relay_offer, sizeof(relay_offer));
750 
751   /* request sent? */
752   fail_unless(txpacket == 2, "txpkt = %d, should be 2", txpacket);
753   xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */
754   memcpy(&relay_ack1[46], &xid, 4); /* insert transaction id */
755   send_pkt(&net_test, relay_ack1, sizeof(relay_ack1));
756 
757   for (i = 0; i < 25; i++) {
758     tick_lwip();
759   }
760   fail_unless(txpacket == 5, "txpkt should be 5, is %d", txpacket); /* ARP requests sent */
761 
762   /* Interface up */
763   fail_unless(netif_is_up(&net_test));
764 
765   /* Now it should have taken the IP */
766   IP4_ADDR(&addr, 79, 138, 51, 5);
767   IP4_ADDR(&netmask, 255, 255, 254, 0);
768   IP4_ADDR(&gw, 79, 138, 50, 1);
769   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
770   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
771   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
772 
773   fail_unless(txpacket == 5, "txpacket = %d", txpacket);
774 
775   for (i = 0; i < 108000 - 25; i++) {
776     tick_lwip();
777   }
778 
779   fail_unless(netif_is_up(&net_test));
780   fail_unless(txpacket == 6, "txpacket = %d", txpacket);
781 
782   /* We need to send arp response here.. */
783 
784   send_pkt(&net_test, arp_resp, sizeof(arp_resp));
785 
786   fail_unless(txpacket == 7, "txpacket = %d", txpacket);
787   fail_unless(netif_is_up(&net_test));
788 
789   xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */
790   memcpy(&relay_ack2[46], &xid, 4); /* insert transaction id */
791   send_pkt(&net_test, relay_ack2, sizeof(relay_ack2));
792 
793   for (i = 0; i < 100000; i++) {
794     tick_lwip();
795   }
796 
797   fail_unless(txpacket == 7, "txpacket = %d", txpacket);
798 
799   netif_remove(&net_test);
800 
801 }
802 END_TEST
803 
804 START_TEST(test_dhcp_nak_no_endmarker)
805 {
806   ip4_addr_t addr;
807   ip4_addr_t netmask;
808   ip4_addr_t gw;
809 
810   u8_t dhcp_nack_no_endmarker[] = {
811     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x54, 0x75,
812     0xd0, 0x26, 0xd0, 0x0d, 0x08, 0x00, 0x45, 0x00,
813     0x01, 0x15, 0x38, 0x86, 0x00, 0x00, 0xff, 0x11,
814     0xc0, 0xa8, 0xc0, 0xa8, 0x01, 0x01, 0xff, 0xff,
815     0xff, 0xff, 0x00, 0x43, 0x00, 0x44, 0x01, 0x01,
816     0x00, 0x00, 0x02, 0x01, 0x06, 0x00, 0x7a, 0xcb,
817     0xba, 0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
818     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
819     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23,
820     0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00,
821     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
822     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
823     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
824     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
825     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
826     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
827     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
828     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
829     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
830     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
831     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
832     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
833     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
834     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
835     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
836     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
837     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
838     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
839     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
840     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
841     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
842     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
843     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
844     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
845     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82,
846     0x53, 0x63, 0x35, 0x01, 0x06, 0x36, 0x04, 0xc0,
847     0xa8, 0x01, 0x01, 0x31, 0xef, 0xad, 0x72, 0x31,
848     0x43, 0x4e, 0x44, 0x30, 0x32, 0x35, 0x30, 0x43,
849     0x52, 0x47, 0x44, 0x38, 0x35, 0x36, 0x3c, 0x08,
850     0x4d, 0x53, 0x46, 0x54, 0x20, 0x35, 0x2e, 0x30,
851     0x37, 0x0d, 0x01, 0x0f, 0x03, 0x06, 0x2c, 0x2e,
852     0x2f, 0x1f, 0x21, 0x79, 0xf9, 0x2b, 0xfc, 0xff,
853     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x71,
854     0xf3, 0x5b, 0xe2, 0x71, 0x2e, 0x01, 0x08, 0x03,
855     0x04, 0xc0, 0xa8, 0x01, 0x01, 0xff, 0xeb, 0x1e,
856     0x44, 0xec, 0xeb, 0x1e, 0x30, 0x37, 0x0c, 0x01,
857     0x0f, 0x03, 0x06, 0x2c, 0x2e, 0x2f, 0x1f, 0x21,
858     0x79, 0xf9, 0x2b, 0xff, 0x25, 0xc0, 0x09, 0xd6,
859     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
860     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
861   };
862   u32_t xid;
863   LWIP_UNUSED_ARG(_i);
864 
865   tcase = TEST_LWIP_DHCP_NAK_NO_ENDMARKER;
866   setdebug(0);
867 
868   IP4_ADDR(&addr, 0, 0, 0, 0);
869   IP4_ADDR(&netmask, 0, 0, 0, 0);
870   IP4_ADDR(&gw, 0, 0, 0, 0);
871 
872   netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
873   netif_set_up(&net_test);
874 
875   dhcp_start(&net_test);
876 
877   fail_unless(txpacket == 1); /* DHCP discover sent */
878   xid = netif_dhcp_data(&net_test)->xid; /* Write bad xid, not using htonl! */
879   memcpy(&dhcp_offer[46], &xid, 4);
880   send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer));
881 
882   /* IP addresses should be zero */
883   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
884   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
885   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
886 
887   fail_unless(txpacket == 1); /* Nothing more sent */
888   xid = htonl(netif_dhcp_data(&net_test)->xid);
889   memcpy(&dhcp_offer[46], &xid, 4); /* insert correct transaction id */
890   send_pkt(&net_test, dhcp_offer, sizeof(dhcp_offer));
891 
892   fail_unless(netif_dhcp_data(&net_test)->state == DHCP_STATE_REQUESTING);
893 
894   fail_unless(txpacket == 2); /* No more sent */
895   xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */
896   memcpy(&dhcp_nack_no_endmarker[46], &xid, 4); /* insert transaction id */
897   send_pkt(&net_test, dhcp_nack_no_endmarker, sizeof(dhcp_nack_no_endmarker));
898 
899   /* NAK should put us in another state for a while, no other way detecting it */
900   fail_unless(netif_dhcp_data(&net_test)->state != DHCP_STATE_REQUESTING);
901 
902   netif_remove(&net_test);
903 }
904 END_TEST
905 
906 START_TEST(test_dhcp_invalid_overload)
907 {
908   u8_t dhcp_offer_invalid_overload[] = {
909       0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, /* To unit */
910       0x00, 0x0F, 0xEE, 0x30, 0xAB, 0x22, /* From Remote host */
911       0x08, 0x00, /* Protocol: IP */
912       0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00, 0x80, 0x11, 0x36, 0xcc, 0xc3, 0xaa, 0xbd, 0xab, 0xc3, 0xaa, 0xbd, 0xc8, /* IP header */
913       0x00, 0x43, 0x00, 0x44, 0x01, 0x34, 0x00, 0x00, /* UDP header */
914 
915       0x02, /* Type == Boot reply */
916       0x01, 0x06, /* Hw Ethernet, 6 bytes addrlen */
917       0x00, /* 0 hops */
918       0xAA, 0xAA, 0xAA, 0xAA, /* Transaction id, will be overwritten */
919       0x00, 0x00, /* 0 seconds elapsed */
920       0x00, 0x00, /* Flags (unicast) */
921       0x00, 0x00, 0x00, 0x00, /* Client ip */
922       0xc3, 0xaa, 0xbd, 0xc8, /* Your IP */
923       0xc3, 0xaa, 0xbd, 0xab, /* DHCP server ip */
924       0x00, 0x00, 0x00, 0x00, /* relay agent */
925       0x00, 0x23, 0xc1, 0xde, 0xd0, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MAC addr + padding */
926 
927       /* Empty server name */
928       0x34, 0x01, 0x02, 0xff, /* Overload: SNAME + END */
929       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
930       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
931       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
932       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
933       /* Empty boot file name */
934       0x34, 0x01, 0x01, 0xff, /* Overload FILE + END */
935       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
936       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
937       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
938       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
939       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
940       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
941       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
942       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
943 
944       0x63, 0x82, 0x53, 0x63, /* Magic cookie */
945       0x35, 0x01, 0x02, /* Message type: Offer */
946       0x36, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Server identifier (IP) */
947       0x33, 0x04, 0x00, 0x00, 0x00, 0x78, /* Lease time 2 minutes */
948       0x03, 0x04, 0xc3, 0xaa, 0xbd, 0xab, /* Router IP */
949       0x01, 0x04, 0xff, 0xff, 0xff, 0x00, /* Subnet mask */
950       0x34, 0x01, 0x03, /* Overload: FILE + SNAME */
951       0xff, /* End option */
952       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
953       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Padding */
954   };
955   ip4_addr_t addr;
956   ip4_addr_t netmask;
957   ip4_addr_t gw;
958   u32_t xid;
959   LWIP_UNUSED_ARG(_i);
960 
961   tcase = TEST_LWIP_DHCP_INVALID_OVERLOAD;
962   setdebug(0);
963 
964   IP4_ADDR(&addr, 0, 0, 0, 0);
965   IP4_ADDR(&netmask, 0, 0, 0, 0);
966   IP4_ADDR(&gw, 0, 0, 0, 0);
967 
968   netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
969   netif_set_up(&net_test);
970 
971   dhcp_start(&net_test);
972 
973   fail_unless(txpacket == 1); /* DHCP discover sent */
974   xid = htonl(netif_dhcp_data(&net_test)->xid);
975   memcpy(&dhcp_offer_invalid_overload[46], &xid, 4); /* insert correct transaction id */
976   dhcp_offer_invalid_overload[311] = 3;
977   send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload));
978   /* IP addresses should be zero */
979   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
980   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
981   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
982   fail_unless(txpacket == 1); /* Nothing more sent */
983 
984   dhcp_offer_invalid_overload[311] = 2;
985   send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload));
986   /* IP addresses should be zero */
987   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
988   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
989   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
990   fail_unless(txpacket == 1); /* Nothing more sent */
991 
992   dhcp_offer_invalid_overload[311] = 1;
993   send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer_invalid_overload));
994   /* IP addresses should be zero */
995   fail_if(memcmp(&addr, &net_test.ip_addr, sizeof(ip4_addr_t)));
996   fail_if(memcmp(&netmask, &net_test.netmask, sizeof(ip4_addr_t)));
997   fail_if(memcmp(&gw, &net_test.gw, sizeof(ip4_addr_t)));
998   fail_unless(txpacket == 1); /* Nothing more sent */
999 
1000   dhcp_offer_invalid_overload[311] = 0;
1001   send_pkt(&net_test, dhcp_offer_invalid_overload, sizeof(dhcp_offer));
1002 
1003   fail_unless(netif_dhcp_data(&net_test)->state == DHCP_STATE_REQUESTING);
1004 
1005   fail_unless(txpacket == 2); /* No more sent */
1006   xid = htonl(netif_dhcp_data(&net_test)->xid); /* xid updated */
1007 
1008   netif_remove(&net_test);
1009 }
1010 END_TEST
1011 
1012 /** Create the suite including all tests for this module */
1013 Suite *
1014 dhcp_suite(void)
1015 {
1016   testfunc tests[] = {
1017     TESTFUNC(test_dhcp),
1018     TESTFUNC(test_dhcp_nak),
1019     TESTFUNC(test_dhcp_relayed),
1020     TESTFUNC(test_dhcp_nak_no_endmarker),
1021     TESTFUNC(test_dhcp_invalid_overload)
1022   };
1023   return create_suite("DHCP", tests, sizeof(tests)/sizeof(testfunc), dhcp_setup, dhcp_teardown);
1024 }
1025