Skip to content

Commit 957b358

Browse files
author
Juha Heiskanen
committed
DHCP server and Agent relay update
Added support for response back Relay agent given interface id option. Relay agent support to add interface id option to Relay message.
1 parent c825b04 commit 957b358

File tree

8 files changed

+126
-37
lines changed

8 files changed

+126
-37
lines changed

nanostack/dhcp_service_api.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,15 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty
142142
*/
143143
void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_address);
144144

145+
/**
146+
* \brief Enable DHCPv6 Relay Agent to add interface ID option to relay frame. Default is disabled.
147+
*
148+
*
149+
* \param instance The instance ID of the registered server.
150+
* \param enable true add interface option
151+
*/
152+
void dhcp_service_relay_interface_id_option_enable(uint16_t instance, bool enable);
153+
145154
/**
146155
* \brief Get DHCPv6 Relay Agent address pointer.
147156
*

source/DHCPv6_client/dhcpv6_client_api.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ void dhcp_client_global_address_delete(int8_t interface, uint8_t *dhcp_addr, uin
139139

140140
void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[static 16]);
141141

142+
void dhcp_relay_agent_interface_id_option_enable(int8_t interface, bool enable);
143+
142144
int dhcp_client_server_address_update(int8_t interface, uint8_t *prefix, uint8_t server_address[static 16]);
143145

144146

source/DHCPv6_client/dhcpv6_client_service.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,16 @@ void dhcp_relay_agent_enable(int8_t interface, uint8_t border_router_address[sta
175175
dhcp_service_relay_instance_enable(dhcp_client->relay_instance, border_router_address);
176176
}
177177

178+
void dhcp_relay_agent_interface_id_option_enable(int8_t interface, bool enable)
179+
{
180+
dhcp_client_class_t *dhcp_client = dhcpv6_client_entry_discover(interface);
181+
if (!dhcp_client) {
182+
return;
183+
}
184+
185+
dhcp_service_relay_interface_id_option_enable(dhcp_client->relay_instance, enable);
186+
}
187+
178188
void dhcp_client_delete(int8_t interface)
179189
{
180190
protocol_interface_info_entry_t *cur = NULL;

source/libDHCPv6/dhcp_service_api.c

Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ typedef struct {
6060
int8_t interface_id;
6161
uint8_t server_address[16];
6262
bool relay_activated;
63+
bool add_interface_id_option;
6364
ns_list_link_t link;
6465
} relay_instance_t;
6566
typedef NS_LIST_HEAD(relay_instance_t, link) relay_instance_list_t;
@@ -83,6 +84,8 @@ typedef struct {
8384
uint8_t *msg_ptr;
8485
uint16_t msg_len;
8586
uint8_t *relay_start;
87+
uint8_t *opt_interface_id;
88+
uint16_t opt_interface_id_length;
8689
ns_list_link_t link;
8790
} msg_tr_t;
8891
typedef NS_LIST_HEAD(msg_tr_t, link) tr_list_t;
@@ -335,6 +338,8 @@ void recv_dhcp_server_msg(void *cb_res)
335338
}
336339
//Update Source and data
337340
msg_tr_ptr->relay_start = msg_ptr;
341+
msg_tr_ptr->opt_interface_id = relay_msg.relay_interface_id.msg_ptr;
342+
msg_tr_ptr->opt_interface_id_length = relay_msg.relay_interface_id.len;
338343
memcpy(msg_tr_ptr->addr.address, relay_msg.peer_address, 16);
339344
msg_ptr = relay_msg.relay_options.msg_ptr;
340345
msg_len = relay_msg.relay_options.len;
@@ -408,35 +413,37 @@ void recv_dhcp_relay_msg(void *cb_res)
408413
}
409414
ns_address_t src_address;
410415

411-
uint8_t relay_frame[DHCPV6_RELAY_LENGTH + 4];
412-
ns_iovec_t msg_iov[2];
413-
msg_iov[0].iov_base = relay_frame;
414-
msg_iov[0].iov_len = 34;
415-
msg_iov[1].iov_base = ns_dyn_mem_temporary_alloc(sckt_data->d_len);
416-
msg_iov[1].iov_len = sckt_data->d_len;
417-
if (msg_iov[1].iov_base == NULL) {
416+
//Relay vector added space for relay frame + Interface ID
417+
uint8_t relay_frame[DHCPV6_RELAY_LENGTH + 4 + 5];
418+
419+
420+
uint8_t *socket_data = ns_dyn_mem_temporary_alloc(sckt_data->d_len);
421+
422+
if (socket_data == NULL) {
418423
// read actual message
419424
tr_error("Out of resources");
420425
goto cleanup;
421426
}
422427

428+
423429
ns_msghdr_t msghdr;
430+
ns_iovec_t msg_data;
431+
msg_data.iov_base = socket_data;
432+
msg_data.iov_len = sckt_data->d_len;
424433
//Set messages name buffer
425434
msghdr.msg_name = &src_address;
426435
msghdr.msg_namelen = sizeof(src_address);
427-
msghdr.msg_iov = &msg_iov[1];
436+
msghdr.msg_iov = &msg_data;
428437
msghdr.msg_iovlen = 1;
429438
msghdr.msg_control = NULL;
430439
msghdr.msg_controllen = 0;
431440

432441
msg_len = socket_recvmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0);
433442

434-
435443
tr_debug("dhcp Relay recv msg");
436444

437445
//Parse type
438-
uint8_t *ptr = msg_iov[1].iov_base;
439-
uint8_t msg_type = *ptr;
446+
uint8_t msg_type = *socket_data;
440447

441448
int16_t tc = 0;
442449
if (msg_type == DHCPV6_RELAY_FORWARD) {
@@ -446,7 +453,7 @@ void recv_dhcp_relay_msg(void *cb_res)
446453
} else if (msg_type == DHCPV6_RELAY_REPLY) {
447454
//Parse and validate Relay
448455
dhcpv6_relay_msg_t relay_msg;
449-
if (!libdhcpv6_relay_msg_read(ptr, msg_len, &relay_msg)) {
456+
if (!libdhcpv6_relay_msg_read(socket_data, msg_len, &relay_msg)) {
450457
tr_error("Not valid relay");
451458
goto cleanup;
452459
}
@@ -458,14 +465,14 @@ void recv_dhcp_relay_msg(void *cb_res)
458465
memcpy(src_address.address, relay_msg.peer_address, 16);
459466
src_address.type = ADDRESS_IPV6;
460467
src_address.identifier = DHCPV6_CLIENT_PORT;
461-
msghdr.msg_iov = &msg_iov[0];
468+
msghdr.msg_iov = &msg_data;
462469
msghdr.msg_iovlen = 1;
463-
msg_iov[0].iov_base = relay_msg.relay_options.msg_ptr;
464-
msg_iov[0].iov_len = relay_msg.relay_options.len;
470+
msg_data.iov_base = relay_msg.relay_options.msg_ptr;
471+
msg_data.iov_len = relay_msg.relay_options.len;
465472
tr_debug("Forward Original relay msg to client");
466473

467474
} else {
468-
if (0 != libdhcpv6_message_malformed_check(ptr, msg_len)) {
475+
if (0 != libdhcpv6_message_malformed_check(socket_data, msg_len)) {
469476
tr_error("Malformed packet");
470477
goto cleanup;
471478
}
@@ -476,10 +483,24 @@ void recv_dhcp_relay_msg(void *cb_res)
476483
tr_error("No GP address");
477484
goto cleanup;
478485
}
479-
486+
ns_iovec_t msg_iov[2];
487+
uint8_t *ptr = relay_frame;
480488
//Build
481-
libdhcpv6_dhcp_relay_msg_write(relay_frame, DHCPV6_RELAY_FORWARD, 0, src_address.address, gp_address);
482-
libdhcpv6_dhcp_option_header_write(relay_frame + 34, msg_len);
489+
//ADD relay frame vector front of original data
490+
msghdr.msg_iov = &msg_iov[0];
491+
msg_iov[0].iov_base = relay_frame;
492+
msghdr.msg_iovlen = 2;
493+
//SET Original Data
494+
msg_iov[1].iov_base = socket_data;
495+
msg_iov[1].iov_len = msg_len;
496+
497+
ptr = libdhcpv6_dhcp_relay_msg_write(ptr, DHCPV6_RELAY_FORWARD, 0, src_address.address, gp_address);
498+
if (relay_srv->add_interface_id_option) {
499+
ptr = libdhcpv6_option_interface_id_write(ptr, sckt_data->interface_id);
500+
}
501+
ptr = libdhcpv6_dhcp_option_header_write(ptr, DHCPV6_OPTION_RELAY, msg_len);
502+
//Update length of relay vector
503+
msg_iov[0].iov_len = ptr - relay_frame;
483504

484505
//Update Neighbour table if necessary
485506
relay_notify_t *neigh_notify = dhcp_service_notify_find(sckt_data->interface_id);
@@ -491,20 +512,14 @@ void recv_dhcp_relay_msg(void *cb_res)
491512
memcpy(src_address.address, relay_srv->server_address, 16);
492513
src_address.type = ADDRESS_IPV6;
493514
src_address.identifier = DHCPV6_SERVER_PORT;
494-
//ADD relay frame vector front of original data
495-
msghdr.msg_iov = &msg_iov[0];
496-
msghdr.msg_iovlen = 2;
497-
msg_iov[0].iov_base = relay_frame;
498-
msg_iov[0].iov_len = 38;
499-
msg_iov[1].iov_len = msg_len;
500515
tr_debug("Forward Client msg to server");
501516
tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT;
502517

503518
}
504519
socket_setsockopt(sckt_data->socket_id, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc));
505520
socket_sendmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0);
506521
cleanup:
507-
ns_dyn_mem_free(msg_iov[1].iov_base);
522+
ns_dyn_mem_free(socket_data);
508523

509524
return;
510525
}
@@ -635,6 +650,7 @@ uint16_t dhcp_service_init(int8_t interface_id, dhcp_instance_type_e instance_ty
635650
relay_srv->instance_id = id;
636651
relay_srv->interface_id = interface_id;
637652
relay_srv->relay_activated = false;
653+
relay_srv->add_interface_id_option = false;
638654

639655
}
640656

@@ -655,6 +671,14 @@ void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_addre
655671
}
656672
}
657673

674+
void dhcp_service_relay_interface_id_option_enable(uint16_t instance, bool enable)
675+
{
676+
relay_instance_t *relay_srv = dhcp_service_relay_find(instance);
677+
if (relay_srv) {
678+
relay_srv->add_interface_id_option = enable;
679+
}
680+
}
681+
658682
uint8_t *dhcp_service_relay_global_addres_get(uint16_t instance)
659683
{
660684
relay_instance_t *relay_srv = dhcp_service_relay_find(instance);
@@ -851,30 +875,42 @@ void dhcp_service_send_message(msg_tr_t *msg_tr_ptr)
851875
//Build Relay Reply only server do this
852876
int16_t tc = IP_DSCP_CS6 << IP_TCLASS_DSCP_SHIFT;
853877
socket_setsockopt(msg_tr_ptr->socket, SOCKET_IPPROTO_IPV6, SOCKET_IPV6_TCLASS, &tc, sizeof(tc));
854-
ns_iovec_t data_vector[2];
878+
ns_iovec_t data_vector[4];
879+
uint8_t relay_header[4];
880+
libdhcpv6_dhcp_option_header_write(relay_header, DHCPV6_OPTION_RELAY, msg_tr_ptr->msg_len);
855881
ns_msghdr_t msghdr;
882+
msghdr.msg_iovlen = 0;
856883
memcpy(msg_tr_ptr->addr.address, msg_tr_ptr->relay_start + 2, 16);
857884
msg_tr_ptr->addr.identifier = DHCPV6_SERVER_PORT;
858885
//SET IOV vectors
859886
//Relay Reply
860-
data_vector[0].iov_base = (void *) msg_tr_ptr->relay_start;
861-
data_vector[0].iov_len = DHCPV6_RELAY_LENGTH + 4;
887+
data_vector[msghdr.msg_iovlen].iov_base = (void *) msg_tr_ptr->relay_start;
888+
data_vector[msghdr.msg_iovlen].iov_len = DHCPV6_RELAY_LENGTH;
889+
msghdr.msg_iovlen++;
890+
if (msg_tr_ptr->opt_interface_id) {
891+
data_vector[msghdr.msg_iovlen].iov_base = (void *)(msg_tr_ptr->opt_interface_id - 4);
892+
data_vector[msghdr.msg_iovlen].iov_len = msg_tr_ptr->opt_interface_id_length + 4;
893+
msghdr.msg_iovlen++;
894+
}
895+
//Relay reply header
896+
data_vector[msghdr.msg_iovlen].iov_base = (void *) relay_header;
897+
data_vector[msghdr.msg_iovlen].iov_len = 4;
898+
msghdr.msg_iovlen++;
862899
//DHCPV normal message vector
863-
data_vector[1].iov_base = (void *) msg_tr_ptr->msg_ptr;
864-
data_vector[1].iov_len = msg_tr_ptr->msg_len;
900+
data_vector[msghdr.msg_iovlen].iov_base = (void *) msg_tr_ptr->msg_ptr;
901+
data_vector[msghdr.msg_iovlen].iov_len = msg_tr_ptr->msg_len;
902+
msghdr.msg_iovlen++;
865903

866904
//Set message name
867905
msghdr.msg_name = (void *) &msg_tr_ptr->addr;
868906
msghdr.msg_namelen = sizeof(ns_address_t);
869907
msghdr.msg_iov = &data_vector[0];
870-
msghdr.msg_iovlen = 2;
871908
//No ancillary data
872909
msghdr.msg_control = NULL;
873910
msghdr.msg_controllen = 0;
874911

875912
uint8_t *ptr = msg_tr_ptr->relay_start;
876913
*ptr = DHCPV6_RELAY_REPLY;
877-
libdhcpv6_dhcp_option_header_write(ptr + 34, msg_tr_ptr->msg_len);
878914
retval = socket_sendmsg(msg_tr_ptr->socket, &msghdr, NS_MSG_LEGACY0);
879915

880916
} else {
@@ -972,6 +1008,12 @@ void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_addre
9721008
(void)server_address;
9731009
}
9741010

1011+
void dhcp_service_relay_interface_id_option_enable(uint16_t instance, bool enable)
1012+
{
1013+
(void)instance;
1014+
(void)enable;
1015+
}
1016+
9751017
int dhcp_service_send_resp(uint32_t msg_tr_id, uint8_t options, uint8_t *msg_ptr, uint16_t msg_len)
9761018
{
9771019
(void)msg_tr_id;

source/libDHCPv6/libDHCPv6.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -859,9 +859,16 @@ uint8_t *libdhcpv6_dhcp_relay_msg_write(uint8_t *ptr, uint8_t type, uint8_t hop_
859859
return ptr;
860860
}
861861

862-
uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t length)
862+
uint8_t *libdhcpv6_option_interface_id_write(uint8_t *ptr, int8_t interface_id)
863863
{
864-
ptr = common_write_16_bit(DHCPV6_OPTION_RELAY, ptr);
864+
ptr = libdhcpv6_dhcp_option_header_write(ptr, DHCPV6_OPTION_INTERFACE_ID, 1);
865+
*ptr++ = interface_id;
866+
return ptr;
867+
}
868+
869+
uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t option_type, uint16_t length)
870+
{
871+
ptr = common_write_16_bit(option_type, ptr);
865872
ptr = common_write_16_bit(length, ptr);
866873
return ptr;
867874
}
@@ -878,6 +885,11 @@ bool libdhcpv6_relay_msg_read(uint8_t *ptr, uint16_t length, dhcpv6_relay_msg_t
878885
relay_msg->peer_address = ptr + 16;
879886
ptr += 32;
880887
//Discover
888+
if (libdhcpv6_message_option_discover(ptr, length - 34, DHCPV6_OPTION_INTERFACE_ID, &relay_msg->relay_interface_id) != 0) {
889+
relay_msg->relay_interface_id.len = 0;
890+
relay_msg->relay_interface_id.msg_ptr = NULL;
891+
}
892+
881893
if (libdhcpv6_message_option_discover(ptr, length - 34, DHCPV6_OPTION_RELAY, &relay_msg->relay_options) != 0) {
882894
return false;
883895
}

source/libDHCPv6/libDHCPv6.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ typedef struct dhcpv6_relay_msg {
125125
uint8_t hop_limit;
126126
uint8_t *link_address;
127127
uint8_t *peer_address;
128+
dhcp_options_msg_t relay_interface_id;
128129
dhcp_options_msg_t relay_options;
129130
} dhcpv6_relay_msg_t;
130131

@@ -237,6 +238,7 @@ typedef struct dhcpv6_relay_msg {
237238

238239
#define DHCPV6_RELAY_LENGTH 34
239240
#define DHCPV6_OPTION_RELAY 0x0009
241+
#define DHCPV6_OPTION_INTERFACE_ID 0x0012
240242

241243

242244

@@ -293,7 +295,7 @@ uint16_t libdhcpv6_address_reply_message_len(uint16_t clientDUIDLength, uint16_t
293295

294296
uint8_t *libdhcpv6_generic_nontemporal_address_message_write(uint8_t *ptr, dhcpv6_solication_base_packet_s *packet, dhcpv6_ia_non_temporal_address_s *nonTemporalAddress, dhcp_duid_options_params_t *serverLink);
295297
uint8_t *libdhcpv6_dhcp_relay_msg_write(uint8_t *ptr, uint8_t type, uint8_t hop_limit, uint8_t *peer_addres, uint8_t *link_address);
296-
uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t length);
298+
uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t option_type, uint16_t length);
297299

298300
int libdhcpv6_get_IA_address(uint8_t *ptr, uint16_t data_length, dhcp_ia_non_temporal_params_t *params);
299301
int libdhcpv6_get_duid_by_selected_type_id_opt(uint8_t *ptr, uint16_t data_length, uint16_t type, dhcp_duid_options_params_t *params);
@@ -341,6 +343,8 @@ uint8_t *libdhcpv6_rapid_commit_option_write(uint8_t *ptr);
341343
*/
342344
uint8_t *libdhcvp6_request_option_write(uint8_t *ptr, uint8_t optionCnt, uint16_t *optionPtr);
343345

