DHCP relay: support for dual ToR (#6066)

* DHCP relay: support for dual ToR

* update to use -U option

* update

* update
This commit is contained in:
trzhang-msft 2020-12-02 14:43:20 -08:00 committed by GitHub
parent 2610ad8453
commit c59975c7da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 296 additions and 1 deletions

View File

@ -0,0 +1,269 @@
From 768df61b57a0a7bda23aa8bc7e08c5b2a96a8087 Mon Sep 17 00:00:00 2001
From: Tianrong Zhang <trzhang@microsoft.com>
Date: Tue, 1 Dec 2020 16:33:34 -0800
Subject: [PATCH] support for dual tor scenario
---
relay/dhcrelay.c | 117 +++++++++++++++++++++++++++++++++++++++--------
1 file changed, 98 insertions(+), 19 deletions(-)
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
index e158efe..055d97f 100644
--- a/relay/dhcrelay.c
+++ b/relay/dhcrelay.c
@@ -56,6 +56,8 @@ int bogus_agent_drops = 0; /* Packets dropped because agent option
specified. */
int bogus_giaddr_drops = 0; /* Packets sent to us to relay back to a
client, but with a bogus giaddr. */
+int bogus_yiaddr_drops = 0; /* Packets sent to us to relay back to a
+ client, but with a bogus yiaddr. */
int client_packets_relayed = 0; /* Packets relayed from client to server. */
int server_packet_errors = 0; /* Errors sending packets to servers. */
int server_packets_relayed = 0; /* Packets relayed from server to client. */
@@ -83,6 +85,13 @@ int max_hop_count = 10; /* Maximum hop count */
int no_daemon = 0;
int dfd[2] = { -1, -1 };
+int enable_support_for_dual_tor = 0;
+
+struct downstream_intf_list {
+ struct downstream_intf_list *next;
+ struct interface_info *interface;
+} *downstream_intfs = NULL;
+
#ifdef DHCPv6
/* Force use of DHCPv6 interface-id option. */
isc_boolean_t use_if_id = ISC_FALSE;
@@ -156,6 +165,8 @@ 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);
+static void free_downstream_intfs(void);
+
static const char copyright[] =
"Copyright 2004-2018 Internet Systems Consortium.";
static const char arr[] = "All rights reserved.";
@@ -189,6 +200,7 @@ char *progname;
" [-iu interface0 [ ... -iu interfaceN]\n" \
" [-id interface0 [ ... -id interfaceN]\n" \
" [-U interface]\n" \
+" [-dt]\n"\
" server0 [ ... serverN]\n\n" \
" %s -6 [-d] [-q] [-I] [-c <hops>]\n" \
" [-p <port> | -rp <relay-port>]\n" \
@@ -210,6 +222,7 @@ char *progname;
" [-iu interface0 [ ... -iu interfaceN]\n" \
" [-id interface0 [ ... -id interfaceN]\n" \
" [-U interface]\n" \
+" [-dt]\n"\
" server0 [ ... serverN]\n\n" \
" %s -6 [-d] [-q] [-I] [-c <hops>] [-p <port>]\n" \
" [-pf <pid-file>] [--no-pid]\n" \
@@ -231,6 +244,7 @@ char *progname;
" [-iu interface0 [ ... -iu interfaceN]\n" \
" [-id interface0 [ ... -id interfaceN]\n" \
" [-U interface]\n" \
+" [-dt]\n"\
" server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE \
" %s {--version|--help|-h}"
#else
@@ -242,6 +256,7 @@ char *progname;
" [-iu interface0 [ ... -iu interfaceN]\n" \
" [-id interface0 [ ... -id interfaceN]\n" \
" [-U interface]\n" \
+" [-dt]\n"\
" server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE \
" %s {--version|--help|-h}"
#endif
@@ -639,7 +654,16 @@ main(int argc, char **argv) {
usage(use_noarg, argv[i-1]);
if (load_interface_alias_map(argv[i]) != 0)
log_fatal("Failed to load interface name-alias map.");
- } else if (argv[i][0] == '-') {
+ } else if (!strcmp(argv[i], "-dt")) {
+#ifdef DHCPv6
+ if (local_family_set && (local_family == AF_INET6)) {
+ usage(use_v4command, argv[i]);
+ }
+ local_family_set = 1;
+ local_family = AF_INET;
+#endif
+ enable_support_for_dual_tor = 1;
+ } else if (argv[i][0] == '-') {
usage("Unknown command: %s", argv[i]);
} else {
struct hostent *he;
@@ -747,7 +771,6 @@ main(int argc, char **argv) {
log_fatal("No servers specified.");
}
-
/* Set up the server sockaddrs. */
for (sp = servers; sp; sp = sp->next) {
sp->to.sin_port = local_port;
@@ -862,6 +885,8 @@ main(int argc, char **argv) {
/* In fact dispatch() never returns. */
free_interface_alias_map();
+ free_downstream_intfs();
+
return (0);
}
@@ -885,25 +910,50 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet,
return;
}
- /* Find the interface that corresponds to the giaddr
- in the packet. */
- if (packet->giaddr.s_addr) {
- for (out = interfaces; out; out = out->next) {
- int i;
+ if (enable_support_for_dual_tor) {
+ if (packet->yiaddr.s_addr) {
+ out = NULL;
+
+ for (struct downstream_intf_list *cdi = downstream_intfs; cdi; cdi = cdi->next) {
+ int i = 0;
+ out = cdi->interface;
+
+ for (i = 0 ; i < out->address_count ; i++ ) {
+ if ((out->addresses[i].s_addr & out->netmasks[i].s_addr) == (packet->yiaddr.s_addr & out->netmasks[i].s_addr)) {
+ i = -1;
+ break;
+ }
+ }
- for (i = 0 ; i < out->address_count ; i++ ) {
- if (out->addresses[i].s_addr ==
- packet->giaddr.s_addr) {
- i = -1;
+ if (i == -1) {
break;
+ } else {
+ out = NULL;
}
}
-
- if (i == -1)
- break;
+ } else {
+ out = NULL;
}
} else {
- out = NULL;
+ /* Find the interface that corresponds to the giaddr in the packet. */
+ if (packet->giaddr.s_addr) {
+ for (out = interfaces; out; out = out->next) {
+ int i;
+
+ for (i = 0 ; i < out->address_count ; i++ ) {
+ if (out->addresses[i].s_addr ==
+ packet->giaddr.s_addr) {
+ i = -1;
+ break;
+ }
+ }
+
+ if (i == -1)
+ break;
+ }
+ } else {
+ out = NULL;
+ }
}
/* If it's a bootreply, forward it to the client. */
@@ -913,6 +963,10 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet,
return;
}
+ /* This bootreply does not belong to the current vlan. */
+ if (enable_support_for_dual_tor && !out)
+ return;
+
if (!(packet->flags & htons(BOOTP_BROADCAST)) &&
can_unicast_without_arp(out)) {
to.sin_addr = packet->yiaddr;
@@ -945,9 +999,13 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet,
return;
if (!out) {
- log_error("Packet to bogus giaddr %s.\n",
- inet_ntoa(packet->giaddr));
- ++bogus_giaddr_drops;
+ if (!enable_support_for_dual_tor) {
+ log_error("Packet to bogus giaddr %s.\n", inet_ntoa(packet->giaddr));
+ ++bogus_giaddr_drops;
+ } else {
+ log_error("Packet to bogus yiaddr %s.\n", inet_ntoa(packet->yiaddr));
+ ++bogus_yiaddr_drops;
+ }
return;
}
@@ -989,6 +1047,7 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet,
that set giaddr, so we won't see it. */
if (!packet->giaddr.s_addr)
packet->giaddr = ip->addresses[0];
+
if (packet->hops < max_hop_count)
packet->hops = packet->hops + 1;
else
@@ -1264,7 +1323,6 @@ find_interface_by_agent_option(struct dhcp_packet *packet,
/* Scan the interface list looking for an interface whose
name matches the one specified in circuit_id. */
-
for (ip = interfaces; ip; ip = ip->next) {
if (ip->circuit_id &&
ip->circuit_id_len == circuit_id_len &&
@@ -1668,6 +1726,7 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet,
*sp++ = 4u;
memcpy(sp, &giaddr.s_addr, 4);
sp += 4;
+
packet->giaddr = uplink->addresses[0];
log_debug ("Adding link selection suboption"
" with addr: %s", inet_ntoa(giaddr));
@@ -2398,6 +2457,7 @@ void request_v4_interface(const char* name, int flags) {
struct interface_info *tmp = NULL;
int len = strlen(name);
isc_result_t status;
+ struct downstream_intf_list *ci = NULL;
if (len >= sizeof(tmp->name)) {
log_fatal("%s: interface name too long (is %d)", name, len);
@@ -2413,6 +2473,15 @@ void request_v4_interface(const char* name, int flags) {
(flags & INTERFACE_UPSTREAM ? 'Y' : 'N'),
(flags & INTERFACE_DOWNSTREAM ? 'Y' : 'N'));
+ if (flags & INTERFACE_DOWNSTREAM) {
+ ci = ((struct downstream_intf_list *)dmalloc(sizeof *ci, MDL));
+ if (!ci)
+ log_fatal("no memory for downstream interface pointer.\n");
+ ci->next = downstream_intfs;
+ downstream_intfs = ci;
+ ci->interface = tmp;
+ }
+
strncpy(tmp->name, name, len);
interface_snorf(tmp, (INTERFACE_REQUESTED | flags));
interface_dereference(&tmp, MDL);
@@ -2487,3 +2556,13 @@ free_interface_alias_map(void) {
free(g_interface_name_alias_map);
g_interface_name_alias_map_size = 0;
}
+
+static void
+free_downstream_intfs(void) {
+ struct downstream_intf_list *cdi;
+ while (downstream_intfs) {
+ cdi = downstream_intfs;
+ downstream_intfs = downstream_intfs->next;
+ free(cdi);
+ }
+}
--
2.17.1

View File

@ -0,0 +1,24 @@
From b19547b0574132e4b2efbda012f3169e4db7923c Mon Sep 17 00:00:00 2001
From: Tianrong Zhang <trzhang@microsoft.com>
Date: Mon, 30 Nov 2020 18:42:09 -0800
Subject: [PATCH] Bugfix: correctly set interface netmask
---
common/discover.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/common/discover.c b/common/discover.c
index c6b2431..06e0b12 100644
--- a/common/discover.c
+++ b/common/discover.c
@@ -479,6 +479,7 @@ next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
sa_len = ifaces->next->ifa_addr->sa_len;
#endif
memcpy(&info->addr, ifaces->next->ifa_addr, sa_len);
+ memcpy(&info->netmask, ifaces->next->ifa_netmask, sa_len);
}
info->flags = ifaces->next->ifa_flags;
ifaces->next = ifaces->next->ifa_next;
--
2.17.1

View File

@ -1,4 +1,4 @@
# This series applies on GIT commit d613b77d0473054fb0071b00d01eaa1623e50a07
# This series applies on GIT commit d0d58776805d720029619ea06df5c57706eecd5a
0001-Bugfix-Don-t-print-log-messages-to-stderr-in-release.patch
0002-Customizable-Option-82-circuit-ID-and-remote-ID-fiel.patch
0003-Support-for-obtaining-name-of-physical-interface-tha.patch
@ -7,3 +7,5 @@
0006-Bugfix-Ensure-HAVE_SO_BINDTODEVICE-has-a-chance-to-b.patch
0007-If-destination-of-BOOTREQUEST-is-directed-broadcast-.patch
0008-Don-t-skip-down-interfaces-when-discovering-interfac.patch
0009-Support-for-dual-tor-scenario.patch
0010-Bugfix-correctly-set-interface-netmask.patch