From c3ef23d7a5a36c6b7fbf4a3d360e101f56b13b4e Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Thu, 2 May 2019 18:30:47 +0000 Subject: [PATCH 1/8] Change URL for isc-dhcp source repository --- src/isc-dhcp/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/isc-dhcp/Makefile b/src/isc-dhcp/Makefile index 482abc58dd01..60c6a391c76b 100644 --- a/src/isc-dhcp/Makefile +++ b/src/isc-dhcp/Makefile @@ -11,7 +11,7 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : rm -rf ./isc-dhcp # Clone isc-dhcp repo - git clone https://salsa.debian.org/berni/isc-dhcp.git + git clone https://salsa.debian.org/dhcp-team/isc-dhcp.git pushd ./isc-dhcp # Reset HEAD to the commit of the proper tag From e831527055b6d02b22f4a212c7237b538289611f Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Thu, 2 May 2019 20:04:12 +0000 Subject: [PATCH 2/8] Port upstream patches to isc-dhcp-relay to support upstream/downstream interfaces --- ...anges-from-commit-f2e70402f0f2955f39.patch | 102 ++++++++++++ ...anges-from-commit-edd6d8881bc4d8ec4b.patch | 157 ++++++++++++++++++ src/isc-dhcp/patch/series | 2 + 3 files changed, 261 insertions(+) create mode 100644 src/isc-dhcp/patch/0005-Port-upstream-changes-from-commit-f2e70402f0f2955f39.patch create mode 100644 src/isc-dhcp/patch/0006-Port-upstream-changes-from-commit-edd6d8881bc4d8ec4b.patch diff --git a/src/isc-dhcp/patch/0005-Port-upstream-changes-from-commit-f2e70402f0f2955f39.patch b/src/isc-dhcp/patch/0005-Port-upstream-changes-from-commit-f2e70402f0f2955f39.patch new file mode 100644 index 000000000000..2efbfd6d664d --- /dev/null +++ b/src/isc-dhcp/patch/0005-Port-upstream-changes-from-commit-f2e70402f0f2955f39.patch @@ -0,0 +1,102 @@ +From 0092eed7a80f38078a38fedf601952d0d25c6183 Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Thu, 2 May 2019 19:20:59 +0000 +Subject: [PATCH 1/2] Port upstream changes from commit + f2e70402f0f2955f392edc4eb2dd835b820e25bc to add '-iu' option + +--- + common/discover.c | 8 +++++++- + relay/dhcrelay.c | 36 +++++++++++++++++++++++++++++++++++- + 2 files changed, 42 insertions(+), 2 deletions(-) + +diff --git a/common/discover.c b/common/discover.c +index 3cd64a7..e20d9d5 100644 +--- a/common/discover.c ++++ b/common/discover.c +@@ -948,8 +948,14 @@ discover_interfaces(int state) { + ir = 0; + else if (state == DISCOVER_UNCONFIGURED) + ir = INTERFACE_REQUESTED | INTERFACE_AUTOMATIC; +- else ++ else { + ir = INTERFACE_REQUESTED; ++ if (state == DISCOVER_RELAY && local_family == AF_INET) { ++ /* We're a v4 relay without specifically requested ++ * interfaces, so mark them all as bidirectional. */ ++ ir |= INTERFACE_STREAMS; ++ } ++ } + + /* Cycle through the list of interfaces looking for IP addresses. */ + while (next_iface(&info, &err, &ifaces)) { +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index 15f0acf..8051e17 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -172,6 +172,7 @@ static const char url[] = + " [-m append|replace|forward|discard]\n" \ + " [--name-alias-map-file ]\n" \ + " [-i interface0 [ ... -i interfaceN]\n" \ ++" [-iu interface0 [ ... -iu interfaceN]\n" \ + " server0 [ ... serverN]\n\n" \ + " dhcrelay -6 [-d] [-q] [-I] [-c ] [-p ]\n" \ + " [-pf ] [--no-pid]\n" \ +@@ -188,6 +189,7 @@ static const char url[] = + " [-pf ] [--no-pid]\n"\ + " [-m append|replace|forward|discard]\n" \ + " [-i interface0 [ ... -i interfaceN]\n" \ ++" [-iu interface0 [ ... -iu interfaceN]\n" \ + " server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE + #endif + +@@ -304,7 +306,34 @@ main(int argc, char **argv) { + isc_result_totext(status)); + } + strcpy(tmp->name, argv[i]); +- interface_snorf(tmp, INTERFACE_REQUESTED); ++ interface_snorf(tmp, (INTERFACE_REQUESTED | ++ INTERFACE_STREAMS)); ++ interface_dereference(&tmp, MDL); ++ } else if (!strcmp(argv[i], "-iu")) { ++#ifdef DHCPv6 ++ if (local_family_set && (local_family == AF_INET6)) { ++ usage(); ++ } ++ local_family_set = 1; ++ local_family = AF_INET; ++#endif ++ if (++i == argc) { ++ usage(); ++ } ++ if (strlen(argv[i]) >= sizeof(tmp->name)) { ++ log_fatal("%s: interface name too long " ++ "(is %ld)", ++ argv[i], (long)strlen(argv[i])); ++ } ++ status = interface_allocate(&tmp, MDL); ++ if (status != ISC_R_SUCCESS) { ++ log_fatal("%s: interface_allocate: %s", ++ argv[i], ++ isc_result_totext(status)); ++ } ++ strcpy(tmp->name, argv[i]); ++ interface_snorf(tmp, (INTERFACE_REQUESTED | ++ INTERFACE_UPSTREAM)); + interface_dereference(&tmp, MDL); + } else if (!strcmp(argv[i], "-a")) { + #ifdef DHCPv6 +@@ -691,6 +720,11 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet, + + /* If it's a bootreply, forward it to the client. */ + if (packet->op == BOOTREPLY) { ++ if (!(ip->flags & INTERFACE_UPSTREAM)) { ++ log_debug("Dropping reply received on %s", ip->name); ++ return; ++ } ++ + if (!(packet->flags & htons(BOOTP_BROADCAST)) && + can_unicast_without_arp(out)) { + to.sin_addr = packet->yiaddr; +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0006-Port-upstream-changes-from-commit-edd6d8881bc4d8ec4b.patch b/src/isc-dhcp/patch/0006-Port-upstream-changes-from-commit-edd6d8881bc4d8ec4b.patch new file mode 100644 index 000000000000..952d1cf66a8a --- /dev/null +++ b/src/isc-dhcp/patch/0006-Port-upstream-changes-from-commit-edd6d8881bc4d8ec4b.patch @@ -0,0 +1,157 @@ +From 1d59a7bd4dc9cb3cd13aedf604a15a8589febe43 Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Thu, 2 May 2019 19:46:42 +0000 +Subject: [PATCH 2/2] Port upstream changes from commit + edd6d8881bc4d8ec4b04173c66c1c840756bbe76 to add '-id' option + +--- + relay/dhcrelay.c | 89 +++++++++++++++++++++++++++++++++--------------- + 1 file changed, 61 insertions(+), 28 deletions(-) + +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index 8051e17..292ba4f 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -142,6 +142,8 @@ static int strip_relay_agent_options(struct interface_info *, + struct interface_info **, + struct dhcp_packet *, unsigned); + ++static void request_v4_interface(const char* name, int flags); ++ + static int load_interface_alias_map(const char *port_alias_map_file_path); + static int get_interface_alias_by_name(const char *if_name, char *if_alias_out); + static void free_interface_alias_map(void); +@@ -173,6 +175,7 @@ static const char url[] = + " [--name-alias-map-file ]\n" \ + " [-i interface0 [ ... -i interfaceN]\n" \ + " [-iu interface0 [ ... -iu interfaceN]\n" \ ++" [-id interface0 [ ... -id interfaceN]\n" \ + " server0 [ ... serverN]\n\n" \ + " dhcrelay -6 [-d] [-q] [-I] [-c ] [-p ]\n" \ + " [-pf ] [--no-pid]\n" \ +@@ -190,6 +193,7 @@ static const char url[] = + " [-m append|replace|forward|discard]\n" \ + " [-i interface0 [ ... -i interfaceN]\n" \ + " [-iu interface0 [ ... -iu interfaceN]\n" \ ++" [-id interface0 [ ... -id interfaceN]\n" \ + " server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE + #endif + +@@ -294,21 +298,8 @@ main(int argc, char **argv) { + if (++i == argc) { + usage(); + } +- if (strlen(argv[i]) >= sizeof(tmp->name)) { +- log_fatal("%s: interface name too long " +- "(is %ld)", +- argv[i], (long)strlen(argv[i])); +- } +- status = interface_allocate(&tmp, MDL); +- if (status != ISC_R_SUCCESS) { +- log_fatal("%s: interface_allocate: %s", +- argv[i], +- isc_result_totext(status)); +- } +- strcpy(tmp->name, argv[i]); +- interface_snorf(tmp, (INTERFACE_REQUESTED | +- INTERFACE_STREAMS)); +- interface_dereference(&tmp, MDL); ++ ++ request_v4_interface(argv[i], INTERFACE_STREAMS); + } else if (!strcmp(argv[i], "-iu")) { + #ifdef DHCPv6 + if (local_family_set && (local_family == AF_INET6)) { +@@ -320,21 +311,21 @@ main(int argc, char **argv) { + if (++i == argc) { + usage(); + } +- if (strlen(argv[i]) >= sizeof(tmp->name)) { +- log_fatal("%s: interface name too long " +- "(is %ld)", +- argv[i], (long)strlen(argv[i])); ++ ++ request_v4_interface(argv[i], INTERFACE_UPSTREAM); ++ } else if (!strcmp(argv[i], "-id")) { ++#ifdef DHCPv6 ++ if (local_family_set && (local_family == AF_INET6)) { ++ usage(); + } +- status = interface_allocate(&tmp, MDL); +- if (status != ISC_R_SUCCESS) { +- log_fatal("%s: interface_allocate: %s", +- argv[i], +- isc_result_totext(status)); ++ local_family_set = 1; ++ local_family = AF_INET; ++#endif ++ if (++i == argc) { ++ usage(); + } +- strcpy(tmp->name, argv[i]); +- interface_snorf(tmp, (INTERFACE_REQUESTED | +- INTERFACE_UPSTREAM)); +- interface_dereference(&tmp, MDL); ++ ++ request_v4_interface(argv[i], INTERFACE_DOWNSTREAM); + } else if (!strcmp(argv[i], "-a")) { + #ifdef DHCPv6 + if (local_family_set && (local_family == AF_INET6)) { +@@ -782,6 +773,11 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet, + if (out) + return; + ++ if (!(ip->flags & INTERFACE_DOWNSTREAM)) { ++ log_debug("Dropping request received on %s", ip->name); ++ return; ++ } ++ + /* Add relay agent options if indicated. If something goes wrong, + drop the packet. */ + if (!(length = add_relay_agent_options(ip, packet, length, +@@ -1991,6 +1987,43 @@ dhcp_set_control_state(control_object_state_t oldstate, + exit(0); + } + ++/*! ++ * ++ * \brief Allocate an interface as requested with a given set of flags ++ * ++ * The requested interface is allocated, its flags field is set to ++ * INTERFACE_REQUESTED OR'd with the given flags, and then added to ++ * the list of interfaces. ++ * ++ * \param name - name of the requested interface ++ * \param flags - additional flags for the interface ++ * ++ * \return Nothing ++ */ ++void request_v4_interface(const char* name, int flags) { ++ struct interface_info *tmp = NULL; ++ int len = strlen(name); ++ isc_result_t status; ++ ++ if (len >= sizeof(tmp->name)) { ++ log_fatal("%s: interface name too long (is %d)", name, len); ++ } ++ ++ status = interface_allocate(&tmp, MDL); ++ if (status != ISC_R_SUCCESS) { ++ log_fatal("%s: interface_allocate: %s", name, ++ isc_result_totext(status)); ++ } ++ ++ log_debug("Requesting: %s as upstream: %c downstream: %c", name, ++ (flags & INTERFACE_UPSTREAM ? 'Y' : 'N'), ++ (flags & INTERFACE_DOWNSTREAM ? 'Y' : 'N')); ++ ++ strncpy(tmp->name, name, len); ++ interface_snorf(tmp, (INTERFACE_REQUESTED | flags)); ++ interface_dereference(&tmp, MDL); ++} ++ + #define MAX_PORT_CONFIG_LINE_LEN 1024 + + // Allocates and loads global map g_interface_name_alias_map +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/series b/src/isc-dhcp/patch/series index 17e5e152483b..baf3060b8cef 100644 --- a/src/isc-dhcp/patch/series +++ b/src/isc-dhcp/patch/series @@ -3,3 +3,5 @@ 0002-Support-for-obtaining-name-of-physical-interface-tha.patch 0003-Support-for-loading-port-alias-map-file-to-replace-p.patch 0004-Bugfix-Don-t-print-log-messages-to-stderr-in-release.patch +0005-Port-upstream-changes-from-commit-f2e70402f0f2955f39.patch +0006-Port-upstream-changes-from-commit-edd6d8881bc4d8ec4b.patch From 48a3183b53e29bbd256c2ac0a70f3dcb0637c9b6 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Thu, 2 May 2019 21:17:58 +0000 Subject: [PATCH 3/8] Modify supervisor conf to generate dhcrelay commands with '-id' and '-iu' options --- .../docker-dhcp-relay.supervisord.conf.j2 | 10 +++++++--- .../sample_output/docker-dhcp-relay.supervisord.conf | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 b/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 index 747f65a3aaf6..76b2725e2d2c 100644 --- a/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 +++ b/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 @@ -46,12 +46,16 @@ isc-dhcp-relay-{{ vlan_name }} {% for vlan_name in VLAN -%} {%- if VLAN[vlan_name]['dhcp_servers'] -%} [program:isc-dhcp-relay-{{ vlan_name }}] -command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -i {{ vlan_name }} +command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id {{ vlan_name }} +{#- We treat all other interfaces besides this VLAN as potential upstream interfaces -#} +{%- for (name, prefix) in VLAN_INTERFACE -%} +{%- if prefix | ipv4 and name != vlan_name %} -iu {{ name }}{% endif -%} +{%- endfor -%} {%- for (name, prefix) in INTERFACE -%} -{%- if prefix | ipv4 %} -i {{ name }}{% endif -%} +{%- if prefix | ipv4 %} -iu {{ name }}{% endif -%} {%- endfor -%} {%- for (name, prefix) in PORTCHANNEL_INTERFACE -%} -{%- if prefix | ipv4 %} -i {{ name }}{% endif -%} +{%- if prefix | ipv4 %} -iu {{ name }}{% endif -%} {%- endfor -%} {%- for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %} {{ dhcp_server }}{% endfor %} diff --git a/src/sonic-config-engine/tests/sample_output/docker-dhcp-relay.supervisord.conf b/src/sonic-config-engine/tests/sample_output/docker-dhcp-relay.supervisord.conf index f955546cdc09..7f63a61fd074 100644 --- a/src/sonic-config-engine/tests/sample_output/docker-dhcp-relay.supervisord.conf +++ b/src/sonic-config-engine/tests/sample_output/docker-dhcp-relay.supervisord.conf @@ -23,7 +23,7 @@ stderr_logfile=syslog programs=isc-dhcp-relay-Vlan1000 [program:isc-dhcp-relay-Vlan1000] -command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -i Vlan1000 -i PortChannel02 -i PortChannel03 -i PortChannel04 -i PortChannel01 192.0.0.1 192.0.0.2 +command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id Vlan1000 -iu PortChannel02 -iu PortChannel03 -iu PortChannel04 -iu PortChannel01 192.0.0.1 192.0.0.2 priority=3 autostart=false autorestart=false From 8d75963141f5272ca2f3d3a90a0833fb712a44ee Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Sun, 5 May 2019 19:58:01 +0000 Subject: [PATCH 4/8] Comments; Also clean up jinja2 syntax --- .../docker-dhcp-relay.supervisord.conf.j2 | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 b/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 index 76b2725e2d2c..cd18dfa13108 100644 --- a/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 +++ b/dockers/docker-dhcp-relay/docker-dhcp-relay.supervisord.conf.j2 @@ -32,32 +32,33 @@ stderr_logfile=syslog {% if num_relays.count > 0 %} [group:isc-dhcp-relay] programs= -{%- set add_preceding_comma = { 'flag': False } -%} -{%- for vlan_name in VLAN -%} -{%- if VLAN[vlan_name]['dhcp_servers'] -%} -{%- if add_preceding_comma.flag %},{% endif -%} -{%- set _dummy = add_preceding_comma.update({'flag': True}) -%} +{%- set add_preceding_comma = { 'flag': False } %} +{% for vlan_name in VLAN %} +{% if VLAN[vlan_name]['dhcp_servers'] %} +{% if add_preceding_comma.flag %},{% endif %} +{% set _dummy = add_preceding_comma.update({'flag': True}) %} isc-dhcp-relay-{{ vlan_name }} {%- endif %} {% endfor %} {# Create a program entry for each DHCP relay agent instance #} -{% for vlan_name in VLAN -%} -{%- if VLAN[vlan_name]['dhcp_servers'] -%} +{% for vlan_name in VLAN %} +{% if VLAN[vlan_name]['dhcp_servers'] %} [program:isc-dhcp-relay-{{ vlan_name }}] +{# We treat this VLAN as a downstream interface (-id), as we only want to listen for requests #} command=/usr/sbin/dhcrelay -d -m discard -a %%h:%%p %%P --name-alias-map-file /tmp/port-name-alias-map.txt -id {{ vlan_name }} -{#- We treat all other interfaces besides this VLAN as potential upstream interfaces -#} -{%- for (name, prefix) in VLAN_INTERFACE -%} -{%- if prefix | ipv4 and name != vlan_name %} -iu {{ name }}{% endif -%} -{%- endfor -%} -{%- for (name, prefix) in INTERFACE -%} -{%- if prefix | ipv4 %} -iu {{ name }}{% endif -%} -{%- endfor -%} -{%- for (name, prefix) in PORTCHANNEL_INTERFACE -%} -{%- if prefix | ipv4 %} -iu {{ name }}{% endif -%} -{%- endfor -%} -{%- for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %} {{ dhcp_server }}{% endfor %} +{#- We treat all other interfaces as upstream interfaces (-iu), as we only want to listen for replies #} +{% for (name, prefix) in VLAN_INTERFACE %} +{% if prefix | ipv4 and name != vlan_name %} -iu {{ name }}{% endif -%} +{% endfor %} +{% for (name, prefix) in INTERFACE %} +{% if prefix | ipv4 %} -iu {{ name }}{% endif -%} +{% endfor %} +{% for (name, prefix) in PORTCHANNEL_INTERFACE %} +{% if prefix | ipv4 %} -iu {{ name }}{% endif -%} +{% endfor %} +{% for dhcp_server in VLAN[vlan_name]['dhcp_servers'] %} {{ dhcp_server }}{% endfor %} priority=3 autostart=false From 7beae069f6f466fbe25dfca4cde1ba9346f0cd6d Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Sun, 5 May 2019 22:56:07 +0000 Subject: [PATCH 5/8] Patch relay to open one socket per interface and send to all servers on all upstream interfaces --- ...CKETS-to-force-dhcrelay-to-create-an.patch | 26 ++++++++ ...t-per-interface-send-to-ALL-servers-.patch | 64 +++++++++++++++++++ src/isc-dhcp/patch/series | 2 + 3 files changed, 92 insertions(+) create mode 100644 src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch create mode 100644 src/isc-dhcp/patch/0008-If-using-a-socket-per-interface-send-to-ALL-servers-.patch diff --git a/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch b/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch new file mode 100644 index 000000000000..266eb5774b99 --- /dev/null +++ b/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch @@ -0,0 +1,26 @@ +From 56b3863e26965549072e40113a065ab6aab5b658 Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Sat, 4 May 2019 04:30:42 +0000 +Subject: [PATCH 1/2] Uncomment 'USE_SOCKETS' to force dhcrelay to create and + bind separate sockets to each interface + +--- + includes/site.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/includes/site.h b/includes/site.h +index f11fefb..fd129a1 100644 +--- a/includes/site.h ++++ b/includes/site.h +@@ -162,7 +162,7 @@ + the aforementioned problems do not matter to you, or if no other + API is supported for your system, you may want to go with it. */ + +-/* #define USE_SOCKETS */ ++#define USE_SOCKETS + + /* Define this to use the Sun Streams NIT API. + +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0008-If-using-a-socket-per-interface-send-to-ALL-servers-.patch b/src/isc-dhcp/patch/0008-If-using-a-socket-per-interface-send-to-ALL-servers-.patch new file mode 100644 index 000000000000..25abdc71bda2 --- /dev/null +++ b/src/isc-dhcp/patch/0008-If-using-a-socket-per-interface-send-to-ALL-servers-.patch @@ -0,0 +1,64 @@ +From 6ee1b280c1bf06b5dedef33522eccfbcb70d02bd Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Sun, 5 May 2019 22:52:49 +0000 +Subject: [PATCH 2/2] If using a socket per interface, send to ALL servers on + ALL upstream interfaces + +--- + relay/dhcrelay.c | 38 ++++++++++++++++++++++++++++---------- + 1 file changed, 28 insertions(+), 10 deletions(-) + +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index 292ba4f..72bbe1c 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -799,18 +799,36 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet, + /* Otherwise, it's a BOOTREQUEST, so forward it to all the + servers. */ + for (sp = servers; sp; sp = sp->next) { +- if (send_packet((fallback_interface +- ? fallback_interface : interfaces), +- NULL, packet, length, ip->addresses[0], +- &sp->to, NULL) < 0) { +- ++client_packet_errors; ++ if (fallback_interface) { ++ if (send_packet(fallback_interface, NULL, packet, ++ length, ip->addresses[0],&sp->to, NULL) < 0) { ++ ++client_packet_errors; ++ } else { ++ log_debug("Forwarded BOOTREQUEST for %s to %s on fallback interface", ++ print_hw_addr(packet->htype, packet->hlen, ++ packet->chaddr), ++ inet_ntoa(sp->to.sin_addr)); ++ ++ ++client_packets_relayed; ++ } + } else { +- log_debug("Forwarded BOOTREQUEST for %s to %s", +- print_hw_addr(packet->htype, packet->hlen, +- packet->chaddr), +- inet_ntoa(sp->to.sin_addr)); ++ for (out = interfaces; out; out = out->next) { ++ // Only relay BOOTREQUEST on upstream interfaces ++ if (!(out->flags & INTERFACE_UPSTREAM)) ++ continue; ++ ++ if (send_packet(out, NULL, packet, ++ length, ip->addresses[0],&sp->to, NULL) < 0) { ++ ++client_packet_errors; ++ } else { ++ log_debug("Forwarded BOOTREQUEST for %s to %s on interface %s", ++ print_hw_addr(packet->htype, packet->hlen, ++ packet->chaddr), ++ inet_ntoa(sp->to.sin_addr), out->name); + +- ++client_packets_relayed; ++ ++client_packets_relayed; ++ } ++ } + } + } + +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/series b/src/isc-dhcp/patch/series index baf3060b8cef..1f96daa6a39c 100644 --- a/src/isc-dhcp/patch/series +++ b/src/isc-dhcp/patch/series @@ -5,3 +5,5 @@ 0004-Bugfix-Don-t-print-log-messages-to-stderr-in-release.patch 0005-Port-upstream-changes-from-commit-f2e70402f0f2955f39.patch 0006-Port-upstream-changes-from-commit-edd6d8881bc4d8ec4b.patch +0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch +0008-If-using-a-socket-per-interface-send-to-ALL-servers-.patch From f1b5357187b95487fef518785fbd0872d18127cd Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Thu, 9 May 2019 01:17:35 +0000 Subject: [PATCH 6/8] Patch relay agent to properly forward BOOTREQUEST only on appropriate interfaace if it is a directed broadcast --- ...CKETS-to-force-dhcrelay-to-create-an.patch | 4 +- ...VE_SO_BINDTODEVICE-has-a-chance-to-b.patch | 122 ++++++++++++++++ ...t-per-interface-send-to-ALL-servers-.patch | 64 --------- ...f-BOOTREQUEST-is-directed-broadcast-.patch | 130 ++++++++++++++++++ src/isc-dhcp/patch/series | 3 +- 5 files changed, 256 insertions(+), 67 deletions(-) create mode 100644 src/isc-dhcp/patch/0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch delete mode 100644 src/isc-dhcp/patch/0008-If-using-a-socket-per-interface-send-to-ALL-servers-.patch create mode 100644 src/isc-dhcp/patch/0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch diff --git a/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch b/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch index 266eb5774b99..a98e2c3b2abf 100644 --- a/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch +++ b/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch @@ -1,7 +1,7 @@ -From 56b3863e26965549072e40113a065ab6aab5b658 Mon Sep 17 00:00:00 2001 +From f8fc69c18abee41bdea38d0fff4d9c6f65f46884 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Sat, 4 May 2019 04:30:42 +0000 -Subject: [PATCH 1/2] Uncomment 'USE_SOCKETS' to force dhcrelay to create and +Subject: [PATCH 1/3] Uncomment 'USE_SOCKETS' to force dhcrelay to create and bind separate sockets to each interface --- diff --git a/src/isc-dhcp/patch/0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch b/src/isc-dhcp/patch/0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch new file mode 100644 index 000000000000..9a3e50079c60 --- /dev/null +++ b/src/isc-dhcp/patch/0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch @@ -0,0 +1,122 @@ +From c0bb9b992f5adc6272b491baa62666a02f3b5387 Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Wed, 8 May 2019 18:08:13 +0000 +Subject: [PATCH 2/3] Bugfix: Ensure HAVE_SO_BINDTODEVICE has a chance to be + defined before it is referenced + +--- + includes/osdep.h | 93 ++++++++++++++++++++++++------------------------ + 1 file changed, 47 insertions(+), 46 deletions(-) + +diff --git a/includes/osdep.h b/includes/osdep.h +index 5ae0c35..670b356 100644 +--- a/includes/osdep.h ++++ b/includes/osdep.h +@@ -139,52 +139,6 @@ + # define USE_UPF_RECEIVE + #endif + +-/* Porting:: +- +- If you add support for sending packets directly out an interface, +- and your support does not do ARP or routing, you must use a fallback +- mechanism to deal with packets that need to be sent to routers. +- Currently, all low-level packet interfaces use BSD sockets as a +- fallback. */ +- +-#if defined (USE_BPF_SEND) || defined (USE_NIT_SEND) || \ +- defined (USE_DLPI_SEND) || defined (USE_UPF_SEND) || \ +- defined (USE_LPF_SEND) || \ +- (defined (USE_SOCKET_SEND) && defined (HAVE_SO_BINDTODEVICE)) +-# define USE_SOCKET_FALLBACK +-# define USE_FALLBACK +-#endif +- +-/* Porting:: +- +- If you add support for sending packets directly out an interface +- and need to be able to assemble packets, add the USE_XXX_SEND +- definition for your interface to the list tested below. */ +- +-#if defined (USE_RAW_SEND) || defined (USE_BPF_SEND) || \ +- defined (USE_NIT_SEND) || defined (USE_UPF_SEND) || \ +- defined (USE_DLPI_SEND) || defined (USE_LPF_SEND) +-# define PACKET_ASSEMBLY +-#endif +- +-/* Porting:: +- +- If you add support for receiving packets directly from an interface +- and need to be able to decode raw packets, add the USE_XXX_RECEIVE +- definition for your interface to the list tested below. */ +- +-#if defined (USE_RAW_RECEIVE) || defined (USE_BPF_SEND) || \ +- defined (USE_NIT_RECEIVE) || defined (USE_UPF_RECEIVE) || \ +- defined (USE_DLPI_RECEIVE) || defined (USE_LPF_RECEIVE) +-# define PACKET_DECODING +-#endif +- +-/* If we don't have a DLPI packet filter, we have to filter in userland. +- Probably not worth doing, actually. */ +-#if defined (USE_DLPI_RECEIVE) && !defined (USE_DLPI_PFMOD) +-# define USERLAND_FILTER +-#endif +- + /* jmp_buf is assumed to be a struct unless otherwise defined in the + system header. */ + #ifndef jbp_decl +@@ -288,4 +242,51 @@ + # define STDERR_FILENO 2 + #endif + ++/* Porting:: ++ ++ If you add support for sending packets directly out an interface, ++ and your support does not do ARP or routing, you must use a fallback ++ mechanism to deal with packets that need to be sent to routers. ++ Currently, all low-level packet interfaces use BSD sockets as a ++ fallback. */ ++ ++#if defined (USE_BPF_SEND) || defined (USE_NIT_SEND) || \ ++ defined (USE_DLPI_SEND) || defined (USE_UPF_SEND) || \ ++ defined (USE_LPF_SEND) || \ ++ (defined (USE_SOCKET_SEND) && defined (HAVE_SO_BINDTODEVICE)) ++# define USE_SOCKET_FALLBACK ++# define USE_FALLBACK ++#endif ++ ++/* Porting:: ++ ++ If you add support for sending packets directly out an interface ++ and need to be able to assemble packets, add the USE_XXX_SEND ++ definition for your interface to the list tested below. */ ++ ++#if defined (USE_RAW_SEND) || defined (USE_BPF_SEND) || \ ++ defined (USE_NIT_SEND) || defined (USE_UPF_SEND) || \ ++ defined (USE_DLPI_SEND) || defined (USE_LPF_SEND) ++# define PACKET_ASSEMBLY ++#endif ++ ++/* Porting:: ++ ++ If you add support for receiving packets directly from an interface ++ and need to be able to decode raw packets, add the USE_XXX_RECEIVE ++ definition for your interface to the list tested below. */ ++ ++#if defined (USE_RAW_RECEIVE) || defined (USE_BPF_SEND) || \ ++ defined (USE_NIT_RECEIVE) || defined (USE_UPF_RECEIVE) || \ ++ defined (USE_DLPI_RECEIVE) || defined (USE_LPF_RECEIVE) ++# define PACKET_DECODING ++#endif ++ ++/* If we don't have a DLPI packet filter, we have to filter in userland. ++ Probably not worth doing, actually. */ ++#if defined (USE_DLPI_RECEIVE) && !defined (USE_DLPI_PFMOD) ++# define USERLAND_FILTER ++#endif ++ ++ + #endif /* __ISC_DHCP_OSDEP_H__ */ +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0008-If-using-a-socket-per-interface-send-to-ALL-servers-.patch b/src/isc-dhcp/patch/0008-If-using-a-socket-per-interface-send-to-ALL-servers-.patch deleted file mode 100644 index 25abdc71bda2..000000000000 --- a/src/isc-dhcp/patch/0008-If-using-a-socket-per-interface-send-to-ALL-servers-.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 6ee1b280c1bf06b5dedef33522eccfbcb70d02bd Mon Sep 17 00:00:00 2001 -From: Joe LeVeque -Date: Sun, 5 May 2019 22:52:49 +0000 -Subject: [PATCH 2/2] If using a socket per interface, send to ALL servers on - ALL upstream interfaces - ---- - relay/dhcrelay.c | 38 ++++++++++++++++++++++++++++---------- - 1 file changed, 28 insertions(+), 10 deletions(-) - -diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c -index 292ba4f..72bbe1c 100644 ---- a/relay/dhcrelay.c -+++ b/relay/dhcrelay.c -@@ -799,18 +799,36 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet, - /* Otherwise, it's a BOOTREQUEST, so forward it to all the - servers. */ - for (sp = servers; sp; sp = sp->next) { -- if (send_packet((fallback_interface -- ? fallback_interface : interfaces), -- NULL, packet, length, ip->addresses[0], -- &sp->to, NULL) < 0) { -- ++client_packet_errors; -+ if (fallback_interface) { -+ if (send_packet(fallback_interface, NULL, packet, -+ length, ip->addresses[0],&sp->to, NULL) < 0) { -+ ++client_packet_errors; -+ } else { -+ log_debug("Forwarded BOOTREQUEST for %s to %s on fallback interface", -+ print_hw_addr(packet->htype, packet->hlen, -+ packet->chaddr), -+ inet_ntoa(sp->to.sin_addr)); -+ -+ ++client_packets_relayed; -+ } - } else { -- log_debug("Forwarded BOOTREQUEST for %s to %s", -- print_hw_addr(packet->htype, packet->hlen, -- packet->chaddr), -- inet_ntoa(sp->to.sin_addr)); -+ for (out = interfaces; out; out = out->next) { -+ // Only relay BOOTREQUEST on upstream interfaces -+ if (!(out->flags & INTERFACE_UPSTREAM)) -+ continue; -+ -+ if (send_packet(out, NULL, packet, -+ length, ip->addresses[0],&sp->to, NULL) < 0) { -+ ++client_packet_errors; -+ } else { -+ log_debug("Forwarded BOOTREQUEST for %s to %s on interface %s", -+ print_hw_addr(packet->htype, packet->hlen, -+ packet->chaddr), -+ inet_ntoa(sp->to.sin_addr), out->name); - -- ++client_packets_relayed; -+ ++client_packets_relayed; -+ } -+ } - } - } - --- -2.17.1 - diff --git a/src/isc-dhcp/patch/0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch b/src/isc-dhcp/patch/0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch new file mode 100644 index 000000000000..09f5aafc8a71 --- /dev/null +++ b/src/isc-dhcp/patch/0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch @@ -0,0 +1,130 @@ +From 822491fc285c65fd0d09435e14a29e53e007414c Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Sun, 5 May 2019 22:52:49 +0000 +Subject: [PATCH 3/3] If destination of BOOTREQUEST is directed broadcast, + forward on that interface. Otherwise forward on fallback or all upstream + interfaces + +--- + relay/dhcrelay.c | 96 +++++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 86 insertions(+), 10 deletions(-) + +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index 292ba4f..c4c3234 100644 +--- a/relay/dhcrelay.c ++++ b/relay/dhcrelay.c +@@ -30,6 +30,7 @@ + #include + #include + #include ++#include + + TIME default_lease_time = 43200; /* 12 hours... */ + TIME max_lease_time = 86400; /* 24 hours... */ +@@ -799,18 +800,93 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet, + /* Otherwise, it's a BOOTREQUEST, so forward it to all the + servers. */ + for (sp = servers; sp; sp = sp->next) { +- if (send_packet((fallback_interface +- ? fallback_interface : interfaces), +- NULL, packet, length, ip->addresses[0], +- &sp->to, NULL) < 0) { +- ++client_packet_errors; ++ int packet_relay_attempted = 0; ++ ++ log_debug("Server IP: %s", inet_ntoa(sp->to.sin_addr)); ++ ++ /* If the server's IP address is the broadcast IP of one ++ of our interfaces, we send it directly on that interface's ++ socket, because the kernel will drop directed broadcast ++ packets if we send on the fallback. */ ++ for (out = interfaces; out; out = out->next) { ++ struct in_addr out_addr, out_netmask, out_bcast_addr; ++ ++ // Only relay BOOTREQUEST on upstream interfaces ++ if (!(out->flags & INTERFACE_UPSTREAM)) ++ continue; ++ ++ // Calculate interface's broadcast using IP and netmask ++ if (ioctl(out->wfdesc, SIOCGIFNETMASK, out->ifp) != 0) { ++ log_info("Unable to get netmask for interface %s", out->name); ++ continue; ++ } ++ ++ out_addr = out->addresses[0]; ++ log_debug("Iface %s addr: %s", out->name, inet_ntoa(out_addr)); ++ ++ out_netmask = ((struct sockaddr_in *)&out->ifp->ifr_netmask)->sin_addr; ++ log_debug("Iface %s netmask: %s", out->name, inet_ntoa(out_netmask)); ++ ++ // Broadcast = ip_addr | ~netmask ++ out_bcast_addr.s_addr = out->addresses[0].s_addr | ~out_netmask.s_addr; ++ log_debug("Iface %s broadcast: %s", out->name, inet_ntoa(out_bcast_addr)); ++ ++ if (sp->to.sin_addr.s_addr == out_bcast_addr.s_addr) { ++ log_debug("Packet destined for broadcast IP of %s", out->name); ++ if (send_packet(out, NULL, packet, ++ length, ip->addresses[0],&sp->to, NULL) < 0) { ++ ++client_packet_errors; ++ } else { ++ log_debug("Forwarded BOOTREQUEST for %s to %s on interface %s", ++ print_hw_addr(packet->htype, packet->hlen, ++ packet->chaddr), ++ inet_ntoa(sp->to.sin_addr), out->name); ++ ++ ++client_packets_relayed; ++ } ++ ++ packet_relay_attempted = 1; ++ ++ break; ++ } ++ ++ } ++ ++ if (packet_relay_attempted) ++ continue; ++ ++ /* Otherwise, if we have a fallback interface, we send the packet ++ on it. If not, we send the packet out all interfaces.*/ ++ if (fallback_interface) { ++ if (send_packet(fallback_interface, NULL, packet, ++ length, ip->addresses[0],&sp->to, NULL) < 0) { ++ ++client_packet_errors; ++ } else { ++ log_debug("Forwarded BOOTREQUEST for %s to %s on fallback interface", ++ print_hw_addr(packet->htype, packet->hlen, ++ packet->chaddr), ++ inet_ntoa(sp->to.sin_addr)); ++ ++ ++client_packets_relayed; ++ } + } else { +- log_debug("Forwarded BOOTREQUEST for %s to %s", +- print_hw_addr(packet->htype, packet->hlen, +- packet->chaddr), +- inet_ntoa(sp->to.sin_addr)); ++ for (out = interfaces; out; out = out->next) { ++ // Only relay BOOTREQUEST on upstream interfaces ++ if (!(out->flags & INTERFACE_UPSTREAM)) ++ continue; ++ ++ if (send_packet(out, NULL, packet, ++ length, ip->addresses[0],&sp->to, NULL) < 0) { ++ ++client_packet_errors; ++ } else { ++ log_debug("Forwarded BOOTREQUEST for %s to %s on interface %s", ++ print_hw_addr(packet->htype, packet->hlen, ++ packet->chaddr), ++ inet_ntoa(sp->to.sin_addr), out->name); + +- ++client_packets_relayed; ++ ++client_packets_relayed; ++ } ++ } + } + } + +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/series b/src/isc-dhcp/patch/series index 1f96daa6a39c..b997b147e3a6 100644 --- a/src/isc-dhcp/patch/series +++ b/src/isc-dhcp/patch/series @@ -6,4 +6,5 @@ 0005-Port-upstream-changes-from-commit-f2e70402f0f2955f39.patch 0006-Port-upstream-changes-from-commit-edd6d8881bc4d8ec4b.patch 0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch -0008-If-using-a-socket-per-interface-send-to-ALL-servers-.patch +0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch +0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch From ff4870fe3b841c628e4849c069b5f152f56ae00d Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Mon, 13 May 2019 21:13:06 +0000 Subject: [PATCH 7/8] Update patch to properly support interfaces with multiple IP addresses assigned --- ...CKETS-to-force-dhcrelay-to-create-an.patch | 2 +- ...VE_SO_BINDTODEVICE-has-a-chance-to-b.patch | 2 +- ...f-BOOTREQUEST-is-directed-broadcast-.patch | 194 +++++++++++++++--- 3 files changed, 166 insertions(+), 32 deletions(-) diff --git a/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch b/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch index a98e2c3b2abf..a007d17ca8eb 100644 --- a/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch +++ b/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch @@ -1,4 +1,4 @@ -From f8fc69c18abee41bdea38d0fff4d9c6f65f46884 Mon Sep 17 00:00:00 2001 +From 1499278795a552685f0d339e9e6f4c452790a16c Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Sat, 4 May 2019 04:30:42 +0000 Subject: [PATCH 1/3] Uncomment 'USE_SOCKETS' to force dhcrelay to create and diff --git a/src/isc-dhcp/patch/0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch b/src/isc-dhcp/patch/0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch index 9a3e50079c60..19697e6cc4db 100644 --- a/src/isc-dhcp/patch/0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch +++ b/src/isc-dhcp/patch/0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch @@ -1,4 +1,4 @@ -From c0bb9b992f5adc6272b491baa62666a02f3b5387 Mon Sep 17 00:00:00 2001 +From ddf74bdf94184b8009cc6ea28b36248ac4803ea9 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Wed, 8 May 2019 18:08:13 +0000 Subject: [PATCH 2/3] Bugfix: Ensure HAVE_SO_BINDTODEVICE has a chance to be diff --git a/src/isc-dhcp/patch/0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch b/src/isc-dhcp/patch/0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch index 09f5aafc8a71..680d6e35d596 100644 --- a/src/isc-dhcp/patch/0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch +++ b/src/isc-dhcp/patch/0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch @@ -1,4 +1,4 @@ -From 822491fc285c65fd0d09435e14a29e53e007414c Mon Sep 17 00:00:00 2001 +From 386f97b7d2eaf9446e125834b70595f5ae67ea14 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Sun, 5 May 2019 22:52:49 +0000 Subject: [PATCH 3/3] If destination of BOOTREQUEST is directed broadcast, @@ -6,11 +6,145 @@ Subject: [PATCH 3/3] If destination of BOOTREQUEST is directed broadcast, interfaces --- - relay/dhcrelay.c | 96 +++++++++++++++++++++++++++++++++++++++++++----- - 1 file changed, 86 insertions(+), 10 deletions(-) + common/discover.c | 46 ++++++++++++++++++++--- + includes/dhcpd.h | 3 ++ + relay/dhcrelay.c | 96 ++++++++++++++++++++++++++++++++++++++++++----- + 3 files changed, 130 insertions(+), 15 deletions(-) +diff --git a/common/discover.c b/common/discover.c +index e20d9d5..bf82735 100644 +--- a/common/discover.c ++++ b/common/discover.c +@@ -227,6 +227,7 @@ struct iface_conf_list { + struct iface_info { + char name[IF_NAMESIZE+1]; /* name of the interface, e.g. "bge0" */ + struct sockaddr_storage addr; /* address information */ ++ struct sockaddr_storage netmask; /* netmask information */ + isc_uint64_t flags; /* interface flags, e.g. IFF_LOOPBACK */ + }; + +@@ -401,6 +402,7 @@ struct iface_conf_list { + struct iface_info { + char name[IFNAMSIZ]; /* name of the interface, e.g. "eth0" */ + struct sockaddr_storage addr; /* address information */ ++ struct sockaddr_storage netmask; /* netmask information */ + isc_uint64_t flags; /* interface flags, e.g. IFF_LOOPBACK */ + }; + +@@ -576,6 +578,17 @@ next_iface4(struct iface_info *info, int *err, struct iface_conf_list *ifaces) { + } + memcpy(&info->addr, &tmp.ifr_addr, sizeof(tmp.ifr_addr)); + ++ if (ioctl(ifaces->sock, SIOCGIFNETMASK, &tmp) < 0) { ++ if (errno == EADDRNOTAVAIL) { ++ continue; ++ } ++ log_error("Error getting netmask " ++ "for '%s'; %m", name); ++ *err = 1; ++ return 0; ++ } ++ memcpy(&info->netmask, &tmp.ifr_netmask, sizeof(tmp.ifr_netmask)); ++ + memset(&tmp, 0, sizeof(tmp)); + strncpy(tmp.ifr_name, name, sizeof(tmp.ifr_name) - 1); + if (ioctl(ifaces->sock, SIOCGIFFLAGS, &tmp) < 0) { +@@ -779,6 +792,7 @@ struct iface_conf_list { + struct iface_info { + char name[IFNAMSIZ]; /* name of the interface, e.g. "bge0" */ + struct sockaddr_storage addr; /* address information */ ++ struct sockaddr_storage netmask; /* netmask information */ + isc_uint64_t flags; /* interface flags, e.g. IFF_LOOPBACK */ + }; + +@@ -838,7 +852,8 @@ end_iface_scan(struct iface_conf_list *ifaces) { + /* XXX: perhaps create drealloc() rather than do it manually */ + void + add_ipv4_addr_to_interface(struct interface_info *iface, +- const struct in_addr *addr) { ++ const struct in_addr *addr, ++ const struct in_addr *netmask) { + /* + * We don't expect a lot of addresses per IPv4 interface, so + * we use 4, as our "chunk size" for collecting addresses. +@@ -849,6 +864,12 @@ add_ipv4_addr_to_interface(struct interface_info *iface, + log_fatal("Out of memory saving IPv4 address " + "on interface."); + } ++ ++ iface->netmasks = dmalloc(4 * sizeof(struct in_addr), MDL); ++ if (iface->netmasks == NULL) { ++ log_fatal("Out of memory saving IPv4 netmask " ++ "on interface."); ++ } + iface->address_count = 0; + iface->address_max = 4; + } else if (iface->address_count >= iface->address_max) { +@@ -861,14 +882,28 @@ add_ipv4_addr_to_interface(struct interface_info *iface, + log_fatal("Out of memory saving IPv4 address " + "on interface."); + } +- memcpy(tmp, +- iface->addresses, ++ memcpy(tmp, ++ iface->addresses, + iface->address_max * sizeof(struct in_addr)); + dfree(iface->addresses, MDL); + iface->addresses = tmp; ++ ++ tmp = dmalloc(new_max * sizeof(struct in_addr), MDL); ++ if (tmp == NULL) { ++ log_fatal("Out of memory saving IPv4 netmask " ++ "on interface."); ++ } ++ memcpy(tmp, ++ iface->netmasks, ++ iface->address_max * sizeof(struct in_addr)); ++ dfree(iface->netmasks, MDL); ++ iface->netmasks = tmp; ++ + iface->address_max = new_max; + } +- iface->addresses[iface->address_count++] = *addr; ++ iface->addresses[iface->address_count] = *addr; ++ iface->netmasks[iface->address_count] = *netmask; ++ iface->address_count++; + } + + #ifdef DHCPv6 +@@ -1003,6 +1038,7 @@ discover_interfaces(int state) { + if ((info.addr.ss_family == AF_INET) && + (local_family == AF_INET)) { + struct sockaddr_in *a = (struct sockaddr_in*)&info.addr; ++ struct sockaddr_in *n = (struct sockaddr_in*)&info.netmask; + struct iaddr addr; + + /* We don't want the loopback interface. */ +@@ -1016,7 +1052,7 @@ discover_interfaces(int state) { + if (a->sin_addr.s_addr != htonl(INADDR_ANY)) + tmp->configured = 1; + +- add_ipv4_addr_to_interface(tmp, &a->sin_addr); ++ add_ipv4_addr_to_interface(tmp, &a->sin_addr, &n->sin_addr); + + /* invoke the setup hook */ + addr.len = 4; +diff --git a/includes/dhcpd.h b/includes/dhcpd.h +index 1fd12db..8b509f1 100644 +--- a/includes/dhcpd.h ++++ b/includes/dhcpd.h +@@ -1323,6 +1323,9 @@ struct interface_info { + struct in_addr *addresses; /* Addresses associated with this + * interface. + */ ++ struct in_addr *netmasks; /* Netmask associated with this ++ * interface. ++ */ + int address_count; /* Number of addresses stored. */ + int address_max; /* Size of addresses buffer. */ + struct in6_addr *v6addresses; /* IPv6 addresses associated with diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c -index 292ba4f..c4c3234 100644 +index 292ba4f..339be87 100644 --- a/relay/dhcrelay.c +++ b/relay/dhcrelay.c @@ -30,6 +30,7 @@ @@ -39,47 +173,47 @@ index 292ba4f..c4c3234 100644 + socket, because the kernel will drop directed broadcast + packets if we send on the fallback. */ + for (out = interfaces; out; out = out->next) { -+ struct in_addr out_addr, out_netmask, out_bcast_addr; ++ int i = 0; + + // Only relay BOOTREQUEST on upstream interfaces + if (!(out->flags & INTERFACE_UPSTREAM)) + continue; + -+ // Calculate interface's broadcast using IP and netmask -+ if (ioctl(out->wfdesc, SIOCGIFNETMASK, out->ifp) != 0) { -+ log_info("Unable to get netmask for interface %s", out->name); ++ if (!out->addresses || !out->netmasks) + continue; -+ } + -+ out_addr = out->addresses[0]; -+ log_debug("Iface %s addr: %s", out->name, inet_ntoa(out_addr)); ++ for (i = 0; i < out->address_count; i++) { ++ struct in_addr bcast_addr; + -+ out_netmask = ((struct sockaddr_in *)&out->ifp->ifr_netmask)->sin_addr; -+ log_debug("Iface %s netmask: %s", out->name, inet_ntoa(out_netmask)); ++ log_debug("Iface %s addr: %s", out->name, inet_ntoa(out->addresses[i])); ++ log_debug("Iface %s netmask: %s", out->name, inet_ntoa(out->netmasks[i])); + -+ // Broadcast = ip_addr | ~netmask -+ out_bcast_addr.s_addr = out->addresses[0].s_addr | ~out_netmask.s_addr; -+ log_debug("Iface %s broadcast: %s", out->name, inet_ntoa(out_bcast_addr)); ++ // Broadcast = ip_addr | ~netmask ++ bcast_addr.s_addr = out->addresses[i].s_addr | ~out->netmasks[i].s_addr; ++ log_debug("Iface %s broadcast: %s", out->name, inet_ntoa(bcast_addr)); + -+ if (sp->to.sin_addr.s_addr == out_bcast_addr.s_addr) { -+ log_debug("Packet destined for broadcast IP of %s", out->name); -+ if (send_packet(out, NULL, packet, -+ length, ip->addresses[0],&sp->to, NULL) < 0) { -+ ++client_packet_errors; -+ } else { -+ log_debug("Forwarded BOOTREQUEST for %s to %s on interface %s", -+ print_hw_addr(packet->htype, packet->hlen, -+ packet->chaddr), -+ inet_ntoa(sp->to.sin_addr), out->name); ++ if (sp->to.sin_addr.s_addr == bcast_addr.s_addr) { ++ log_debug("Packet destined for broadcast IP of %s", out->name); ++ if (send_packet(out, NULL, packet, ++ length, ip->addresses[0],&sp->to, NULL) < 0) { ++ ++client_packet_errors; ++ } else { ++ log_debug("Forwarded BOOTREQUEST for %s to %s on interface %s", ++ print_hw_addr(packet->htype, packet->hlen, ++ packet->chaddr), ++ inet_ntoa(sp->to.sin_addr), out->name); + -+ ++client_packets_relayed; -+ } ++ ++client_packets_relayed; ++ } + -+ packet_relay_attempted = 1; ++ packet_relay_attempted = 1; + -+ break; ++ break; ++ } + } + ++ if (packet_relay_attempted) ++ break; + } + + if (packet_relay_attempted) From c5be8196a4bce3317538d98e834f5d0dc7bc5082 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Wed, 15 May 2019 23:55:11 +0000 Subject: [PATCH 8/8] Pass --enable-use-sockets to configure instead of uncommenting USE_SOCKETS directly --- ...ockets-to-configure-flags-in-debian-.patch | 28 +++++++++++++++++++ ...CKETS-to-force-dhcrelay-to-create-an.patch | 26 ----------------- ...VE_SO_BINDTODEVICE-has-a-chance-to-b.patch | 2 +- ...f-BOOTREQUEST-is-directed-broadcast-.patch | 2 +- src/isc-dhcp/patch/series | 2 +- 5 files changed, 31 insertions(+), 29 deletions(-) create mode 100644 src/isc-dhcp/patch/0007-Add-enable-use-sockets-to-configure-flags-in-debian-.patch delete mode 100644 src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch diff --git a/src/isc-dhcp/patch/0007-Add-enable-use-sockets-to-configure-flags-in-debian-.patch b/src/isc-dhcp/patch/0007-Add-enable-use-sockets-to-configure-flags-in-debian-.patch new file mode 100644 index 000000000000..a21b210a3b2e --- /dev/null +++ b/src/isc-dhcp/patch/0007-Add-enable-use-sockets-to-configure-flags-in-debian-.patch @@ -0,0 +1,28 @@ +From ab779f1d59f27f66e6e6bea89287c810e0a10a0f Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Wed, 15 May 2019 23:48:08 +0000 +Subject: [PATCH 1/3] Add --enable-use-sockets to configure flags in + debian/rules + +This defines USE_SOCKETS at compile time which forces dhcrelay +to create and bind separate sockets to each interface +--- + debian/rules | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/debian/rules b/debian/rules +index 4184716..46d6527 100755 +--- a/debian/rules ++++ b/debian/rules +@@ -23,7 +23,7 @@ CFLAGS+=-D_PATH_DHCLIENT_CONF='\"/etc/dhcp/dhclient.conf\"' + CFLAGS+=-D_PATH_DHCLIENT_DB='\"$(LEASE_PATH)/dhclient.leases\"' + CFLAGS+=-D_PATH_DHCLIENT6_DB='\"$(LEASE_PATH)/dhclient6.leases\"' + +-CONFFLAGS=--prefix=/usr --enable-log-pid --enable-paranoia ++CONFFLAGS=--prefix=/usr --enable-log-pid --enable-paranoia --enable-use-sockets + + # cross-architecture building + ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE)) +-- +2.17.1 + diff --git a/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch b/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch deleted file mode 100644 index a007d17ca8eb..000000000000 --- a/src/isc-dhcp/patch/0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 1499278795a552685f0d339e9e6f4c452790a16c Mon Sep 17 00:00:00 2001 -From: Joe LeVeque -Date: Sat, 4 May 2019 04:30:42 +0000 -Subject: [PATCH 1/3] Uncomment 'USE_SOCKETS' to force dhcrelay to create and - bind separate sockets to each interface - ---- - includes/site.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/includes/site.h b/includes/site.h -index f11fefb..fd129a1 100644 ---- a/includes/site.h -+++ b/includes/site.h -@@ -162,7 +162,7 @@ - the aforementioned problems do not matter to you, or if no other - API is supported for your system, you may want to go with it. */ - --/* #define USE_SOCKETS */ -+#define USE_SOCKETS - - /* Define this to use the Sun Streams NIT API. - --- -2.17.1 - diff --git a/src/isc-dhcp/patch/0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch b/src/isc-dhcp/patch/0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch index 19697e6cc4db..291d5b0ed69f 100644 --- a/src/isc-dhcp/patch/0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch +++ b/src/isc-dhcp/patch/0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch @@ -1,4 +1,4 @@ -From ddf74bdf94184b8009cc6ea28b36248ac4803ea9 Mon Sep 17 00:00:00 2001 +From c26520f36ebcd1f143312fc61440ed3d546c7504 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Wed, 8 May 2019 18:08:13 +0000 Subject: [PATCH 2/3] Bugfix: Ensure HAVE_SO_BINDTODEVICE has a chance to be diff --git a/src/isc-dhcp/patch/0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch b/src/isc-dhcp/patch/0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch index 680d6e35d596..4a572e933624 100644 --- a/src/isc-dhcp/patch/0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch +++ b/src/isc-dhcp/patch/0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch @@ -1,4 +1,4 @@ -From 386f97b7d2eaf9446e125834b70595f5ae67ea14 Mon Sep 17 00:00:00 2001 +From d8ed5f313d06829290e49d4d4b5413700affcf26 Mon Sep 17 00:00:00 2001 From: Joe LeVeque Date: Sun, 5 May 2019 22:52:49 +0000 Subject: [PATCH 3/3] If destination of BOOTREQUEST is directed broadcast, diff --git a/src/isc-dhcp/patch/series b/src/isc-dhcp/patch/series index b997b147e3a6..9c0edf9b683d 100644 --- a/src/isc-dhcp/patch/series +++ b/src/isc-dhcp/patch/series @@ -5,6 +5,6 @@ 0004-Bugfix-Don-t-print-log-messages-to-stderr-in-release.patch 0005-Port-upstream-changes-from-commit-f2e70402f0f2955f39.patch 0006-Port-upstream-changes-from-commit-edd6d8881bc4d8ec4b.patch -0007-Uncomment-USE_SOCKETS-to-force-dhcrelay-to-create-an.patch +0007-Add-enable-use-sockets-to-configure-flags-in-debian-.patch 0008-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch 0009-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch