-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DHCP Relay]: Add support for custom Option 82 circuit_id of the form '<hostname>:<portname>' #747
Merged
+351
−5
Merged
Changes from 7 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
3a2b6d6
Add isc-dhcp-relay .deb package to image build process, along with my…
jleveque f4a8bfb
Install custom isc-dhcp-relay in dhcp_relay docker
jleveque f633656
Install isc-dhcp-relay build dependencies in sonic-slave Docker conta…
jleveque 1d2f244
Copy the built .deb package to the destination directory
jleveque fc3560e
Add dependencies for isc-dhcp-relay
jleveque fe394ba
Change Option 82 string to '<hostname>:<portname>'
jleveque b551b56
Install dependencies of .deb files implicitly in Dockerfile
jleveque 938474f
Add docker-dhcp-relay/Dockerfile to .gitignore
jleveque a2579da
Remove unused line
jleveque 28b45f3
Remove unnecessary space
jleveque File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
FROM docker-config-engine | ||
|
||
# Make apt-get non-interactive | ||
ENV DEBIAN_FRONTEND=noninteractive | ||
|
||
# Update apt's cache of available packages | ||
RUN apt-get update | ||
|
||
{% if docker_dhcp_relay_debs.strip() -%} | ||
# Copy built Debian packages | ||
{%- for deb in docker_dhcp_relay_debs.split(' ') %} | ||
COPY debs/{{ deb }}{{' '}} debs/ | ||
{%- endfor %} | ||
|
||
# Install built Debian packages and implicitly install their dependencies | ||
{%- for deb in docker_dhcp_relay_debs.split(' ') %} | ||
#RUN dpkg -i debs/{{ deb }} | ||
RUN dpkg_apt() { [ -f $1 ] && { dpkg -i $1 || apt-get -y install -f; } || return 1; }; dpkg_apt debs/{{ deb }} | ||
{%- endfor %} | ||
{%- endif %} | ||
|
||
# Clean up | ||
RUN apt-get clean -y; apt-get autoclean -y; apt-get autoremove -y | ||
RUN rm -rf /debs | ||
|
||
COPY ["start.sh", "isc-dhcp-relay.sh", "/usr/bin/"] | ||
COPY ["supervisord.conf", "/etc/supervisor/conf.d/"] | ||
COPY ["isc-dhcp-relay.j2", "/usr/share/sonic/templates/"] | ||
|
||
ENTRYPOINT ["/usr/bin/supervisord"] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# isc-dhcp packages | ||
|
||
ISC_DHCP_VERSION = 4.3.1-6 | ||
|
||
export ISC_DHCP_VERSION | ||
|
||
ISC_DHCP_COMMON = isc-dhcp-common_$(ISC_DHCP_VERSION)_amd64.deb | ||
$(ISC_DHCP_COMMON)_SRC_PATH = $(SRC_PATH)/isc-dhcp | ||
SONIC_MAKE_DEBS += $(ISC_DHCP_COMMON) | ||
|
||
ISC_DHCP_RELAY = isc-dhcp-relay_$(ISC_DHCP_VERSION)_amd64.deb | ||
$(eval $(call add_derived_package,$(ISC_DHCP_COMMON),$(ISC_DHCP_RELAY))) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
.ONESHELL: | ||
SHELL = /bin/bash | ||
.SHELLFLAGS += -e | ||
|
||
MAIN_TARGET = isc-dhcp-common_$(ISC_DHCP_VERSION)_amd64.deb | ||
DERIVED_TARGETS = isc-dhcp-relay_$(ISC_DHCP_VERSION)_amd64.deb | ||
|
||
$(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : | ||
# Remove any stale files | ||
rm -rf ./isc-dhcp | ||
|
||
# Clone isc-dhcp repo | ||
git clone git://anonscm.debian.org/pkg-dhcp/isc-dhcp.git | ||
pushd ./isc-dhcp | ||
git checkout -f debian/4.3.1-6 | ||
popd | ||
|
||
# Apply patch | ||
patch -p1 < isc-dhcp-4.3.1_dhcrelay-custom-circuit_id-remote_id-and-bridge-iface-support.patch | ||
|
||
# Build source and Debian packages | ||
pushd ./isc-dhcp | ||
dpkg-buildpackage -rfakeroot -b -us -uc | ||
popd | ||
|
||
# Move the newly-built .deb packages to the destination directory | ||
mv $* $(DERIVED_TARGETS) $(DEST)/ | ||
|
||
$(addprefix $(DEST)/, $(DERIVED_TARGETS)): $(DEST)/% : $(DEST)/$(MAIN_TARGET) | ||
|
289 changes: 289 additions & 0 deletions
289
...c-dhcp/isc-dhcp-4.3.1_dhcrelay-custom-circuit_id-remote_id-and-bridge-iface-support.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,289 @@ | ||
This patch adds the following functionality to dhcrelay in isc-dhcp v4.3.1-6: | ||
* Add customizable Circuit ID and Remote ID fields | ||
* Support for obtaining name of physical interface of 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 2014-08-06 22:35:02.000000000 +0000 | ||
+++ b/isc-dhcp/relay/dhcrelay.c 2017-06-08 21:39:53.856192546 +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 | ||
@@ -140,9 +142,19 @@ | ||
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 @@ | ||
" -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 @@ | ||
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 | ||
@@ -937,6 +959,166 @@ | ||
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) { | ||
+ char cmdstr[256] = { 0 }; | ||
+ char cmdout[256] = { 0 }; | ||
+ | ||
+ log_debug("Adding option 82 interface name for MAC Address: %s as %s", | ||
+ print_hw_addr (packet->htype, packet->hlen, packet->chaddr), | ||
+ ip->name); | ||
+ | ||
+ // Translate SONiC interface name to vendor alias | ||
+ sprintf(cmdstr, "sonic-cfggen -m /etc/sonic/minigraph.xml -v \"minigraph_ports['%s'].alias\"", ip->name); | ||
+ | ||
+ FILE *cmd = popen(cmdstr, "r"); | ||
+ | ||
+ if (cmd != NULL) { | ||
+ while (fgets(cmdout, sizeof(cmdout), cmd)) { | ||
+ // Strip any trailing newline | ||
+ if (cmdout[strlen(cmdout) - 1] == '\n') | ||
+ cmdout[strlen(cmdout) - 1] = '\0'; | ||
+ | ||
+ log_debug ("Retrieved alias %s for interface %s", buf, ip->name); | ||
+ } | ||
+ | ||
+ pclose(cmd); | ||
+ } | ||
+ | ||
+ strncpy(ifname, cmdout, 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; | ||
+ } | ||
+ | ||
+ 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 +1130,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 +1261,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 " | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove the comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it looks like commented code. it's confusing. Someone didn't removed old code, or necessary code wasn't uncommented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the confusion. I was looking as the wrong comment!