Skip to content

Commit d8f0003

Browse files
author
Juha Heiskanen
committed
DHCPv6 functionality update
Wi-sun DHCP client enable dhcp option notify and support DNS Server and domain list already. DHCP client library support extra option notification callback's for selected option types. DHCPv6 library support new length field calculation and vendor option write DHCPv6 server reply message is builded now at Server API code which enable options write's to message. DHPCP server support Vendor data and DNS server data set. ICMP RA handler cut padding away now for dns searc list options.
1 parent 7fe0423 commit d8f0003

File tree

15 files changed

+492
-64
lines changed

15 files changed

+492
-64
lines changed

source/6LoWPAN/ws/ws_bbr_api.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *
391391
(void)cur;
392392
if (net_dns_server_get(backbone_interface_id, dns_server_address, &dns_search_list_ptr, &dns_search_list_len, 0) == 0) {
393393
/*Only supporting one DNS server address*/
394-
//DHCPv6_server_service_set_dns_server(cur->id, dns_server_address, dns_search_list_ptr, dns_search_list_len);
394+
DHCPv6_server_service_set_dns_server(cur->id, global_id, dns_server_address, dns_search_list_ptr, dns_search_list_len);
395395
}
396396

397397
//TODO Generate vendor data in Wi-SUN network include the cached DNS query results in some sort of TLV format
@@ -421,8 +421,7 @@ static void ws_bbr_dhcp_server_dns_info_update(protocol_interface_info_entry_t *
421421
}
422422
}
423423

424-
(void)global_id;
425-
//DHCPv6_server_service_set_vendor_data(cur->id, global_id, ARM_ENTERPRISE_NUMBER, dhcp_vendor_data_ptr, dhcp_vendor_data_len);
424+
DHCPv6_server_service_set_vendor_data(cur->id, global_id, ARM_ENTERPRISE_NUMBER, dhcp_vendor_data_ptr, dhcp_vendor_data_len);
426425
}
427426

428427
static void ws_bbr_dhcp_server_start(protocol_interface_info_entry_t *cur, uint8_t *global_id, uint32_t dhcp_address_lifetime)

source/6LoWPAN/ws/ws_bootstrap.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
#include "6LoWPAN/ws/ws_eapol_pdu.h"
7474
#include "6LoWPAN/ws/ws_eapol_auth_relay.h"
7575
#include "6LoWPAN/ws/ws_eapol_relay.h"
76+
#include "libNET/src/net_dns_internal.h"
7677

7778
#define TRACE_GROUP "wsbs"
7879

@@ -872,6 +873,51 @@ static void ws_bootstrap_dhcp_neighbour_update_cb(int8_t interface_id, uint8_t l
872873
ws_bootstrap_mac_neighbor_short_time_set(cur, mac64, WS_NEIGHBOUR_DHCP_ENTRY_LIFETIME);
873874
}
874875

