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