diff --git a/src/configInterface.cpp b/src/configInterface.cpp index ca78d80..5f20741 100644 --- a/src/configInterface.cpp +++ b/src/configInterface.cpp @@ -118,6 +118,7 @@ void processRelayNotification(std::deque &entries, relay_config intf; intf.is_option_79 = true; + intf.is_interface_id = false; intf.interface = vlan; intf.db = nullptr; for (auto &fieldValue: fieldValues) { @@ -135,6 +136,9 @@ void processRelayNotification(std::deque &entries, if(f == "dhcpv6_option|rfc6939_support" && v == "false") { intf.is_option_79 = false; } + if(f == "dhcpv6_option|interface_id" && v == "true") { // interface-id is off by default on non-Dual-ToR, unless specified in config db + intf.is_interface_id = true; + } } vlans->push_back(intf); } diff --git a/src/relay.cpp b/src/relay.cpp index 5233fe5..f59253d 100644 --- a/src/relay.cpp +++ b/src/relay.cpp @@ -471,7 +471,10 @@ void relay_client(int sock, const uint8_t *msg, int32_t len, const ip6_hdr *ip_h option79.link_layer_type = htons(1); option79.option_code = htons(OPTION_CLIENT_LINKLAYER_ADDR); option79.option_length = htons(2 + 6); // link_layer_type field + address - + + if ((unsigned)(current_buffer_position + sizeof(linklayer_addr_option) - buffer) > sizeof(buffer)) { + return; + } memcpy(current_buffer_position, &option79, sizeof(linklayer_addr_option)); current_buffer_position += sizeof(linklayer_addr_option); @@ -479,6 +482,19 @@ void relay_client(int sock, const uint8_t *msg, int32_t len, const ip6_hdr *ip_h current_buffer_position += sizeof(ether_hdr->ether_shost); } + if(config->is_interface_id) { + interface_id_option intf_id; + intf_id.option_code = htons(OPTION_INTERFACE_ID); + intf_id.option_length = htons(sizeof(in6_addr)); + intf_id.interface_id = config->link_address.sin6_addr; + + if ((unsigned)(current_buffer_position + sizeof(linklayer_addr_option) - buffer) > sizeof(buffer)) { + return; + } + memcpy(current_buffer_position, &intf_id, sizeof(interface_id_option)); + current_buffer_position += sizeof(interface_id_option); + } + auto dhcp_message_length = len; relay_forward(current_buffer_position, parse_dhcpv6_hdr(msg), dhcp_message_length); current_buffer_position += dhcp_message_length + sizeof(dhcpv6_option); diff --git a/src/relay.h b/src/relay.h index c5b0732..9f32a1d 100644 --- a/src/relay.h +++ b/src/relay.h @@ -21,6 +21,7 @@ #define lengthof(A) (sizeof (A) / sizeof (A)[0]) #define OPTION_RELAY_MSG 9 +#define OPTION_INTERFACE_ID 18 #define OPTION_CLIENT_LINKLAYER_ADDR 79 /* DHCPv6 message types */ @@ -55,6 +56,7 @@ struct relay_config { std::vector servers; std::vector servers_sock; bool is_option_79; + bool is_interface_id; }; @@ -84,6 +86,12 @@ struct linklayer_addr_option { uint16_t link_layer_type; }; +struct interface_id_option { + uint16_t option_code; + uint16_t option_length; + in6_addr interface_id; // to accomodate dual-tor, this opaque value is set to carry relay interface's global ipv6 address +}; + /** * @code sock_open(int ifindex, const struct sock_fprog *fprog); *