876+
static void ws_bootstrap_dhcp_info_notify_cb(int8_t interface, dhcp_option_notify_t *options, dhcp_server_notify_info_t *server_info)
877+
{
878+
protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface);
879+
if (!cur) {
880+
return;
881+
}
882+
uint8_t server_ll64[16];
883+
memcpy(server_ll64, ADDR_LINK_LOCAL_PREFIX, 8);
884+
885+
if (server_info->duid_length == 8) {
886+
memcpy(server_ll64 + 8, server_info->duid, 8);
887+
} else {
888+
server_ll64[8] = server_info->duid[0];
889+
server_ll64[9] = server_info->duid[1];
890+
server_ll64[10] = server_info->duid[2];
891+
server_ll64[11] = 0xff;
892+
server_ll64[12] = 0xfe;
893+
server_ll64[13] = server_info->duid[3];
894+
server_ll64[14] = server_info->duid[4];
895+
server_ll64[15] = server_info->duid[5];
896+
}
897+
server_ll64[8] ^= 2;
898+
899+
switch (options->option_type) {
900+
case DHCPV6_OPTION_VENDOR_SPECIFIC_INFO:
901+
902+
break;
903+
904+
case DHCPV6_OPTION_DNS_SERVERS:
905+
while (options->option.generic.data_length) {
906+
net_dns_server_address_set(interface, server_ll64, options->option.generic.data, server_info->life_time);
907+
options->option.generic.data_length -= 16;
908+
options->option.generic.data += 16;
909+
}
910+
break;
911+
case DHCPV6_OPTION_DOMAIN_LIST:
912+
net_dns_server_search_list_set(interface, server_ll64, options->option.generic.data, options->option.generic.data_length, server_info->life_time);
913+
break;
914+
default:
915+
break;
916+
}
917+
918+
}
919+
920+
875921
static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur)
876922
{
877923
int8_t ret_val = -1;
@@ -923,6 +969,7 @@ static int8_t ws_bootstrap_up(protocol_interface_info_entry_t *cur)
923969
dhcp_service_link_local_rx_cb_set(cur->id, ws_bootstrap_dhcp_neighbour_update_cb);
924970
dhcp_client_configure(cur->id, true, true, true); //RENEW uses SOLICIT, Interface will use 1 instance for address get, IAID address hint is not used.
925971
dhcp_client_solicit_timeout_set(cur->id, WS_DHCP_SOLICIT_TIMEOUT, WS_DHCP_SOLICIT_MAX_RT, WS_DHCP_SOLICIT_MAX_RC);
972+
dhcp_client_option_notification_cb_set(cur->id, ws_bootstrap_dhcp_info_notify_cb);
926973

927974

928975
ws_nud_table_reset(cur);

source/Common_Protocols/icmpv6.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,21 @@ if_address_entry_t *icmpv6_slaac_address_add(protocol_interface_info_entry_t *cu
639639
}
640640

641641
#ifdef HAVE_IPV6_ND
642+
643+
static uint8_t icmpv6_dns_search_list_remove_pad(uint8_t *data_ptr, uint8_t length)
644+
{
645+
while (length) {
646+
647+
if (data_ptr[length - 2] && data_ptr[length - 1] == 0) {
648+
break;
649+
} else if (data_ptr[length - 2] == 0 && data_ptr[length - 1] == 0) {
650+
length--;
651+
}
652+
}
653+
654+
return length;
655+
}
656+
642657
static buffer_t *icmpv6_ra_handler(buffer_t *buf)
643658
{
644659
protocol_interface_info_entry_t *cur;
@@ -869,7 +884,8 @@ static buffer_t *icmpv6_ra_handler(buffer_t *buf)
869884
uint32_t dns_lifetime = common_read_32_bit(dptr + 2); // 2 x reserved
870885
uint8_t *dns_search_list = dptr + 6;
871886
uint8_t dns_search_list_len = length - 8; // Length includes type and length
872-
887+
//Cut Padding
888+
dns_search_list_len = icmpv6_dns_search_list_remove_pad(dns_search_list, dns_search_list_len);
873889
//tr_info("DNS Search List: %s Lifetime: %lu", trace_array(dns_search_list, dns_search_list_len), (unsigned long) dns_lifetime);
874890
// Add DNS server to DNS information storage.
875891
net_dns_server_search_list_set(cur->id, buf->src_sa.address, dns_search_list, dns_search_list_len, dns_lifetime);

source/DHCPv6_Server/DHCPv6_Server_service.c

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,29 @@ int DHCPv6_server_respond_client(dhcpv6_gua_server_entry_s *serverBase, dhcpv6_r
115115
}
116116

117117
response->responseLength = libdhcpv6_address_reply_message_len(replyPacket->clientDUID.duid_length, replyPacket->serverDUID.duid_length, 0, replyPacket->rapidCommit, address_allocated);
118+
//Calculate DNS LIST and Vendor data lengths here
119+
response->responseLength += libdhcpv6_dns_server_message_sizes(serverBase);
120+
response->responseLength += libdhcpv6_vendor_data_message_sizes(serverBase);
121+
118122
response->responsePtr = ns_dyn_mem_temporary_alloc(response->responseLength);
119123
if (response->responsePtr) {
124+
uint8_t *ptr = response->responsePtr;
125+
//Write Generic data at beginning
126+
ptr = libdhcpv6_header_write(ptr, DHCPV6_REPLY_TYPE, replyPacket->transaction_ID);
127+
ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_SERVER_ID_OPTION, &replyPacket->serverDUID); //16
128+
ptr = libdhcpv6_duid_option_write(ptr, DHCPV6_CLIENT_ID_OPTION, &replyPacket->clientDUID); //16
120129
if (address_allocated) {
121-
libdhcpv6_reply_message_write(response->responsePtr, replyPacket, &nonTemporalAddress, NULL);
130+
ptr = libdhcpv6_identity_association_option_write(ptr, replyPacket->iaId, replyPacket->T0, replyPacket->T1, true);
131+
ptr = libdhcpv6_ia_address_option_write(ptr, nonTemporalAddress.requestedAddress, nonTemporalAddress.preferredLifeTime, nonTemporalAddress.validLifeTime);
132+
//Write DNS LIST and Vendor data here
133+
ptr = libdhcpv6_dns_server_message_writes(serverBase, ptr);
134+
ptr = libdhcpv6_vendor_data_message_writes(serverBase, ptr);
122135
} else {
123-
libdhcpv6_reply_message_write(response->responsePtr, replyPacket, NULL, NULL);
136+
ptr = libdhcpv6_identity_association_option_write_with_status(ptr, replyPacket->iaId, replyPacket->T0, replyPacket->T1, DHCPV6_STATUS_NO_ADDR_AVAILABLE_CODE);
137+
}
138+
139+
if (replyPacket->rapidCommit) {
140+
ptr = libdhcpv6_rapid_commit_option_write(ptr);
124141
}
125142
return 0;
126143
}
@@ -407,6 +424,71 @@ int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t gu
407424

408425
return 0;
409426
}
427+
428+
int DHCPv6_server_service_set_dns_server(int8_t interface, uint8_t guaPrefix[static 16], uint8_t dns_server_address[static 16], uint8_t *dns_search_list_ptr, uint8_t dns_search_list_len)
429+
{
430+
dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix);
431+
if (!serverInfo) {
432+
return -1;
433+
}
434+
435+
dhcpv6_dns_server_data_t *dns_entry = libdhcpv6_dns_server_allocate(serverInfo, dns_server_address);
436+
if (!dns_entry) {
437+
return -1;
438+
}
439+
440+
if (dns_entry->search_list_length != dns_search_list_len) {
441+
ns_dyn_mem_free(dns_entry->search_list);
442+
dns_entry->search_list = NULL;
443+
dns_entry->search_list_length = 0;
444+
if (dns_search_list_len) {
445+
dns_entry->search_list = ns_dyn_mem_alloc(dns_search_list_len);
446+
if (dns_entry->search_list) {
447+
dns_entry->search_list_length = dns_search_list_len;
448+
}
449+
}
450+
}
451+
452+
if (dns_entry->search_list_length) {
453+
//Copy Search List to allocated buffer
454+
memcpy(dns_entry->search_list, dns_search_list_ptr, dns_entry->search_list_length);
455+
}
456+
457+
return 0;
458+
}
459+
460+
int DHCPv6_server_service_set_vendor_data(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, uint8_t *dhcp_vendor_data_ptr, uint8_t dhcp_vendor_data_len)
461+
{
462+
dhcpv6_gua_server_entry_s *serverInfo = libdhcpv6_server_data_get_by_prefix_and_interfaceid(interface, guaPrefix);
463+
if (!serverInfo) {
464+
return -1;
465+
}
466+
467+
dhcpv6_vendor_data_t *vendor_data_entry = libdhcpv6_vendor_data_allocate(serverInfo, enterprise_number);
468+
469+
if (!vendor_data_entry) {
470+
return -1;
471+
}
472+
473+
if (vendor_data_entry->vendor_data_length != dhcp_vendor_data_len) {
474+
ns_dyn_mem_free(vendor_data_entry->vendor_data);
475+
vendor_data_entry->vendor_data = NULL;
476+
vendor_data_entry->vendor_data_length = 0;
477+
if (dhcp_vendor_data_len) {
478+
vendor_data_entry->vendor_data = ns_dyn_mem_alloc(dhcp_vendor_data_len);
479+
if (vendor_data_entry->vendor_data) {
480+
vendor_data_entry->vendor_data_length = dhcp_vendor_data_len;
481+
}
482+
}
483+
}
484+
485+
if (vendor_data_entry->vendor_data_length) {
486+
//Copy Venfor Data to allocated buffer
487+
memcpy(vendor_data_entry->vendor_data, dhcp_vendor_data_ptr, vendor_data_entry->vendor_data_length);
488+
}
489+
return 0;
490+
}
491+
410492
#else
411493

