This repository has been archived on 2025-03-20. You can view files and clone it, but cannot push or open issues or pull requests.
sonic-buildimage/src/isc-dhcp/patch/0002-Support-for-obtaining-name-of-physical-interface-tha.patch
Joe LeVeque 2571cb59b6 [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
2017-12-12 23:56:59 -08:00

115 lines
4.0 KiB
Diff

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