346+
uint8_t *libdhcpv6_option_interface_id_write(uint8_t *ptr, int8_t interface_id);
347+
344348

345349

346350
/**

test/nanostack/unittest/stub/dhcp_service_api_stub.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,11 @@ void dhcp_service_relay_instance_enable(uint16_t instance, uint8_t *server_addre
179179

180180
}
181181

182+
void dhcp_service_relay_interface_id_option_enable(uint16_t instance, bool enable)
183+
{
184+
185+
}
186+
182187
uint8_t *dhcp_service_relay_global_addres_get(uint16_t instance)
183188
{
184189
return NULL;

test/nanostack/unittest/stub/libDHCPv6_stub.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,12 @@ uint8_t *libdhcpv6_dhcp_relay_msg_write(uint8_t *ptr, uint8_t type, uint8_t hop_
228228
return ptr + 34;
229229
}
230230

231-
uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t length)
231+
uint8_t *libdhcpv6_option_interface_id_write(uint8_t *ptr, int8_t interface_id)
232+
{
233+
return ptr + 5;
234+
}
235+
236+
uint8_t *libdhcpv6_dhcp_option_header_write(uint8_t *ptr, uint16_t option_type, uint16_t length)
232237
{
233238
return ptr + 4;
234239
}

0 commit comments

Comments
 (0)