412494
int DHCPv6_server_service_init(int8_t interface, uint8_t guaPrefix[static 16], uint8_t serverDUID[static 8], uint16_t serverDUIDType)

source/DHCPv6_Server/DHCPv6_server_service.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ int DHCPv6_server_service_set_max_clients_accepts_count(int8_t interface, uint8_
8989
* /param validLifeTimne in seconds
9090
*/
9191
int DHCPv6_server_service_set_address_validlifetime(int8_t interface, uint8_t guaPrefix[static 16], uint32_t validLifeTimne);
92+
93+
int DHCPv6_server_service_set_dns_server(int8_t interface, uint8_t guaPrefix[static 16], uint8_t dns_server_address[static 16], uint8_t *dns_search_list_ptr, uint8_t dns_search_list_len);
94+
95+
int DHCPv6_server_service_set_vendor_data(int8_t interface, uint8_t guaPrefix[static 16], uint32_t enterprise_number, uint8_t *dhcp_vendor_data_ptr, uint8_t dhcp_vendor_data_len);
96+
9297
#else
9398
#define DHCPv6_server_service_delete(interface, guaPrefix, delete_gua_addresses)
9499
#endif

source/DHCPv6_client/dhcpv6_client_api.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,48 @@ void dhcp_client_delete(int8_t interface);
7979
*/
8080
typedef void (dhcp_client_global_adress_cb)(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], bool register_status);
8181

