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