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