82+
typedef struct dhcp_server_notify_info {
83+
uint16_t duid_type;
84+
uint16_t duid_length;
85+
uint32_t life_time;
86+
uint8_t *duid;
87+
} dhcp_server_notify_info_t;
88+
89+
90+
typedef struct dhcp_gen_option {
91+
uint16_t data_length;
92+
uint8_t *data;
93+
} dhcp_gen_option_t;
94+
95+
typedef struct dhcp_vendor_spesific_option {
96+
uint32_t enterprise_number;
97+
uint16_t data_length;
98+
uint8_t *data;
99+
} dhcp_vendor_spesific_option_t;
100+
101+
typedef struct dhcp_option_notify_s {
102+
uint8_t option_type;
103+
union {
104+
dhcp_gen_option_t generic;
105+
dhcp_vendor_spesific_option_t vendor_spesific;
106+
} option;
107+
} dhcp_option_notify_t;
108+
109+
/* give dhcp Client server Optional options notication
110+
*
111+
* /param interface interface id
112+
* /param option_type Type of option
113+
* /param option_data data of options.
114+
* /param option_length length of option.
115+
* /param server_info info inclu DUID and Life-time for notify options
116+
*
117+
*/
118+
typedef void (dhcp_client_options_notify_cb)(int8_t interface, dhcp_option_notify_t *options, dhcp_server_notify_info_t *server_info);
119+
82120
int dhcp_client_get_global_address(int8_t interface, uint8_t dhcp_addr[static 16], uint8_t prefix[static 16], dhcp_client_global_adress_cb *error_cb);
83121

