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
9struct netif net_test;
10
11static const u8_t broadcast[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
12
13static const u8_t magic_cookie[] = { 0x63, 0x82, 0x53, 0x63 };
14
15static 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
59static 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
103static 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
118static int txpacket;
119static 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
128static int debug = 0;
129static void setdebug(int a) {debug = a;}
130
131static int tick = 0;
132static 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
143static 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
167static err_t lwip_tx_func(struct netif *netif, struct pbuf *p);
168
169static 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
189static void dhcp_setup(void)
190{
191  txpacket = 0;
192  lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
193}
194
195static void dhcp_teardown(void)
196{
197  lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
198}
199
200static 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
216static 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
241static 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 */
434START_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}
502END_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 */
508START_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}
568END_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 */
575START_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}
817END_TEST
818
819START_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}
933END_TEST
934
935START_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}
1043END_TEST
1044
1045/** Create the suite including all tests for this module */
1046Suite *
1047dhcp_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