1 /* This is a small demo of the NetX Duo DHCPv6 Client for the high-performance NetX Duo stack. */
2
3 #include <stdio.h>
4 #include "tx_api.h"
5 #include "nx_api.h"
6 #include "nxd_dhcpv6_client.h"
7
8 #ifdef FEATURE_NX_IPV6
9 #define DEMO_STACK_SIZE 2048
10
11 /* Set the client address, and request these address from DHCPv6 Server. */
12 /*
13 #define NX_DHCPV6_REQUEST_IA_ADDRESS
14 */
15
16 /* Set the list of DHCPv6 option data (timezone, DNS server, timer server, domain name)to get from the DHCPv6 server. */
17
18 #define NX_DHCPV6_REQUEST_OPTION
19
20
21 /* Add the fully qualified domain name to request whether the DHCPv6 server SHOULD or SHOULD NOT perform the AAAA RR or DNS updates. */
22
23 #define NX_DHCPV6_REQUEST_FQDN_OPTION
24
25
26 /* Define the ThreadX and NetX object control blocks... */
27
28 NX_PACKET_POOL pool_0;
29 TX_THREAD thread_client;
30 NX_IP client_ip;
31
32 /* Define the Client and Server instances. */
33
34 NX_DHCPV6 dhcp_client;
35
36 /* Define the error counter used in the demo application... */
37 ULONG error_counter;
38 CHAR *pointer;
39
40 /* Define thread prototypes. */
41 void thread_client_entry(ULONG thread_input);
42
43 /***** Substitute your ethernet driver entry function here *********/
44 extern VOID _nx_ram_network_driver(NX_IP_DRIVER *driver_req_ptr);
45
46 /* Declare DHCPv6 Client callbacks */
47 VOID dhcpv6_state_change_notify(NX_DHCPV6 *dhcpv6_ptr, UINT old_state, UINT new_state);
48 VOID dhcpv6_server_error_handler(NX_DHCPV6 *dhcpv6_ptr, UINT op_code, UINT status_code, UINT message_type);
49
50 /* Set up globals for tracking changes to DHCPv6 Client from callback services. */
51 UINT state_changes = 0;
52 UINT address_expired = 0;
53 UINT address_failed_dad = 0;
54 UINT bound_addresses = 0;
55 UINT address_not_assigned = 0;
56 UINT server_errors = 0;
57
58 /* Define some DHCPv6 parameters. */
59
60 #define DHCPV6_IANA_ID 0xABCDEFAB
61 #define DHCPV6_T1 NX_DHCPV6_INFINITE_LEASE
62 #define DHCPV6_T2 NX_DHCPV6_INFINITE_LEASE
63 #define DHCPV6_RENEW_TIME NX_DHCPV6_INFINITE_LEASE
64 #define DHCPV6_REBIND_TIME NX_DHCPV6_INFINITE_LEASE
65 #define PACKET_PAYLOAD 500
66 #define PACKET_POOL_SIZE (5*PACKET_PAYLOAD)
67
68 /* Define main entry point. */
69
main()70 int main()
71 {
72
73 /* Enter the ThreadX kernel. */
74 tx_kernel_enter();
75 }
76
77
78 /* Define what the initial system looks like. */
79
tx_application_define(void * first_unused_memory)80 void tx_application_define(void *first_unused_memory)
81 {
82
83 UINT status;
84
85 /* Setup the working pointer. */
86 pointer = (CHAR *) first_unused_memory;
87
88 /* Create the Client thread. */
89 status = tx_thread_create(&thread_client, "Client thread", thread_client_entry, 0,
90 pointer, DEMO_STACK_SIZE, 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START);
91
92 /* Check for IP create errors. */
93 if (status)
94 {
95 error_counter++;
96 return;
97 }
98
99 pointer = pointer + DEMO_STACK_SIZE;
100
101 /* Initialize the NetX system. */
102 nx_system_initialize();
103
104 /* Create a packet pool. */
105 status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1024, pointer, PACKET_POOL_SIZE);
106
107 pointer = pointer + PACKET_POOL_SIZE;
108
109 /* Check for pool creation error. */
110 if (status)
111 {
112 error_counter++;
113 return;
114 }
115
116 /* Create a Client IP instance. */
117 status = nx_ip_create(&client_ip, "Client IP", IP_ADDRESS(0, 0, 0, 0),
118 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
119 pointer, 2048, 1);
120
121 pointer = pointer + 2048;
122
123 /* Check for IP create errors. */
124 if (status)
125 {
126 error_counter++;
127 return;
128 }
129
130 /* Enable UDP traffic for sending DHCPv6 messages. */
131 status = nx_udp_enable(&client_ip);
132
133 /* Check for UDP enable errors. */
134 if (status)
135 {
136 error_counter++;
137 return;
138 }
139
140 /* Enable ICMP. */
141 status = nx_icmp_enable(&client_ip);
142
143 /* Check for ICMP enable errors. */
144 if (status)
145 {
146 error_counter++;
147 return;
148 }
149
150 /* Create the DHCPv6 Client. */
151 status = nx_dhcpv6_client_create(&dhcp_client, &client_ip, "DHCPv6 Client",
152 &pool_0, pointer, 2048, dhcpv6_state_change_notify,
153 dhcpv6_server_error_handler);
154
155 /* Check for errors. */
156 if (status)
157 {
158 error_counter++;
159 return;
160 }
161
162 /* Update the stack pointer because we need it again. */
163 pointer = pointer + 2048;
164
165 /* Yield control to DHCPv6 threads and ThreadX. */
166 return;
167 }
168
169
170 /* Define the Client host application thread. */
171
thread_client_entry(ULONG thread_input)172 void thread_client_entry(ULONG thread_input)
173 {
174
175 UINT status;
176 ULONG T1, T2;
177 UINT address_count;
178 UINT address_index = 0;
179 NXD_ADDRESS valid_ipv6_address;
180 ULONG preferred_lifetime;
181 ULONG valid_lifetime;
182 UINT ia_count = 1;
183
184 #ifdef NX_DHCPV6_REQUEST_IA_ADDRESS
185 NXD_ADDRESS ipv6_address;
186 #endif
187
188 #ifdef NX_DHCPV6_REQUEST_OPTION
189 UCHAR buffer[200];
190 NXD_ADDRESS dns_server;
191 #endif
192
193 #ifdef NX_DHCPV6_CLIENT_RESTORE_STATE
194 ULONG current_time;
195 ULONG elapsed_time;
196 NX_DHCPV6_CLIENT_RECORD dhcpv6_client_record;
197 #endif
198
199 NX_PARAMETER_NOT_USED(thread_input);
200
201 state_changes = 0;
202
203 /* Establish the link local address for the host. The RAM driver creates
204 a virtual MAC address of 0x1122334456. */
205 status = nxd_ipv6_address_set(&client_ip, 0, NX_NULL, 10, NULL);
206
207 if (status)
208 {
209 error_counter++;
210 return;
211 }
212
213 /* Let NetX Duo get initialized. */
214 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
215
216 /* Enable the Client IP for IPv6 and ICMPv6 services. */
217 nxd_ipv6_enable(&client_ip);
218 nxd_icmp_enable(&client_ip);
219
220 /* Create a Link Layer Plus Time DUID for the DHCPv6 Client. Set time ID field
221 to NULL; the DHCPv6 Client API will supply one. */
222 status = nx_dhcpv6_create_client_duid(&dhcp_client, NX_DHCPV6_DUID_TYPE_LINK_TIME,
223 NX_DHCPV6_CLIENT_HARDWARE_TYPE_ETHERNET, 0);
224
225 if (status != NX_SUCCESS)
226 {
227 error_counter++;
228 return;
229 }
230
231 /* Create the DHCPv6 client's Identity Association (IA-NA) now.
232
233 Note that if this host had already been assigned in IPv6 lease, it
234 would have to use the assigned T1 and T2 values in loading the DHCPv6
235 client with an IANA block.
236 */
237 status = nx_dhcpv6_create_client_iana(&dhcp_client, DHCPV6_IANA_ID, DHCPV6_T1, DHCPV6_T2);
238
239 if (status != NX_SUCCESS)
240 {
241 error_counter++;
242 return;
243 }
244
245 #ifdef NX_DHCPV6_REQUEST_IA_ADDRESS
246 memset(&ipv6_address,0x0, sizeof(NXD_ADDRESS));
247 ipv6_address.nxd_ip_version = NX_IP_VERSION_V6;
248 ipv6_address.nxd_ip_address.v6[0] = 0x3ffe0501;
249 ipv6_address.nxd_ip_address.v6[1] = 0xffff0100;
250 ipv6_address.nxd_ip_address.v6[2] = 0x00000000;
251 ipv6_address.nxd_ip_address.v6[3] = 0x0000abcd;
252
253 /* Create an IA address option.
254 Note that if this host had already been assigned in IPv6 lease, it
255 would have to use the assigned IPv6 address, preferred and valid lifetime
256 values in loading the DHCPv6 Client with an IA block.
257 */
258 status = nx_dhcpv6_add_client_ia(&dhcp_client, &ipv6_address,DHCPV6_RENEW_TIME, DHCPV6_REBIND_TIME);
259
260 if (status != NX_SUCCESS)
261 {
262 error_counter++;
263 return;
264 }
265
266 /* If the DHCPv6 Client is configured for a maximum number of IA addresses
267 greater than 1, we can add another IA address if the device requires
268 multiple global IPv6 addresses. */
269 if(NX_DHCPV6_MAX_IA_ADDRESS >= 2)
270 {
271 memset(&ipv6_address,0x0, sizeof(NXD_ADDRESS));
272 ipv6_address.nxd_ip_version = NX_IP_VERSION_V6;
273 ipv6_address.nxd_ip_address.v6[0] = 0x3ffe0501;
274 ipv6_address.nxd_ip_address.v6[1] = 0xffff0100;
275 ipv6_address.nxd_ip_address.v6[2] = 0x00000000;
276 ipv6_address.nxd_ip_address.v6[3] = 0x00001234;
277
278 /* Add another IA address option. */
279 status = nx_dhcpv6_add_client_ia(&dhcp_client, &ipv6_address, DHCPV6_RENEW_TIME, DHCPV6_REBIND_TIME);
280
281 if (status != NX_SUCCESS)
282 {
283 error_counter++;
284 return;
285 }
286 }
287 #endif /* NX_DHCPV6_REQUEST_IA_ADDRESS */
288
289 #ifdef NX_DHCPV6_REQUEST_OPTION
290 /* Set the list of DHCPv6 option data to get from the DHCPv6 server if needed. */
291 nx_dhcpv6_request_option_timezone(&dhcp_client, NX_TRUE);
292 nx_dhcpv6_request_option_DNS_server(&dhcp_client, NX_TRUE);
293 nx_dhcpv6_request_option_time_server(&dhcp_client, NX_TRUE);
294 nx_dhcpv6_request_option_domain_name(&dhcp_client, NX_TRUE);
295 #endif /* NX_DHCPV6_REQUEST_OPTION */
296
297
298 #ifdef NX_DHCPV6_REQUEST_FQDN_OPTION
299 /* Set the DHCPv6 Client FQDN option.
300 operation: NX_DHCPV6_CLIENT_DESIRES_UPDATE_AAAA_RR DHCPv6 Client choose to updating the FQDN-to-IPv6 address mapping for FQDN and address(es) used by the client.
301 NX_DHCPV6_CLIENT_DESIRES_SERVER_DO_DNS_UPDATE DHCPv6 Client choose to updating the FQDN-to-IPv6 address mapping for FQDN and address(es) used by the client to the server.
302 NX_DHCPV6_CLIENT_DESIRES_NO_SERVER_DNS_UPDATE DHCPv6 Client choose to request that the server perform no DNS updatest on its behalf. */
303 nx_dhcpv6_request_option_FQDN(&dhcp_client, "DHCPv6-Client", NX_DHCPV6_CLIENT_DESIRES_UPDATE_AAAA_RR);
304 #endif /* NX_DHCPV6_REQUEST_FQDN_OPTION */
305
306 /* Start up the NetX DHCPv6 Client thread task. */
307 status = nx_dhcpv6_start(&dhcp_client);
308
309 /* Check for errors. */
310 if (status != NX_SUCCESS)
311 {
312
313 error_counter++;
314 return;
315 }
316
317 /* Start the DHCPv6 by sending a Solicit message out on the network. */
318 status = nx_dhcpv6_request_solicit(&dhcp_client);
319
320 /* Check status. */
321 if (status != NX_SUCCESS)
322 {
323
324 error_counter++;
325 return;
326 }
327
328 /* Is the DHCPv6 Client request for address assignment successfully started? */
329 if (status == NX_SUCCESS)
330 {
331
332 /* If Duplicate Address Detection (DAD) is enabled in NetX Duo, e.g. #NX_DISABLE_IPV6_DAD
333 not defined, allow time for NetX Duo to verify the address is unique on our network.
334 */
335 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
336
337 /* Check the bound address. */
338 if (bound_addresses != ia_count)
339 {
340
341 /* Attempt to find out why DHCPv6 failed, where...*/
342
343 if (server_errors > 0)
344 {
345 /* Actually you would compare server_error count with number of IA's added
346 to determine if any addresses were assigned. */
347 printf("Server error, not all address assigned\n");
348 }
349
350 if (address_not_assigned > 0)
351 {
352 /* Actually you would compare address not assigned count with number of IA's added
353 to determine if any addresses were assigned. */
354
355 printf("No servers responded to some or all of our IAs\n");
356 }
357
358 }
359
360 /* Regardless if the DHCPv6 Client achieved a bound state, check for DAD
361 failures. */
362 if (address_failed_dad > 0)
363 {
364 /* Actually you would compare failed dad count with number of IA's added
365 to determine if any addresses were assigned. */
366
367 printf("Some or all of our IAs failed DAD\n");
368
369 }
370
371 /* Successfully assigned IPv6 addresses! */
372
373 /* Get the count of valid IPv6 address obtained by DHCPv6. */
374 status = nx_dhcpv6_get_valid_ip_address_count(&dhcp_client, &address_count);
375
376 /* Check status. */
377 if (status != NX_SUCCESS)
378 {
379 error_counter++;
380 }
381
382 /* Get the IPv6 address and related lifetimes by address index. This index is the
383 index into the DHCPv6 Client address table. Not to be confused with the IP
384 instance address table! */
385 status = nx_dhcpv6_get_valid_ip_address_lease_time(&dhcp_client, address_index,
386 &valid_ipv6_address, &preferred_lifetime,
387 &valid_lifetime);
388
389 /* Check status. */
390 if (status != NX_SUCCESS)
391 {
392 error_counter++;
393 }
394
395 /* Get the IANA options for when to start renew/rebind requests. These time
396 parameters are the same for all IPv6 addresses assigned in the Client
397 e.g. IANA returned from Server. */
398 status = nx_dhcpv6_get_iana_lease_time(&dhcp_client, &T1, &T2);
399
400 /* Check status. */
401 if (status != NX_SUCCESS)
402 {
403 error_counter++;
404 }
405
406 /*****************************************************************************/
407 /* These are 'legacy' DHCPv6 services and are for the most part identical to the services
408 above except they default to the primary global IPv6 address regardless if the
409 Client was assigned more than one global IPv6 address. */
410
411 /* Now check the assigned lease times. */
412 status = nx_dhcpv6_get_lease_time_data(&dhcp_client, &T1, &T2,
413 &preferred_lifetime, &valid_lifetime);
414
415 /* Check status. */
416 if (status != NX_SUCCESS)
417 {
418 error_counter++;
419 }
420
421 /* Get the IP address. */
422 status = nx_dhcpv6_get_IP_address(&dhcp_client, &valid_ipv6_address);
423
424 /* Check status. */
425 if (status != NX_SUCCESS)
426 {
427 error_counter++;
428 }
429
430 /* Bound state. */
431
432 #ifdef NX_DHCPV6_CLIENT_RESTORE_STATE
433
434 /* Get the DHCPv6 Client record. */
435 nx_dhcpv6_client_get_record(&dhcp_client, &dhcpv6_client_record);
436
437 /* Delete DHCPv6 instance. */
438 nx_dhcpv6_client_delete(&dhcp_client);
439
440 /* Delete IP instance. */
441 status = nx_ip_delete(&client_ip);
442
443 /* Check for error. */
444 if (status)
445 {
446 error_counter++;
447 return;
448 }
449
450 /* Create a Client IP instance. */
451 status = nx_ip_create(&client_ip, "Client IP", IP_ADDRESS(0, 0, 0, 0),
452 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
453 pointer, 2048, 1);
454
455 pointer = pointer + 2048;
456
457 /* Check for IP create errors. */
458 if (status)
459 {
460 error_counter++;
461 return;
462 }
463
464 /* Enable UDP traffic for sending DHCPv6 messages. */
465 status = nx_udp_enable(&client_ip);
466
467 /* Check for UDP enable errors. */
468 if (status)
469 {
470 error_counter++;
471 return;
472 }
473
474 /* Enable ICMP. */
475 status = nx_icmp_enable(&client_ip);
476
477 /* Check for ICMP enable errors. */
478 if (status)
479 {
480 error_counter++;
481 return;
482 }
483
484 /* Enable the Client IP for IPv6 and ICMPv6 services. */
485 status = nxd_ipv6_enable(&client_ip);
486 status += nxd_icmp_enable(&client_ip);
487
488 /* Check for IPv6 and ICMPv6 enable errors. */
489 if (status)
490 {
491 error_counter++;
492 return;
493 }
494
495 /* Establish the link local address for the host. The RAM driver creates
496 a virtual MAC address of 0x1122334456. */
497 status = nxd_ipv6_address_set(&client_ip, 0, NX_NULL, 10, NULL);
498
499 if (status)
500 {
501 error_counter++;
502 return;
503 }
504
505 /* If Duplicate Address Detection (DAD) is enabled in NetX Duo, e.g. #NX_DISABLE_IPV6_DAD
506 not defined, allow time for NetX Duo to verify the address is unique on our network.
507 */
508 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
509
510 /* Create the DHCPv6 Client. */
511 status = nx_dhcpv6_client_create(&dhcp_client, &client_ip, "DHCPv6 Client",
512 &pool_0, pointer, 2048, dhcpv6_state_change_notify,
513 dhcpv6_server_error_handler);
514
515 /* Check for errors. */
516 if (status)
517 {
518 error_counter++;
519 return;
520 }
521
522 /* Update the stack pointer because we need it again. */
523 pointer = pointer + 2048;
524
525 /* Restore the DHCPv6 record. */
526 nx_dhcpv6_client_restore_record(&dhcp_client, &dhcpv6_client_record, 5);
527
528 /* Resume the DHCPv6 service. */
529 nx_dhcpv6_resume(&dhcp_client);
530 #endif
531
532
533 #ifdef NX_DHCPV6_REQUEST_OPTION
534
535 /* Get the DNS Server address. */
536 nx_dhcpv6_get_DNS_server_address(&dhcp_client, 0, &dns_server);
537
538 /* Reset the buffer. */
539 memset(buffer, 0, sizeof(buffer));
540
541 /* Get DNS domain name. */
542 nx_dhcpv6_get_other_option_data(&dhcp_client, NX_DHCPV6_DOMAIN_NAME_OPTION, buffer, 200);
543
544 /* Reset the buffer. */
545 memset(buffer, 0, sizeof(buffer));
546
547 /* Get the time zone. */
548 nx_dhcpv6_get_other_option_data(&dhcp_client, NX_DHCPV6_NEW_POSIX_TIMEZONE_OPTION, buffer, 200); // Try to get DNS info got from DHCPv6 Server
549 #endif
550
551 /* At some point, we may wish to release the IPv6 address lease e.g. the device
552 is leaving the network or powering down. In that case we inform the
553 DHCPv6 Server that we are releasing the address lease. */
554 status = nx_dhcpv6_request_release(&dhcp_client);
555
556 /* Check status. */
557 if (status != NX_SUCCESS)
558 {
559
560 error_counter++;
561 return;
562 }
563
564 /* Send the release message. */
565 tx_thread_sleep(NX_IP_PERIODIC_RATE);
566 }
567
568 /* Stopping the Client task. */
569 status = nx_dhcpv6_stop(&dhcp_client);
570
571 /* Check status. */
572 if (status != NX_SUCCESS)
573 {
574
575 error_counter++;
576 return;
577 }
578
579 /* Clear the previously assigned IPv6 addresses from the Client and IP address table. */
580 status = nx_dhcpv6_reinitialize(&dhcp_client);
581
582 /* Check status. */
583 if (status != NX_SUCCESS)
584 {
585
586 error_counter++;
587 return;
588 }
589
590 /* Start up the Client task again. */
591 status = nx_dhcpv6_start(&dhcp_client);
592
593 /* Check status. */
594 if (status != NX_SUCCESS)
595 {
596
597 error_counter++;
598 return;
599 }
600
601 /* Begin the request process by sending a Solicit message with the IA created above
602 with our preferred IPv6 address. */
603 status = nx_dhcpv6_request_solicit(&dhcp_client);
604 /* Check status. */
605 if (status != NX_SUCCESS)
606 {
607
608 error_counter++;
609 return;
610 }
611
612 /* Wait a bit before releasing the IP address and terminating the client. */
613 tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
614
615 /* Ok, lets stop the application. Again we DO NOT plan
616 to keep the IPv6 address we were assigned and need to release it
617 back to the DHCPv6 server. */
618 status = nx_dhcpv6_request_release(&dhcp_client);
619
620 /* Check for error. */
621 if (status != NX_SUCCESS)
622 {
623 error_counter++;
624 }
625
626 /* Now delete the DHCPv6 client and release ThreadX and
627 NetX Duo resources back to the system. */
628 nx_dhcpv6_client_delete(&dhcp_client);
629
630
631 return;
632
633 }
634
635
636 /* This is the notification from the DHCPv6 Client task that it has changed
637 state in the DHCPv6 protocol, for example getting assigned an IPv6 lease and
638 achieving the bound state or an IPv6 lease expires and being reset to
639 the init state.
640 */
dhcpv6_state_change_notify(NX_DHCPV6 * dhcpv6_ptr,UINT old_state,UINT new_state)641 VOID dhcpv6_state_change_notify(NX_DHCPV6 *dhcpv6_ptr, UINT old_state, UINT new_state)
642 {
643
644 NX_PARAMETER_NOT_USED(dhcpv6_ptr);
645
646 /* Increment state change counter. */
647 state_changes++;
648
649 /* Check if the Client attempted to request an IPv6 lease but no servers
650 responded. */
651 if ((old_state == NX_DHCPV6_STATE_SENDING_SOLICIT) && (new_state == NX_DHCPV6_STATE_INIT))
652 {
653
654 /* Indication that either DAD failed or IP lease expired. */
655 address_not_assigned++;
656 }
657
658 /* Check if the Client has been assigned an IPv6 lease. */
659 if (new_state == NX_DHCPV6_STATE_BOUND_TO_ADDRESS)
660 {
661 bound_addresses++;
662 }
663
664 /* Check if the Client was bound, but failed the uniqueness check
665 (Duplicate Address Detection) and was reset to the INIT state. */
666 if ((old_state == NX_DHCPV6_STATE_SENDING_DECLINE) && (new_state == NX_DHCPV6_STATE_INIT))
667 {
668
669 /* Indication that DAD failed on Client IA. */
670 address_failed_dad++;
671 }
672
673 /* Check if the Client was bound, attempted renew the lease but the
674 IPv6 address renewal/rebinding failed. */
675 if ((old_state == NX_DHCPV6_STATE_SENDING_REBIND) && (new_state == NX_DHCPV6_STATE_INIT))
676 {
677
678 /* Indication that the IP lease expired. */
679 address_expired++;
680 }
681
682
683
684 /* Other checks are possible. */
685
686 }
687
688 /* This is the notification from the DHCPv6 Client task that it received an error
689 from the server (status code) in response to the Client's last DHCPv6 message.
690 */
691
dhcpv6_server_error_handler(NX_DHCPV6 * dhcpv6_ptr,UINT op_code,UINT status_code,UINT message_type)692 VOID dhcpv6_server_error_handler(NX_DHCPV6 *dhcpv6_ptr, UINT op_code, UINT status_code, UINT message_type)
693 {
694
695 NX_PARAMETER_NOT_USED(dhcpv6_ptr);
696 NX_PARAMETER_NOT_USED(op_code);
697 NX_PARAMETER_NOT_USED(status_code);
698 NX_PARAMETER_NOT_USED(message_type);
699
700 /* Increment the server error count. */
701 server_errors++;
702
703 /* This should distinguish between receiving a server error and no server
704 available to assign the Client an IPv6 address if the Client fails
705 to get assigned an address. */
706 }
707
708 #endif /* FEATURE_NX_IPV6 */
709