Skip to content

Commit 0d2badf

Browse files
committed
Add complete support of DHCP relay interface ID option
RFC3315 specifies the following: "The relay agent MAY send the Interface-id option to identify the interface on which the client message was received. If a relay agent receives a Relay-reply message with an Interface-id option, the relay agent relays the message to the client through the interface identified by the option." The current implementation of the DHCP relay reply handling, the interface ID field from the server response is ignored. Managing the interface ID is very important especially as DHCP requests/replies use link-local addresses. The consequence of this is that the interface must always be specified because the routing layer cannot guess the correct interface. Moreover, Mbed provides a mechanism to enable/disable the interface ID option on a DHCP relay instance, so it is important to fully support it. The reason why this issue has not been discoverd until now is that the DHCP relay is mainly used on systems that use only one interface (such as Wi-SUN routers). By default, when no interface ID is specified for the socket, the latter will choose 6loWPAN interface by default. This means that if two interfaces are used on the same device, the 6loWPAN interface is always selected. The commit adds code to retrieve the interface-id value contained within the DHCP relay reply message and write it to a control message header that is added to the socket message. This tells the socket which interface to choose. If the interface-id option is not enabled on the relay, this procedure is simply ignored.
1 parent 807fd79 commit 0d2badf

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

connectivity/nanostack/sal-stack-nanostack/source/libDHCPv6/dhcp_service_api.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,9 @@ void recv_dhcp_relay_msg(void *cb_res)
442442

443443
msg_len = socket_recvmsg(sckt_data->socket_id, &msghdr, NS_MSG_LEGACY0);
444444

445+
// Buffer to tell additional data for the socket (such as interface ID)
446+
uint8_t ancillary_databuffer[NS_CMSG_SPACE(sizeof(ns_in6_pktinfo_t))];
447+
445448
tr_debug("dhcp Relay recv msg");
446449

447450
//Parse type
@@ -471,6 +474,25 @@ void recv_dhcp_relay_msg(void *cb_res)
471474
msghdr.msg_iovlen = 1;
472475
msg_data.iov_base = relay_msg.relay_options.msg_ptr;
473476
msg_data.iov_len = relay_msg.relay_options.len;
477+
478+
// Append a control message to tell the socket which interface to use if option is activated
479+
if (memcmp(src_address.address, ns_in6addr_any, 16) != 0 && relay_srv->add_interface_id_option) {
480+
ns_cmsghdr_t *cmsg;
481+
ns_in6_pktinfo_t *pktinfo;
482+
483+
msghdr.msg_control = ancillary_databuffer;
484+
msghdr.msg_controllen = sizeof(ancillary_databuffer);
485+
486+
cmsg = NS_CMSG_FIRSTHDR(&msghdr);
487+
cmsg->cmsg_type = SOCKET_IPV6_PKTINFO;
488+
cmsg->cmsg_level = SOCKET_IPPROTO_IPV6;
489+
cmsg->cmsg_len = NS_CMSG_LEN(sizeof(ns_in6_pktinfo_t));
490+
491+
pktinfo = (ns_in6_pktinfo_t *)NS_CMSG_DATA(cmsg);
492+
pktinfo->ipi6_ifindex = *relay_msg.relay_interface_id.msg_ptr;
493+
memset(pktinfo->ipi6_addr, 0, 16); // Don't specify address (let socket choose appropriate by routing)
494+
}
495+
474496
tr_debug("Forward Original relay msg to client");
475497

476498
} else {

0 commit comments

Comments
 (0)