diff --git a/net/isc-dhcp/files/dhcrelay4.init b/net/isc-dhcp/files/dhcrelay4.init index e1e68711e..9af0f84e1 100644 --- a/net/isc-dhcp/files/dhcrelay4.init +++ b/net/isc-dhcp/files/dhcrelay4.init @@ -26,6 +26,13 @@ start() { fi done + # link selection sub-option (RFC3527) + local link_selection + config_get link_selection ipv4 link_selection + if network_get_device ifname "$link_selection"; then + append args "-l $ifname" + fi + # relay mode local relay_mode config_get relay_mode ipv4 relay_mode diff --git a/net/isc-dhcp/files/etc/config/dhcrelay b/net/isc-dhcp/files/etc/config/dhcrelay index 1b8978256..b3b53b516 100644 --- a/net/isc-dhcp/files/etc/config/dhcrelay +++ b/net/isc-dhcp/files/etc/config/dhcrelay @@ -15,6 +15,9 @@ config dhcrelay ipv4 # 'discard': Don't forward option 'relay_mode' '' + # enable RFC3527 link selection sub-option and use the IP address of + # the specified network interface as "uplink" IP address (e.g. wan) + option 'link_selection' '' config dhcrelay ipv6 # option dhcpserver '2001:db8:1::1' diff --git a/net/isc-dhcp/patches/100-relay-rfc3527-link-selection.patch b/net/isc-dhcp/patches/100-relay-rfc3527-link-selection.patch new file mode 100644 index 000000000..1f593ee2b --- /dev/null +++ b/net/isc-dhcp/patches/100-relay-rfc3527-link-selection.patch @@ -0,0 +1,100 @@ +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -65,6 +65,7 @@ int server_packets_relayed = 0; /* Packe + int client_packet_errors = 0; /* Errors sending packets to clients. */ + + int add_agent_options = 0; /* If nonzero, add relay agent options. */ ++int add_rfc3527_suboption = 0; /* If nonzero, add RFC3527 link selection sub-option. */ + + int agent_option_errors = 0; /* Number of packets forwarded without + agent options because there was no room. */ +@@ -104,6 +105,8 @@ struct server_list { + struct sockaddr_in to; + } *servers; + ++struct interface_info *uplink; ++ + #ifdef DHCPv6 + struct stream_list { + struct stream_list *next; +@@ -144,6 +147,7 @@ static const char url[] = + " [-pf ] [--no-pid]\n"\ + " [-m append|replace|forward|discard]\n" \ + " [-i interface0 [ ... -i interfaceN]\n" \ ++" [-l interface]\n" \ + " server0 [ ... serverN]\n\n" \ + " dhcrelay -6 [-d] [-q] [-I] [-c ] [-p ]\n" \ + " [-pf ] [--no-pid]\n"\ +@@ -157,6 +161,7 @@ static const char url[] = + " [-pf ] [--no-pid]\n"\ + " [-m append|replace|forward|discard]\n" \ + " [-i interface0 [ ... -i interfaceN]\n" \ ++" [-l interface]\n" \ + " server0 [ ... serverN]\n\n" + #endif + +@@ -314,6 +319,20 @@ main(int argc, char **argv) { + agent_relay_mode = discard; + } else + usage(); ++ } else if (!strcmp (argv [i], "-l")) { ++ add_agent_options = 1; ++ add_rfc3527_suboption = 1; ++ if (++i == argc) ++ usage(); ++ ++ status = interface_allocate(&uplink, MDL); ++ if (status != ISC_R_SUCCESS) ++ log_fatal("%s: interface_allocate: %s", ++ argv[i], ++ isc_result_totext(status)); ++ strcpy(uplink->name, argv[i]); ++ interface_snorf(uplink, INTERFACE_REQUESTED); ++ //interface_dereference(&uplink, MDL); + } else if (!strcmp(argv[i], "-D")) { + #ifdef DHCPv6 + if (local_family_set && (local_family == AF_INET6)) { +@@ -685,12 +704,17 @@ do_relay4(struct interface_info *ip, str + ip->addresses[0]))) + return; + ++ /* RFC3527: Replace giaddr address by uplink address. The original ++ * giaddr will be used in the link selection sub-option */ ++ if (add_rfc3527_suboption) ++ packet->giaddr = uplink->addresses[0]; ++ + /* If giaddr is not already set, Set it so the server can + figure out what net it's from and so that we can later + forward the response to the correct net. If it's already + set, the response will be sent directly to the relay agent + that set giaddr, so we won't see it. */ +- if (!packet->giaddr.s_addr) ++ else if (!packet->giaddr.s_addr) + packet->giaddr = ip->addresses[0]; + if (packet->hops < max_hop_count) + packet->hops = packet->hops + 1; +@@ -1062,6 +1086,9 @@ add_relay_agent_options(struct interface + optlen += ip->remote_id_len + 2; /* RAI_REMOTE_ID + len */ + } + ++ if (add_rfc3527_suboption) ++ optlen += 6; ++ + /* We do not support relay option fragmenting(multiple options to + * support an option data exceeding 255 bytes). + */ +@@ -1093,6 +1120,14 @@ add_relay_agent_options(struct interface + memcpy(sp, ip->remote_id, ip->remote_id_len); + sp += ip->remote_id_len; + } ++ ++ if (add_rfc3527_suboption) { ++ *sp++ = RAI_LINK_SELECT; ++ *sp++ = 4u; ++ memcpy(sp, &giaddr.s_addr, 4); ++ sp += 4; ++ log_debug ("RFC3527 link selection sub-option added: %s", inet_ntoa(giaddr)); ++ } + } else { + ++agent_option_errors; + log_error("No room in packet (used %d of %d) "