122+
int dhcp_client_option_notification_cb_set(int8_t interface, dhcp_client_options_notify_cb *notify_cb);
123+
84124
/* Renew all leased adddresses might be used when short address changes
85125
*
86126
* /param interface interface where address is got

source/DHCPv6_client/dhcpv6_client_service.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
typedef struct {
3535
dhcp_client_global_adress_cb *global_address_cb;
36+
dhcp_client_options_notify_cb *option_information_cb;
3637
uint16_t service_instance;
3738
uint16_t relay_instance;
3839
uint16_t sol_timeout;
@@ -152,6 +153,17 @@ void dhcp_client_solicit_timeout_set(int8_t interface, uint16_t timeout, uint16_
152153
return;
153154
}
154155

156+
int dhcp_client_option_notification_cb_set(int8_t interface, dhcp_client_options_notify_cb *notify_cb)
157+
{
158+
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
159+
if (!dhcp_client) {
160+
return -1;
161+
}
162+
dhcp_client->option_information_cb = notify_cb;
163+
return 0;
164+
165+
}
166+
155167
void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16])
156168
{
157169
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
@@ -215,6 +227,66 @@ void dhcpv6_client_send_error_cb(dhcpv6_client_server_data_t *srv_data_ptr)
215227
}
216228

217229

230+
static void dhcp_vendor_information_notify(uint8_t *ptr, uint16_t data_len, dhcp_client_class_t *dhcp_client, dhcpv6_client_server_data_t *srv_data_ptr)
231+
{
232+
if (!dhcp_client->option_information_cb) {
233+
return;
234+
}
235+
236+
if (!srv_data_ptr->iaNontemporalAddress.validLifetime) {
237+
return; //Valid Lifetime zero
238+
}
239+
240+
dhcp_option_notify_t dhcp_option;
241+
242+
uint16_t type, length;
243+
bool valid_optional_options;
244+
245+
dhcp_server_notify_info_t server_info;
246+
server_info.life_time = srv_data_ptr->iaNontemporalAddress.validLifetime;
247+
server_info.duid = srv_data_ptr->serverDUID.duid;
248+
server_info.duid_type = srv_data_ptr->serverDUID.type;
249+
server_info.duid_length = srv_data_ptr->serverDUID.duid_length;
250+
251+
while (data_len >= 4) {
252+
type = common_read_16_bit(ptr);
253+
ptr += 2;
254+
length = common_read_16_bit(ptr);
255+
ptr += 2;
256+
data_len -= 4;
257+
if (data_len < length) {
258+
return;
259+
}
260+
valid_optional_options = false;
261+
//Accept only listed items below with validated lengths
262+
if ((type == DHCPV6_OPTION_VENDOR_SPECIFIC_INFO || type == DHCPV6_OPTION_VENDOR_CLASS) && data_len >= 4) {
263+
valid_optional_options = true;
264+
//Parse enterprise number
265+
dhcp_option.option.vendor_spesific.enterprise_number = common_read_32_bit(ptr);
266+
ptr += 4;
267+
data_len -= 4;
268+
dhcp_option.option.vendor_spesific.data = ptr;
269+
dhcp_option.option.vendor_spesific.data_length = data_len;
270+
271+
272+
} else if (type == DHCPV6_OPTION_DNS_SERVERS && (data_len >= 16 && ((data_len % 16) == 0))) {
273+
valid_optional_options = true;
274+
dhcp_option.option.generic.data = ptr;
275+
dhcp_option.option.generic.data_length = data_len;
276+
} else if (type == DHCPV6_OPTION_DOMAIN_LIST) {
277+
valid_optional_options = true;
278+
dhcp_option.option.generic.data = ptr;
279+
dhcp_option.option.generic.data_length = data_len;
280+
}
281+
if (valid_optional_options) {
282+
dhcp_option.option_type = type;
283+
dhcp_client->option_information_cb(dhcp_client->interface, &dhcp_option, &server_info);
284+
}
285+
data_len -= length;
286+
ptr += length;
287+
}
288+
}
289+
218290
/* solication responce received for either global address or routter id assignment */
219291
int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uint8_t *msg_ptr, uint16_t msg_len)
220292
{
@@ -310,6 +382,10 @@ int dhcp_solicit_resp_cb(uint16_t instance_id, void *ptr, uint8_t msg_name, uin
310382
if (dhcp_client->global_address_cb) {
311383
dhcp_client->global_address_cb(dhcp_client->interface, srv_data_ptr->server_address, srv_data_ptr->iaNontemporalAddress.addressPrefix, status);
312384
}
385+
386+
//Optional Options notify from Reply
387+
dhcp_vendor_information_notify(msg_ptr, msg_len, dhcp_client, srv_data_ptr);
388+
313389
return RET_MSG_ACCEPTED;
314390
error_exit:
315391
dhcpv6_client_send_error_cb(srv_data_ptr);

0 commit comments

Comments
 (0)