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