[DHCP relay]: Fix bug which could cause incorrect interface name association (#1233)
* [DHCP relay]: Fix bug which could cause incorrect interface name association * Add patches to series file and apply using stgit * Update .gitignore in order to ignore downloaded and generated files * Reorganize src/ subdirectories alphabetically in .gitignore
This commit is contained in:
parent
79f790409f
commit
2571cb59b6
23
.gitignore
vendored
23
.gitignore
vendored
@ -12,28 +12,31 @@ target/
|
|||||||
# Subdirectories in src
|
# Subdirectories in src
|
||||||
src/hiredis/*
|
src/hiredis/*
|
||||||
!src/hiredis/Makefile
|
!src/hiredis/Makefile
|
||||||
|
src/igb/*
|
||||||
|
!src/igb/Makefile
|
||||||
src/initramfs-tools/*
|
src/initramfs-tools/*
|
||||||
!src/initramfs-tools/Makefile
|
!src/initramfs-tools/Makefile
|
||||||
src/redis/*
|
src/isc-dhcp/*
|
||||||
!src/redis/Makefile
|
!src/isc-dhcp/Makefile
|
||||||
|
!src/isc-dhcp/patch/
|
||||||
src/libnl3/*
|
src/libnl3/*
|
||||||
!src/libnl3/Makefile
|
!src/libnl3/Makefile
|
||||||
src/libteam/*
|
src/libteam/*
|
||||||
!src/libteam/Makefile
|
!src/libteam/Makefile
|
||||||
src/snmpd/*
|
|
||||||
!src/snmpd/Makefile
|
|
||||||
src/thrift/*
|
|
||||||
!src/thrift/Makefile
|
|
||||||
src/sonic-device-data/src/device/
|
|
||||||
src/sonic-device-data/src/debian/
|
|
||||||
src/igb/*
|
|
||||||
!src/igb/Makefile
|
|
||||||
src/mpdecimal/*
|
src/mpdecimal/*
|
||||||
!src/mpdecimal/Makefile
|
!src/mpdecimal/Makefile
|
||||||
src/python3/*
|
src/python3/*
|
||||||
!src/python3/Makefile
|
!src/python3/Makefile
|
||||||
|
src/redis/*
|
||||||
|
!src/redis/Makefile
|
||||||
|
src/snmpd/*
|
||||||
|
!src/snmpd/Makefile
|
||||||
|
src/sonic-device-data/src/device/
|
||||||
|
src/sonic-device-data/src/debian/
|
||||||
src/supervisor/*
|
src/supervisor/*
|
||||||
!src/supervisor/Makefile
|
!src/supervisor/Makefile
|
||||||
|
src/thrift/*
|
||||||
|
!src/thrift/Makefile
|
||||||
|
|
||||||
# Autogenerated Dockerfiles
|
# Autogenerated Dockerfiles
|
||||||
dockers/docker-base/Dockerfile
|
dockers/docker-base/Dockerfile
|
||||||
|
@ -12,14 +12,17 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% :
|
|||||||
# Clone isc-dhcp repo
|
# Clone isc-dhcp repo
|
||||||
git clone https://anonscm.debian.org/cgit/pkg-dhcp/isc-dhcp.git
|
git clone https://anonscm.debian.org/cgit/pkg-dhcp/isc-dhcp.git
|
||||||
pushd ./isc-dhcp
|
pushd ./isc-dhcp
|
||||||
git checkout -f debian/$(ISC_DHCP_VERSION)
|
|
||||||
popd
|
|
||||||
|
|
||||||
# Apply patch
|
# Reset HEAD to the commit of the proper tag
|
||||||
patch -p1 < isc-dhcp-$(ISC_DHCP_VERSION)_dhcrelay-custom-circuit_id-remote_id-and-bridge-iface-support.patch
|
# NOTE: Using "git checkout <tag_name>" here detaches our HEAD,
|
||||||
|
# which stg doesn't like, so we use this method instead
|
||||||
|
git reset --hard debian/$(ISC_DHCP_VERSION)
|
||||||
|
|
||||||
|
# Apply patches
|
||||||
|
stg init
|
||||||
|
stg import -s ../patch/series
|
||||||
|
|
||||||
# Build source and Debian packages
|
# Build source and Debian packages
|
||||||
pushd ./isc-dhcp
|
|
||||||
dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS)
|
dpkg-buildpackage -rfakeroot -b -us -uc -j$(SONIC_CONFIG_MAKE_JOBS)
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
@ -1,442 +0,0 @@
|
|||||||
This patch adds the following functionality to dhcrelay in isc-dhcp v4.3.3-6:
|
|
||||||
* Add customizable Circuit ID and Remote ID fields
|
|
||||||
* Support for obtaining name of physical interfaces that are part of a bridge interface
|
|
||||||
|
|
||||||
diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c
|
|
||||||
--- a/isc-dhcp/relay/dhcrelay.c 2017-11-17 00:36:51.575121900 +0000
|
|
||||||
+++ b/isc-dhcp/relay/dhcrelay.c 2017-11-17 00:52:51.024607833 +0000
|
|
||||||
@@ -73,6 +73,8 @@
|
|
||||||
did not match any known circuit ID. */
|
|
||||||
int missing_circuit_id = 0; /* Circuit ID option in matching RAI option
|
|
||||||
was missing. */
|
|
||||||
+const char *agent_circuit_id_fmt = NULL; /* Circuit ID custom format string. */
|
|
||||||
+const char *agent_remote_id_fmt = NULL; /* Remote ID custom format string. */
|
|
||||||
int max_hop_count = 10; /* Maximum hop count */
|
|
||||||
|
|
||||||
#ifdef DHCPv6
|
|
||||||
@@ -120,6 +122,14 @@
|
|
||||||
char *dhcrelay_sub_id = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+struct interface_name_alias_tuple {
|
|
||||||
+ char if_name[IFNAMSIZ + 1];
|
|
||||||
+ char if_alias[IFNAMSIZ + 1];
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static struct interface_name_alias_tuple *g_interface_name_alias_map = NULL;
|
|
||||||
+static size_t g_interface_name_alias_map_size = 0;
|
|
||||||
+
|
|
||||||
static void do_relay4(struct interface_info *, struct dhcp_packet *,
|
|
||||||
unsigned int, unsigned int, struct iaddr,
|
|
||||||
struct hardware *);
|
|
||||||
@@ -132,6 +142,10 @@
|
|
||||||
struct interface_info **,
|
|
||||||
struct dhcp_packet *, unsigned);
|
|
||||||
|
|
||||||
+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 const char copyright[] =
|
|
||||||
"Copyright 2004-2015 Internet Systems Consortium.";
|
|
||||||
static const char arr[] = "All rights reserved.";
|
|
||||||
@@ -140,28 +154,41 @@
|
|
||||||
static const char url[] =
|
|
||||||
"For info, please visit https://www.isc.org/software/dhcp/";
|
|
||||||
|
|
||||||
+#define DHCRELAY_OPTION82_USAGE \
|
|
||||||
+"circuit_id/remote_id interpreted sequences are:\n" \
|
|
||||||
+"\n" \
|
|
||||||
+" %%%% A single %%\n" \
|
|
||||||
+" %%h Hostname of device\n" \
|
|
||||||
+" %%p Alias of interface that generated the request\n" \
|
|
||||||
+" %%P Hardware address of interface that generated the request\n" \
|
|
||||||
+" %%C Client hardware address\n" \
|
|
||||||
+" %%I DHCP relay agent IP Address\n" \
|
|
||||||
+
|
|
||||||
#ifdef DHCPv6
|
|
||||||
#define DHCRELAY_USAGE \
|
|
||||||
-"Usage: dhcrelay [-4] [-d] [-q] [-a] [-D]\n"\
|
|
||||||
+"Usage: dhcrelay [-4] [-d] [-q] [-a <circuit_id> <remote_id>] [-D]\n"\
|
|
||||||
" [-A <length>] [-c <hops>] [-p <port>]\n" \
|
|
||||||
" [-pf <pid-file>] [--no-pid]\n"\
|
|
||||||
" [-m append|replace|forward|discard]\n" \
|
|
||||||
+" [--name-alias-map-file <name-alias-map-file>]\n" \
|
|
||||||
" [-i interface0 [ ... -i interfaceN]\n" \
|
|
||||||
" server0 [ ... serverN]\n\n" \
|
|
||||||
" dhcrelay -6 [-d] [-q] [-I] [-c <hops>] [-p <port>]\n" \
|
|
||||||
" [-pf <pid-file>] [--no-pid]\n" \
|
|
||||||
+" [--name-alias-map-file <name-alias-map-file>]\n" \
|
|
||||||
" [-s <subscriber-id>]\n" \
|
|
||||||
" -l lower0 [ ... -l lowerN]\n" \
|
|
||||||
" -u upper0 [ ... -u upperN]\n" \
|
|
||||||
" lower (client link): [address%%]interface[#index]\n" \
|
|
||||||
-" upper (server link): [address%%]interface"
|
|
||||||
+" upper (server link): [address%%]interface\n\n" DHCRELAY_OPTION82_USAGE
|
|
||||||
#else
|
|
||||||
#define DHCRELAY_USAGE \
|
|
||||||
-"Usage: dhcrelay [-d] [-q] [-a] [-D] [-A <length>] [-c <hops>] [-p <port>]\n" \
|
|
||||||
-" [-pf <pid-file>] [--no-pid]\n" \
|
|
||||||
+"Usage: dhcrelay [-d] [-q] [-a <circuit_id> <remote_id>] [-D]\n" \
|
|
||||||
+" [-A <length>] [-c <hops>] [-p <port>]\n" \
|
|
||||||
+" [-pf <pid-file>] [--no-pid]\n"\
|
|
||||||
" [-m append|replace|forward|discard]\n" \
|
|
||||||
" [-i interface0 [ ... -i interfaceN]\n" \
|
|
||||||
-" server0 [ ... serverN]\n\n"
|
|
||||||
+" server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void usage() {
|
|
||||||
@@ -287,6 +314,15 @@
|
|
||||||
local_family_set = 1;
|
|
||||||
local_family = AF_INET;
|
|
||||||
#endif
|
|
||||||
+ if (++i == argc)
|
|
||||||
+ usage();
|
|
||||||
+
|
|
||||||
+ if (argv[i] != NULL && argv[i][0] != '-')
|
|
||||||
+ agent_circuit_id_fmt = argv[i++];
|
|
||||||
+
|
|
||||||
+ if (argv[i] != NULL && argv[i][0] != '-')
|
|
||||||
+ agent_remote_id_fmt = argv[i];
|
|
||||||
+
|
|
||||||
add_agent_options = 1;
|
|
||||||
} else if (!strcmp(argv[i], "-A")) {
|
|
||||||
#ifdef DHCPv6
|
|
||||||
@@ -383,6 +419,13 @@
|
|
||||||
no_dhcrelay_pid = ISC_TRUE;
|
|
||||||
} else if (!strcmp(argv[i], "--no-pid")) {
|
|
||||||
no_pid_file = ISC_TRUE;
|
|
||||||
+ } else if (!strcmp(argv[i], "--name-alias-map-file")) {
|
|
||||||
+ if (++i == argc)
|
|
||||||
+ usage();
|
|
||||||
+ if (load_interface_alias_map(argv[i]) != 0)
|
|
||||||
+ log_fatal("Failed to load interface name-alias map.");
|
|
||||||
+ path_dhcrelay_pid = argv[i];
|
|
||||||
+ no_dhcrelay_pid = ISC_TRUE;
|
|
||||||
} else if (!strcmp(argv[i], "--version")) {
|
|
||||||
log_info("isc-dhcrelay-%s", PACKAGE_VERSION);
|
|
||||||
exit(0);
|
|
||||||
@@ -602,6 +645,8 @@
|
|
||||||
dispatch();
|
|
||||||
|
|
||||||
/* In fact dispatch() never returns. */
|
|
||||||
+ free_interface_alias_map();
|
|
||||||
+
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -690,10 +735,10 @@
|
|
||||||
&to, htop) < 0) {
|
|
||||||
++server_packet_errors;
|
|
||||||
} else {
|
|
||||||
- log_debug("Forwarded BOOTREPLY for %s to %s",
|
|
||||||
- print_hw_addr(packet->htype, packet->hlen,
|
|
||||||
- packet->chaddr),
|
|
||||||
- inet_ntoa(to.sin_addr));
|
|
||||||
+ //log_debug("Forwarded BOOTREPLY for %s to %s",
|
|
||||||
+ // print_hw_addr(packet->htype, packet->hlen,
|
|
||||||
+ // packet->chaddr),
|
|
||||||
+ // inet_ntoa(to.sin_addr));
|
|
||||||
|
|
||||||
++server_packets_relayed;
|
|
||||||
}
|
|
||||||
@@ -732,10 +777,11 @@
|
|
||||||
&sp->to, NULL) < 0) {
|
|
||||||
++client_packet_errors;
|
|
||||||
} else {
|
|
||||||
- log_debug("Forwarded BOOTREQUEST for %s to %s",
|
|
||||||
- print_hw_addr(packet->htype, packet->hlen,
|
|
||||||
- packet->chaddr),
|
|
||||||
- inet_ntoa(sp->to.sin_addr));
|
|
||||||
+ //log_debug("Forwarded BOOTREQUEST for %s to %s",
|
|
||||||
+ // print_hw_addr(packet->htype, packet->hlen,
|
|
||||||
+ // packet->chaddr),
|
|
||||||
+ // inet_ntoa(sp->to.sin_addr));
|
|
||||||
+
|
|
||||||
++client_packets_relayed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -937,6 +983,151 @@
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int
|
|
||||||
+_bridgefdbquery(const char *hwAddr, char *interface, int *vlanid) {
|
|
||||||
+
|
|
||||||
+#define xstr(s) str(s)
|
|
||||||
+#define str(s) #s
|
|
||||||
+#define FDB_STRING_LEN 100
|
|
||||||
+#define FDB_BUFFER_LEN (FDB_STRING_LEN + 1)
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Format for sscanf() to read the 1st, 3th, and 5th
|
|
||||||
+ * space-delimited fields
|
|
||||||
+ *
|
|
||||||
+ * bridge fdb show output
|
|
||||||
+ * 6c:64:1a:00:06:13 dev swp35 vlan 0 master bridge permanent
|
|
||||||
+ */
|
|
||||||
+#define FDB_LINE_FORMAT "%" xstr(FDB_STRING_LEN) "s %*s " \
|
|
||||||
+ "%" xstr(FDB_STRING_LEN) "s %*s %d %*s"
|
|
||||||
+
|
|
||||||
+ char cmdstr[FDB_BUFFER_LEN];
|
|
||||||
+ char buf[FDB_BUFFER_LEN];
|
|
||||||
+ char macAddr[FDB_BUFFER_LEN];
|
|
||||||
+
|
|
||||||
+ if ((interface == NULL) || (vlanid == NULL)) {
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+ sprintf(cmdstr, "bridge fdb show | grep -m 1 %s", hwAddr);
|
|
||||||
+ FILE *cmd = popen(cmdstr, "r");
|
|
||||||
+
|
|
||||||
+ if (cmd != NULL) {
|
|
||||||
+ while (fgets(buf, sizeof(buf), cmd)) {
|
|
||||||
+ sscanf(buf, FDB_LINE_FORMAT, macAddr, interface, vlanid);
|
|
||||||
+ //log_debug("bridgefdbquery: macAddr:%s interface: %s vlanid %d",
|
|
||||||
+ // macAddr, interface, *vlanid);
|
|
||||||
+ }
|
|
||||||
+ pclose(cmd);
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return -1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+ * Format the message that will be used by circuit_id and remote_id
|
|
||||||
+ */
|
|
||||||
+static int
|
|
||||||
+format_relay_agent_rfc3046_msg(struct interface_info *ip, struct dhcp_packet *packet,
|
|
||||||
+ const char *format, char *msg, size_t msgn) {
|
|
||||||
+ size_t len = 0;
|
|
||||||
+ char hostname[HOST_NAME_MAX + 1] = { 0 };
|
|
||||||
+ char ifname[IFNAMSIZ + 1] = { 0 };
|
|
||||||
+ char *buf = msg;
|
|
||||||
+
|
|
||||||
+ for ( ; format && *format && len < msgn; ++format) {
|
|
||||||
+ size_t strn = 0;
|
|
||||||
+ const char *str = NULL;
|
|
||||||
+
|
|
||||||
+ if (*format == '%') {
|
|
||||||
+ switch (*++format) {
|
|
||||||
+ case '\0':
|
|
||||||
+ --format;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case '%': /* A literal '%' */
|
|
||||||
+ str = "%";
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 'h': /* Hostname */
|
|
||||||
+ gethostname(hostname, HOST_NAME_MAX);
|
|
||||||
+ str = hostname;
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 'p': /* Name of interface that we received the request from */
|
|
||||||
+ /*
|
|
||||||
+ * Query FDB to identify the exact physical interface only when source MAC address
|
|
||||||
+ * is present and '20: DHCP relay agent IP address' (giaddr) is not present
|
|
||||||
+ */
|
|
||||||
+ if (packet->htype && !packet->giaddr.s_addr) {
|
|
||||||
+ int ret = 0, vlanid = 0;
|
|
||||||
+
|
|
||||||
+ ret = _bridgefdbquery(print_hw_addr(packet->htype, packet->hlen, packet->chaddr),
|
|
||||||
+ ip->name,
|
|
||||||
+ &vlanid);
|
|
||||||
+
|
|
||||||
+ if (ret < 0) {
|
|
||||||
+ //log_debug("MAC Address: %s (interface:%s vlan:%d) not found in bridge fdb show",
|
|
||||||
+ // print_hw_addr (packet->htype, packet->hlen, packet->chaddr),
|
|
||||||
+ // ip->name,
|
|
||||||
+ // vlanid);
|
|
||||||
+
|
|
||||||
+ strncpy(ifname, ip->name, IFNAMSIZ);
|
|
||||||
+ }
|
|
||||||
+ else if (strlen(ip->name) > 0) {
|
|
||||||
+ // Translate SONiC interface name to vendor alias
|
|
||||||
+ if (get_interface_alias_by_name(ip->name, ifname) < 0) {
|
|
||||||
+ log_error("Failed to retrieve alias for interface name '%s'. Defaulting to interface name.", ip->name);
|
|
||||||
+ strncpy(ifname, ip->name, IFNAMSIZ);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ //log_debug("Mapped interface name '%s' to alias '%s'", ip->name, ifname);
|
|
||||||
+
|
|
||||||
+ //log_debug("Adding option 82 interface alias for MAC Address %s as '%s'",
|
|
||||||
+ // print_hw_addr (packet->htype, packet->hlen, packet->chaddr),
|
|
||||||
+ // ifname);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ str = ifname;
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 'P': /* Physical address of interface that we received the request from */
|
|
||||||
+ str = print_hw_addr(ip->hw_address.hbuf[0], ip->hw_address.hlen - 1, &ip->hw_address.hbuf[1]);
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 'C': /* 24: Client hardware address */
|
|
||||||
+ str = print_hw_addr(packet->htype, packet->hlen, packet->chaddr);
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ case 'I': /* 20: DHCP relay agent IP address */
|
|
||||||
+ str = inet_ntoa(packet->giaddr);
|
|
||||||
+ break;
|
|
||||||
+
|
|
||||||
+ default:
|
|
||||||
+ log_error("Option %%%c is unrecognized and will not be formatted!", *format);
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (str)
|
|
||||||
+ strn = strlen(str);
|
|
||||||
+ } else {
|
|
||||||
+ str = format;
|
|
||||||
+ strn += 1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // Do we have room?
|
|
||||||
+ if ((strn+len) > msgn) {
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ memcpy(buf+len, str, strn);
|
|
||||||
+ len += strn;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return len;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Examine a packet to see if it's a candidate to have a Relay
|
|
||||||
* Agent Information option tacked onto its tail. If it is, tack
|
|
||||||
@@ -948,6 +1139,8 @@
|
|
||||||
int is_dhcp = 0, mms;
|
|
||||||
unsigned optlen;
|
|
||||||
u_int8_t *op, *nextop, *sp, *max, *end_pad = NULL;
|
|
||||||
+ char circuit_id_buf[255] = { '\0', };
|
|
||||||
+ char remote_id_buf[255] = { '\0', };
|
|
||||||
|
|
||||||
/* If we're not adding agent options to packets, we can skip
|
|
||||||
this. */
|
|
||||||
@@ -1077,6 +1270,38 @@
|
|
||||||
op = sp;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+ /* option82: custom string for circuit_id */
|
|
||||||
+ if (agent_circuit_id_fmt) {
|
|
||||||
+ size_t len = 0;
|
|
||||||
+
|
|
||||||
+ len = format_relay_agent_rfc3046_msg(ip, packet, agent_circuit_id_fmt,
|
|
||||||
+ circuit_id_buf, sizeof(circuit_id_buf));
|
|
||||||
+
|
|
||||||
+ if (len > 0) {
|
|
||||||
+ ip->circuit_id = (uint8_t *)circuit_id_buf;
|
|
||||||
+ ip->circuit_id_len = len;
|
|
||||||
+
|
|
||||||
+ //log_debug("Sending on %s option82:circuit_id='%s' (%d)",
|
|
||||||
+ // ip->name, (char *)ip->circuit_id, ip->circuit_id_len);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* option82: custom string for remote_id */
|
|
||||||
+ if (agent_remote_id_fmt) {
|
|
||||||
+ size_t len = 0;
|
|
||||||
+
|
|
||||||
+ len = format_relay_agent_rfc3046_msg(ip, packet, agent_remote_id_fmt,
|
|
||||||
+ remote_id_buf, sizeof(remote_id_buf));
|
|
||||||
+
|
|
||||||
+ if (len > 0) {
|
|
||||||
+ ip->remote_id = (uint8_t *)remote_id_buf;
|
|
||||||
+ ip->remote_id_len = len;
|
|
||||||
+
|
|
||||||
+ //log_debug("Sending on %s option82:remote_id='%s' (%d)",
|
|
||||||
+ // ip->name, (char *)ip->remote_id, ip->remote_id_len);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* Sanity check. Had better not ever happen. */
|
|
||||||
if ((ip->circuit_id_len > 255) ||(ip->circuit_id_len < 1))
|
|
||||||
log_fatal("Circuit ID length %d out of range [1-255] on "
|
|
||||||
@@ -1102,7 +1327,7 @@
|
|
||||||
* If not, forward without adding the option.
|
|
||||||
*/
|
|
||||||
if (max - sp >= optlen + 3) {
|
|
||||||
- log_debug("Adding %d-byte relay agent option", optlen + 3);
|
|
||||||
+ //log_debug("Adding %d-byte relay agent option", optlen + 3);
|
|
||||||
|
|
||||||
/* Okay, cons up *our* Relay Agent Information option. */
|
|
||||||
*sp++ = DHO_DHCP_AGENT_OPTIONS;
|
|
||||||
@@ -1735,3 +1960,73 @@
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+#define MAX_PORT_CONFIG_LINE_LEN 1024
|
|
||||||
+
|
|
||||||
+// Allocates and loads global map g_interface_name_alias_map
|
|
||||||
+// Also sets global g_interface_name_alias_map_size
|
|
||||||
+static int
|
|
||||||
+load_interface_alias_map(const char *port_alias_map_file_path) {
|
|
||||||
+ int i = 0;
|
|
||||||
+ FILE *fp = NULL;
|
|
||||||
+ char line[MAX_PORT_CONFIG_LINE_LEN] = { 0 };
|
|
||||||
+
|
|
||||||
+ fp = fopen(port_alias_map_file_path,"r");
|
|
||||||
+ if (fp == NULL) {
|
|
||||||
+ log_error("Unable to open %s", port_alias_map_file_path);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ g_interface_name_alias_map_size = 0;
|
|
||||||
+
|
|
||||||
+ // Count the number of interfaces listed in the file
|
|
||||||
+ while (fgets(line, sizeof(line), fp)) {
|
|
||||||
+ g_interface_name_alias_map_size++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ // Allocate our map accordingly
|
|
||||||
+ g_interface_name_alias_map = ((struct interface_name_alias_tuple *)
|
|
||||||
+ dmalloc((sizeof(struct interface_name_alias_tuple) * g_interface_name_alias_map_size),
|
|
||||||
+ MDL));
|
|
||||||
+
|
|
||||||
+ // Reset file position indicator to beginning of file
|
|
||||||
+ fseek(fp, 0, SEEK_SET);
|
|
||||||
+
|
|
||||||
+ // Every line should contain exactly one name-alias pair
|
|
||||||
+ while (fgets(line, sizeof(line), fp)) {
|
|
||||||
+ // Each line should read as "<name><whitespace><alias>"
|
|
||||||
+ sscanf(line, "%s %s", g_interface_name_alias_map[i].if_name, g_interface_name_alias_map[i].if_alias);
|
|
||||||
+ i++;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ fclose(fp);
|
|
||||||
+
|
|
||||||
+ log_info("Loaded %d interface name-alias mappings", i);
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// Locates alias for port named if_name, copies alias into if_alias_out, up to a
|
|
||||||
+// max of IFNAMSIZ bytes.
|
|
||||||
+// Returns 0 on success, -1 on failure
|
|
||||||
+static int
|
|
||||||
+get_interface_alias_by_name(const char *if_name, char *if_alias_out) {
|
|
||||||
+ int i = 0;
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < g_interface_name_alias_map_size; i++) {
|
|
||||||
+ if (strncmp(if_name, g_interface_name_alias_map[i].if_name, IFNAMSIZ) == 0) {
|
|
||||||
+ strncpy(if_alias_out, g_interface_name_alias_map[i].if_alias, IFNAMSIZ);
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return -1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+// Frees global map g_interface_name_alias_map
|
|
||||||
+// Sets g_interface_name_alias_map_size to 0
|
|
||||||
+static void
|
|
||||||
+free_interface_alias_map(void) {
|
|
||||||
+ free(g_interface_name_alias_map);
|
|
||||||
+ g_interface_name_alias_map_size = 0;
|
|
||||||
+}
|
|
@ -0,0 +1,266 @@
|
|||||||
|
From 42319f1b56ba6362c874cd64383a055ba6498bee Mon Sep 17 00:00:00 2001
|
||||||
|
From: Joe LeVeque <jolevequ@microsoft.com>
|
||||||
|
Date: Mon, 11 Dec 2017 23:21:08 +0000
|
||||||
|
Subject: [PATCH 1/3] Customizable Option 82 circuit ID and remote ID fields
|
||||||
|
|
||||||
|
---
|
||||||
|
relay/dhcrelay.c | 172 +++++++++++++++++++++++++++++++++++++++++++++++--------
|
||||||
|
1 file changed, 147 insertions(+), 25 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
|
||||||
|
index 15b4997..a26efca 100644
|
||||||
|
--- a/relay/dhcrelay.c
|
||||||
|
+++ b/relay/dhcrelay.c
|
||||||
|
@@ -73,6 +73,8 @@ int bad_circuit_id = 0; /* Circuit ID option in matching RAI option
|
||||||
|
did not match any known circuit ID. */
|
||||||
|
int missing_circuit_id = 0; /* Circuit ID option in matching RAI option
|
||||||
|
was missing. */
|
||||||
|
+const char *agent_circuit_id_fmt = NULL; /* Circuit ID custom format string. */
|
||||||
|
+const char *agent_remote_id_fmt = NULL; /* Remote ID custom format string. */
|
||||||
|
int max_hop_count = 10; /* Maximum hop count */
|
||||||
|
|
||||||
|
#ifdef DHCPv6
|
||||||
|
@@ -140,9 +142,19 @@ static const char message[] =
|
||||||
|
static const char url[] =
|
||||||
|
"For info, please visit https://www.isc.org/software/dhcp/";
|
||||||
|
|
||||||
|
+#define DHCRELAY_OPTION82_USAGE \
|
||||||
|
+"circuit_id/remote_id interpreted sequences are:\n" \
|
||||||
|
+"\n" \
|
||||||
|
+" %%%% A single %%\n" \
|
||||||
|
+" %%h Hostname of device\n" \
|
||||||
|
+" %%p Name of interface that generated the request\n" \
|
||||||
|
+" %%P Hardware address of interface that generated the request\n" \
|
||||||
|
+" %%C Client hardware address\n" \
|
||||||
|
+" %%I DHCP relay agent IP Address\n" \
|
||||||
|
+
|
||||||
|
#ifdef DHCPv6
|
||||||
|
#define DHCRELAY_USAGE \
|
||||||
|
-"Usage: dhcrelay [-4] [-d] [-q] [-a] [-D]\n"\
|
||||||
|
+"Usage: dhcrelay [-4] [-d] [-q] [-a <circuit_id> <remote_id>] [-D]\n"\
|
||||||
|
" [-A <length>] [-c <hops>] [-p <port>]\n" \
|
||||||
|
" [-pf <pid-file>] [--no-pid]\n"\
|
||||||
|
" [-m append|replace|forward|discard]\n" \
|
||||||
|
@@ -154,14 +166,15 @@ static const char url[] =
|
||||||
|
" -l lower0 [ ... -l lowerN]\n" \
|
||||||
|
" -u upper0 [ ... -u upperN]\n" \
|
||||||
|
" lower (client link): [address%%]interface[#index]\n" \
|
||||||
|
-" upper (server link): [address%%]interface"
|
||||||
|
+" upper (server link): [address%%]interface\n\n" DHCRELAY_OPTION82_USAGE
|
||||||
|
#else
|
||||||
|
#define DHCRELAY_USAGE \
|
||||||
|
-"Usage: dhcrelay [-d] [-q] [-a] [-D] [-A <length>] [-c <hops>] [-p <port>]\n" \
|
||||||
|
-" [-pf <pid-file>] [--no-pid]\n" \
|
||||||
|
+"Usage: dhcrelay [-d] [-q] [-a <circuit_id> <remote_id>] [-D]\n" \
|
||||||
|
+" [-A <length>] [-c <hops>] [-p <port>]\n" \
|
||||||
|
+" [-pf <pid-file>] [--no-pid]\n"\
|
||||||
|
" [-m append|replace|forward|discard]\n" \
|
||||||
|
" [-i interface0 [ ... -i interfaceN]\n" \
|
||||||
|
-" server0 [ ... serverN]\n\n"
|
||||||
|
+" server0 [ ... serverN]\n\n" DHCRELAY_OPTION82_USAGE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void usage() {
|
||||||
|
@@ -287,6 +300,15 @@ main(int argc, char **argv) {
|
||||||
|
local_family_set = 1;
|
||||||
|
local_family = AF_INET;
|
||||||
|
#endif
|
||||||
|
+ if (++i == argc)
|
||||||
|
+ usage();
|
||||||
|
+
|
||||||
|
+ if (argv[i] != NULL && argv[i][0] != '-')
|
||||||
|
+ agent_circuit_id_fmt = argv[i++];
|
||||||
|
+
|
||||||
|
+ if (argv[i] != NULL && argv[i][0] != '-')
|
||||||
|
+ agent_remote_id_fmt = argv[i];
|
||||||
|
+
|
||||||
|
add_agent_options = 1;
|
||||||
|
} else if (!strcmp(argv[i], "-A")) {
|
||||||
|
#ifdef DHCPv6
|
||||||
|
@@ -938,6 +960,80 @@ find_interface_by_agent_option(struct dhcp_packet *packet,
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
+ * Format the message that will be used by circuit_id and remote_id
|
||||||
|
+ */
|
||||||
|
+static int
|
||||||
|
+format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_packet *packet,
|
||||||
|
+ const char *format, char *msg, size_t msgn) {
|
||||||
|
+ size_t len = 0;
|
||||||
|
+ char hostname[HOST_NAME_MAX] = { 0 };
|
||||||
|
+ char ifname[IFNAMSIZ] = { 0 };
|
||||||
|
+ char *buf = msg;
|
||||||
|
+
|
||||||
|
+ for ( ; format && *format && len < msgn; ++format) {
|
||||||
|
+ size_t strn = 0;
|
||||||
|
+ const char *str = NULL;
|
||||||
|
+
|
||||||
|
+ if (*format == '%') {
|
||||||
|
+ switch (*++format) {
|
||||||
|
+ case '\0':
|
||||||
|
+ --format;
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case '%': /* A literal '%' */
|
||||||
|
+ str = "%";
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case 'h': /* Hostname */
|
||||||
|
+ gethostname(hostname, HOST_NAME_MAX);
|
||||||
|
+ hostname[HOST_NAME_MAX - 1] = '\0';
|
||||||
|
+ str = hostname;
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case 'p': /* Name of interface that we received the request from */
|
||||||
|
+ strncpy(ifname, ip->name, IFNAMSIZ);
|
||||||
|
+ str = ifname;
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case 'P': /* Physical address of interface that we received the request from */
|
||||||
|
+ str = print_hw_addr(ip->hw_address.hbuf[0], ip->hw_address.hlen - 1, &ip->hw_address.hbuf[1]);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case 'C': /* 24: Client hardware address */
|
||||||
|
+ str = print_hw_addr(packet->htype, packet->hlen, packet->chaddr);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case 'I': /* 20: DHCP relay agent IP address */
|
||||||
|
+ str = inet_ntoa(packet->giaddr);
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ log_error("Option %%%c is unrecognized and will not be formatted!", *format);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (str)
|
||||||
|
+ strn = strlen(str);
|
||||||
|
+ } else {
|
||||||
|
+ str = format;
|
||||||
|
+ strn = 1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Do we have room?
|
||||||
|
+ if ((strn+len) >= msgn) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (str && strn > 0) {
|
||||||
|
+ memcpy(buf+len, str, strn);
|
||||||
|
+ len += strn;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return len;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
* Examine a packet to see if it's a candidate to have a Relay
|
||||||
|
* Agent Information option tacked onto its tail. If it is, tack
|
||||||
|
* the option on.
|
||||||
|
@@ -948,6 +1044,9 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet,
|
||||||
|
int is_dhcp = 0, mms;
|
||||||
|
unsigned optlen;
|
||||||
|
u_int8_t *op, *nextop, *sp, *max, *end_pad = NULL;
|
||||||
|
+ char circuit_id_buf[256] = { '\0' };
|
||||||
|
+ char remote_id_buf[256] = { '\0' };
|
||||||
|
+ size_t circuit_id_len = 0, remote_id_len = 0;
|
||||||
|
|
||||||
|
/* If we're not adding agent options to packets, we can skip
|
||||||
|
this. */
|
||||||
|
@@ -1077,24 +1176,47 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet,
|
||||||
|
op = sp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- /* Sanity check. Had better not ever happen. */
|
||||||
|
- if ((ip->circuit_id_len > 255) ||(ip->circuit_id_len < 1))
|
||||||
|
- log_fatal("Circuit ID length %d out of range [1-255] on "
|
||||||
|
- "%s\n", ip->circuit_id_len, ip->name);
|
||||||
|
- optlen = ip->circuit_id_len + 2; /* RAI_CIRCUIT_ID + len */
|
||||||
|
+ /* option82: custom string for circuit_id */
|
||||||
|
+ if (agent_circuit_id_fmt) {
|
||||||
|
+ circuit_id_len = format_relay_agent_rfc3046_msg(ip, packet, agent_circuit_id_fmt,
|
||||||
|
+ circuit_id_buf, sizeof(circuit_id_buf));
|
||||||
|
+
|
||||||
|
+ if (circuit_id_len == 0)
|
||||||
|
+ strncpy(circuit_id_buf, ip->name, sizeof(ip->name));
|
||||||
|
+
|
||||||
|
+ //log_debug("Sending on %s option82:circuit_id='%s' (%d)",
|
||||||
|
+ // ip->name, circuit_id_buf, circuit_id_len);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* option82: custom string for remote_id */
|
||||||
|
+ if (agent_remote_id_fmt) {
|
||||||
|
+ remote_id_len = format_relay_agent_rfc3046_msg(ip, packet, agent_remote_id_fmt,
|
||||||
|
+ remote_id_buf, sizeof(remote_id_buf));
|
||||||
|
+
|
||||||
|
+ //log_debug("Sending on %s option82:remote_id='%s' (%d)",
|
||||||
|
+ // ip->name, remote_id_buf, remote_id_len);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Sanity check. Had better not ever happen. */
|
||||||
|
+ if (circuit_id_len > 255 || circuit_id_len < 1)
|
||||||
|
+ log_fatal("Circuit ID length %d out of range [1-255] on %s\n",
|
||||||
|
+ circuit_id_len, ip->name);
|
||||||
|
+
|
||||||
|
+ optlen = circuit_id_len + 2; // RAI_CIRCUIT_ID + len
|
||||||
|
|
||||||
|
if (ip->remote_id) {
|
||||||
|
- if (ip->remote_id_len > 255 || ip->remote_id_len < 1)
|
||||||
|
- log_fatal("Remote ID length %d out of range [1-255] "
|
||||||
|
- "on %s\n", ip->circuit_id_len, ip->name);
|
||||||
|
- optlen += ip->remote_id_len + 2; /* RAI_REMOTE_ID + len */
|
||||||
|
+ if (remote_id_len > 255 || remote_id_len < 1)
|
||||||
|
+ log_fatal("Remote ID length %d out of range [1-255] on %s\n",
|
||||||
|
+ remote_id_len, ip->name);
|
||||||
|
+
|
||||||
|
+ optlen += remote_id_len + 2; // RAI_REMOTE_ID + len
|
||||||
|
}
|
||||||
|
|
||||||
|
- /* We do not support relay option fragmenting(multiple options to
|
||||||
|
- * support an option data exceeding 255 bytes).
|
||||||
|
+ /* We do not support relay option fragmenting (multiple options to
|
||||||
|
+ * support an option data exceeding 255 bytes)
|
||||||
|
*/
|
||||||
|
- if ((optlen < 3) ||(optlen > 255))
|
||||||
|
- log_fatal("Total agent option length(%u) out of range "
|
||||||
|
+ if (optlen < 3 || optlen > 255)
|
||||||
|
+ log_fatal("Total agent option length (%u) out of range "
|
||||||
|
"[3 - 255] on %s\n", optlen, ip->name);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1102,7 +1224,7 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet,
|
||||||
|
* If not, forward without adding the option.
|
||||||
|
*/
|
||||||
|
if (max - sp >= optlen + 3) {
|
||||||
|
- log_debug("Adding %d-byte relay agent option", optlen + 3);
|
||||||
|
+ //log_debug("Adding %d-byte relay agent option", optlen + 3);
|
||||||
|
|
||||||
|
/* Okay, cons up *our* Relay Agent Information option. */
|
||||||
|
*sp++ = DHO_DHCP_AGENT_OPTIONS;
|
||||||
|
@@ -1110,16 +1232,16 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet,
|
||||||
|
|
||||||
|
/* Copy in the circuit id... */
|
||||||
|
*sp++ = RAI_CIRCUIT_ID;
|
||||||
|
- *sp++ = ip->circuit_id_len;
|
||||||
|
- memcpy(sp, ip->circuit_id, ip->circuit_id_len);
|
||||||
|
- sp += ip->circuit_id_len;
|
||||||
|
+ *sp++ = circuit_id_len;
|
||||||
|
+ memcpy(sp, circuit_id_buf, circuit_id_len);
|
||||||
|
+ sp += circuit_id_len;
|
||||||
|
|
||||||
|
/* Copy in remote ID... */
|
||||||
|
if (ip->remote_id) {
|
||||||
|
*sp++ = RAI_REMOTE_ID;
|
||||||
|
- *sp++ = ip->remote_id_len;
|
||||||
|
- memcpy(sp, ip->remote_id, ip->remote_id_len);
|
||||||
|
- sp += ip->remote_id_len;
|
||||||
|
+ *sp++ = remote_id_len;
|
||||||
|
+ memcpy(sp, remote_id_buf, remote_id_len);
|
||||||
|
+ sp += remote_id_len;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
++agent_option_errors;
|
||||||
|
--
|
||||||
|
2.1.4
|
||||||
|
|
@ -0,0 +1,114 @@
|
|||||||
|
From 18ca48b7c307e1644f653df4c8503f4ce2677f62 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Joe LeVeque <jolevequ@microsoft.com>
|
||||||
|
Date: Mon, 11 Dec 2017 23:39:10 +0000
|
||||||
|
Subject: [PATCH 2/3] Support for obtaining name of physical interface that is
|
||||||
|
a member of a bridge interface
|
||||||
|
|
||||||
|
---
|
||||||
|
relay/dhcrelay.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
|
||||||
|
1 file changed, 67 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
|
||||||
|
index a26efca..84ec79d 100644
|
||||||
|
--- a/relay/dhcrelay.c
|
||||||
|
+++ b/relay/dhcrelay.c
|
||||||
|
@@ -758,6 +758,7 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet,
|
||||||
|
print_hw_addr(packet->htype, packet->hlen,
|
||||||
|
packet->chaddr),
|
||||||
|
inet_ntoa(sp->to.sin_addr));
|
||||||
|
+
|
||||||
|
++client_packets_relayed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -917,6 +918,7 @@ find_interface_by_agent_option(struct dhcp_packet *packet,
|
||||||
|
++corrupt_agent_options;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
switch(buf[i]) {
|
||||||
|
/* Remember where the circuit ID is... */
|
||||||
|
case RAI_CIRCUIT_ID:
|
||||||
|
@@ -959,6 +961,47 @@ find_interface_by_agent_option(struct dhcp_packet *packet,
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int
|
||||||
|
+_bridgefdbquery(const char *hwAddr, char *interface, int *vlanid) {
|
||||||
|
+
|
||||||
|
+#define xstr(s) str(s)
|
||||||
|
+#define str(s) #s
|
||||||
|
+#define FDB_STRING_LEN 100
|
||||||
|
+#define FDB_BUFFER_LEN (FDB_STRING_LEN + 1)
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Format for sscanf() to read the 1st, 3th, and 5th
|
||||||
|
+ * space-delimited fields
|
||||||
|
+ *
|
||||||
|
+ * bridge fdb show output
|
||||||
|
+ * 6c:64:1a:00:06:13 dev swp35 vlan 0 master bridge permanent
|
||||||
|
+ */
|
||||||
|
+#define FDB_LINE_FORMAT "%" xstr(FDB_STRING_LEN) "s %*s " \
|
||||||
|
+ "%" xstr(FDB_STRING_LEN) "s %*s %d %*s"
|
||||||
|
+
|
||||||
|
+ char cmdstr[FDB_BUFFER_LEN];
|
||||||
|
+ char buf[FDB_BUFFER_LEN];
|
||||||
|
+ char macAddr[FDB_BUFFER_LEN];
|
||||||
|
+
|
||||||
|
+ if ((interface == NULL) || (vlanid == NULL)) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ sprintf(cmdstr, "bridge fdb show | grep -m 1 %s", hwAddr);
|
||||||
|
+ FILE *cmd = popen(cmdstr, "r");
|
||||||
|
+
|
||||||
|
+ if (cmd != NULL) {
|
||||||
|
+ while (fgets(buf, sizeof(buf), cmd)) {
|
||||||
|
+ sscanf(buf, FDB_LINE_FORMAT, macAddr, interface, vlanid);
|
||||||
|
+ //log_debug("bridgefdbquery: macAddr:%s interface: %s vlanid %d",
|
||||||
|
+ // macAddr, interface, *vlanid);
|
||||||
|
+ }
|
||||||
|
+ pclose(cmd);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Format the message that will be used by circuit_id and remote_id
|
||||||
|
*/
|
||||||
|
@@ -991,8 +1034,30 @@ format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_pack
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p': /* Name of interface that we received the request from */
|
||||||
|
- strncpy(ifname, ip->name, IFNAMSIZ);
|
||||||
|
- str = ifname;
|
||||||
|
+ /*
|
||||||
|
+ * Query FDB to identify the exact physical interface only when source MAC address
|
||||||
|
+ * is present and '20: DHCP relay agent IP address' (giaddr) is not present
|
||||||
|
+ */
|
||||||
|
+ if (packet->htype && !packet->giaddr.s_addr) {
|
||||||
|
+ int ret = 0, vlanid = 0;
|
||||||
|
+
|
||||||
|
+ ret = _bridgefdbquery(print_hw_addr(packet->htype, packet->hlen, packet->chaddr),
|
||||||
|
+ ifname,
|
||||||
|
+ &vlanid);
|
||||||
|
+
|
||||||
|
+ // If we failed to find a physical interface using the source mac, default
|
||||||
|
+ // to the interface name we received it on.
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ //log_debug("MAC Address: %s (interface:%s vlan:%d) not found in bridge fdb show",
|
||||||
|
+ // print_hw_addr (packet->htype, packet->hlen, packet->chaddr),
|
||||||
|
+ // ip->name,
|
||||||
|
+ // vlanid);
|
||||||
|
+
|
||||||
|
+ strncpy(ifname, ip->name, IFNAMSIZ);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ str = ifname;
|
||||||
|
+ }
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'P': /* Physical address of interface that we received the request from */
|
||||||
|
--
|
||||||
|
2.1.4
|
||||||
|
|
@ -0,0 +1,177 @@
|
|||||||
|
From 3be065305283b90ddfef92a8736221cbf7cf06e0 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Joe LeVeque <jolevequ@microsoft.com>
|
||||||
|
Date: Tue, 12 Dec 2017 00:49:09 +0000
|
||||||
|
Subject: [PATCH 3/3] Support for loading port alias map file to replace
|
||||||
|
port name with alias in circuit id
|
||||||
|
|
||||||
|
---
|
||||||
|
relay/dhcrelay.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||||
|
1 file changed, 102 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
|
||||||
|
index 84ec79d..0b56e2d 100644
|
||||||
|
--- a/relay/dhcrelay.c
|
||||||
|
+++ b/relay/dhcrelay.c
|
||||||
|
@@ -122,6 +122,14 @@ static void setup_streams(void);
|
||||||
|
char *dhcrelay_sub_id = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+struct interface_name_alias_tuple {
|
||||||
|
+ char if_name[IFNAMSIZ];
|
||||||
|
+ char if_alias[IFNAMSIZ];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct interface_name_alias_tuple *g_interface_name_alias_map = NULL;
|
||||||
|
+static size_t g_interface_name_alias_map_size = 0;
|
||||||
|
+
|
||||||
|
static void do_relay4(struct interface_info *, struct dhcp_packet *,
|
||||||
|
unsigned int, unsigned int, struct iaddr,
|
||||||
|
struct hardware *);
|
||||||
|
@@ -134,6 +142,10 @@ static int strip_relay_agent_options(struct interface_info *,
|
||||||
|
struct interface_info **,
|
||||||
|
struct dhcp_packet *, unsigned);
|
||||||
|
|
||||||
|
+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 const char copyright[] =
|
||||||
|
"Copyright 2004-2015 Internet Systems Consortium.";
|
||||||
|
static const char arr[] = "All rights reserved.";
|
||||||
|
@@ -147,7 +159,7 @@ static const char url[] =
|
||||||
|
"\n" \
|
||||||
|
" %%%% A single %%\n" \
|
||||||
|
" %%h Hostname of device\n" \
|
||||||
|
-" %%p Name of interface that generated the request\n" \
|
||||||
|
+" %%p Alias of interface that generated the request\n" \
|
||||||
|
" %%P Hardware address of interface that generated the request\n" \
|
||||||
|
" %%C Client hardware address\n" \
|
||||||
|
" %%I DHCP relay agent IP Address\n" \
|
||||||
|
@@ -158,10 +170,12 @@ static const char url[] =
|
||||||
|
" [-A <length>] [-c <hops>] [-p <port>]\n" \
|
||||||
|
" [-pf <pid-file>] [--no-pid]\n"\
|
||||||
|
" [-m append|replace|forward|discard]\n" \
|
||||||
|
+" [--name-alias-map-file <name-alias-map-file>]\n" \
|
||||||
|
" [-i interface0 [ ... -i interfaceN]\n" \
|
||||||
|
" server0 [ ... serverN]\n\n" \
|
||||||
|
" dhcrelay -6 [-d] [-q] [-I] [-c <hops>] [-p <port>]\n" \
|
||||||
|
" [-pf <pid-file>] [--no-pid]\n" \
|
||||||
|
+" [--name-alias-map-file <name-alias-map-file>]\n" \
|
||||||
|
" [-s <subscriber-id>]\n" \
|
||||||
|
" -l lower0 [ ... -l lowerN]\n" \
|
||||||
|
" -u upper0 [ ... -u upperN]\n" \
|
||||||
|
@@ -405,6 +419,11 @@ main(int argc, char **argv) {
|
||||||
|
no_dhcrelay_pid = ISC_TRUE;
|
||||||
|
} else if (!strcmp(argv[i], "--no-pid")) {
|
||||||
|
no_pid_file = ISC_TRUE;
|
||||||
|
+ } else if (!strcmp(argv[i], "--name-alias-map-file")) {
|
||||||
|
+ if (++i == argc)
|
||||||
|
+ usage();
|
||||||
|
+ if (load_interface_alias_map(argv[i]) != 0)
|
||||||
|
+ log_fatal("Failed to load interface name-alias map.");
|
||||||
|
} else if (!strcmp(argv[i], "--version")) {
|
||||||
|
log_info("isc-dhcrelay-%s", PACKAGE_VERSION);
|
||||||
|
exit(0);
|
||||||
|
@@ -624,6 +643,8 @@ main(int argc, char **argv) {
|
||||||
|
dispatch();
|
||||||
|
|
||||||
|
/* In fact dispatch() never returns. */
|
||||||
|
+ free_interface_alias_map();
|
||||||
|
+
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1056,6 +1077,16 @@ format_relay_agent_rfc3046_msg(const struct interface_info *ip, struct dhcp_pack
|
||||||
|
strncpy(ifname, ip->name, IFNAMSIZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Attempt to translate SONiC interface name to vendor alias
|
||||||
|
+ if (get_interface_alias_by_name(ip->name, ifname) < 0) {
|
||||||
|
+ //log_debug("Failed to retrieve alias for interface name '%s'. Defaulting to interface name.", ip->name);
|
||||||
|
+ strncpy(ifname, ip->name, IFNAMSIZ);
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ //log_debug("Mapped interface name '%s' to alias '%s'. Adding as option 82 interface alias for MAC Address %s",
|
||||||
|
+ // ip->name, ifname, print_hw_addr (packet->htype, packet->hlen, packet->chaddr),
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
str = ifname;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
@@ -1922,3 +1953,73 @@ dhcp_set_control_state(control_object_state_t oldstate,
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+#define MAX_PORT_CONFIG_LINE_LEN 1024
|
||||||
|
+
|
||||||
|
+// Allocates and loads global map g_interface_name_alias_map
|
||||||
|
+// Also sets global g_interface_name_alias_map_size
|
||||||
|
+static int
|
||||||
|
+load_interface_alias_map(const char *port_alias_map_file_path) {
|
||||||
|
+ int i = 0;
|
||||||
|
+ FILE *fp = NULL;
|
||||||
|
+ char line[MAX_PORT_CONFIG_LINE_LEN] = { 0 };
|
||||||
|
+
|
||||||
|
+ fp = fopen(port_alias_map_file_path,"r");
|
||||||
|
+ if (fp == NULL) {
|
||||||
|
+ log_error("Unable to open %s", port_alias_map_file_path);
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ g_interface_name_alias_map_size = 0;
|
||||||
|
+
|
||||||
|
+ // Count the number of interfaces listed in the file
|
||||||
|
+ while (fgets(line, sizeof(line), fp)) {
|
||||||
|
+ g_interface_name_alias_map_size++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Allocate our map accordingly
|
||||||
|
+ g_interface_name_alias_map = ((struct interface_name_alias_tuple *)
|
||||||
|
+ dmalloc((sizeof(struct interface_name_alias_tuple) * g_interface_name_alias_map_size),
|
||||||
|
+ MDL));
|
||||||
|
+
|
||||||
|
+ // Reset file position indicator to beginning of file
|
||||||
|
+ fseek(fp, 0, SEEK_SET);
|
||||||
|
+
|
||||||
|
+ // Every line should contain exactly one name-alias pair
|
||||||
|
+ while (fgets(line, sizeof(line), fp)) {
|
||||||
|
+ // Each line should read as "<name><whitespace><alias>"
|
||||||
|
+ sscanf(line, "%s %s", g_interface_name_alias_map[i].if_name, g_interface_name_alias_map[i].if_alias);
|
||||||
|
+ i++;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fclose(fp);
|
||||||
|
+
|
||||||
|
+ log_info("Loaded %d interface name-alias mappings", i);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// Locates alias for port named if_name, copies alias into if_alias_out, up to a
|
||||||
|
+// max of IFNAMSIZ bytes.
|
||||||
|
+// Returns 0 on success, -1 on failure
|
||||||
|
+static int
|
||||||
|
+get_interface_alias_by_name(const char *if_name, char *if_alias_out) {
|
||||||
|
+ int i = 0;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < g_interface_name_alias_map_size; i++) {
|
||||||
|
+ if (strncmp(if_name, g_interface_name_alias_map[i].if_name, IFNAMSIZ) == 0) {
|
||||||
|
+ strncpy(if_alias_out, g_interface_name_alias_map[i].if_alias, IFNAMSIZ);
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+// Frees global map g_interface_name_alias_map
|
||||||
|
+// Sets g_interface_name_alias_map_size to 0
|
||||||
|
+static void
|
||||||
|
+free_interface_alias_map(void) {
|
||||||
|
+ free(g_interface_name_alias_map);
|
||||||
|
+ g_interface_name_alias_map_size = 0;
|
||||||
|
+}
|
||||||
|
--
|
||||||
|
2.1.4
|
||||||
|
|
4
src/isc-dhcp/patch/series
Normal file
4
src/isc-dhcp/patch/series
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# This series applies on GIT commit ee3dffdda38a8cfc6ad2005d8d64a165d2a709ba
|
||||||
|
0001-Customizable-Option-82-circuit-ID-and-remote-ID-fiel.patch
|
||||||
|
0002-Support-for-obtaining-name-of-physical-interface-tha.patch
|
||||||
|
0003-Support-for-loading-port-alias-map-file-to-replace-p.patch
|
Loading…
Reference in New Issue
Block a user