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