diff --git a/src/isc-dhcp/isc-dhcp-4.3.3-6_dhcrelay-custom-circuit_id-remote_id-and-bridge-iface-support.patch b/src/isc-dhcp/0001-isc-dhcp-4.3.3-6_dhcrelay-custom-circuit_id-remote_id-and-bridge-iface-support.patch similarity index 71% rename from src/isc-dhcp/isc-dhcp-4.3.3-6_dhcrelay-custom-circuit_id-remote_id-and-bridge-iface-support.patch rename to src/isc-dhcp/0001-isc-dhcp-4.3.3-6_dhcrelay-custom-circuit_id-remote_id-and-bridge-iface-support.patch index 6d2a850379c..432d3ea6f71 100644 --- a/src/isc-dhcp/isc-dhcp-4.3.3-6_dhcrelay-custom-circuit_id-remote_id-and-bridge-iface-support.patch +++ b/src/isc-dhcp/0001-isc-dhcp-4.3.3-6_dhcrelay-custom-circuit_id-remote_id-and-bridge-iface-support.patch @@ -1,11 +1,72 @@ -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 +From afede19900d6f6e94565430d4e148959920768dc Mon Sep 17 00:00:00 2001 +From: Joe LeVeque +Date: Sat, 9 Dec 2017 03:33:15 +0000 +Subject: [PATCH] Add customizable Circuit ID and Remote ID fields and 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 @@ +--- + common/discover.c | 10 +- + includes/dhcpd.h | 10 +- + relay/dhcrelay.c | 337 ++++++++++++++++++++++++++++++++++++++++++++++++++---- + 3 files changed, 328 insertions(+), 29 deletions(-) + +diff --git a/common/discover.c b/common/discover.c +index 3cd64a7..8bb7e74 100644 +--- a/common/discover.c ++++ b/common/discover.c +@@ -1848,10 +1848,12 @@ void interface_stash (struct interface_info *tptr) + + void interface_snorf (struct interface_info *tmp, int ir) + { +- tmp -> circuit_id = (u_int8_t *)tmp -> name; +- tmp -> circuit_id_len = strlen (tmp -> name); +- tmp -> remote_id = 0; +- tmp -> remote_id_len = 0; ++ strncpy(tmp->circuit_id, tmp->name, sizeof(tmp->name)); ++ tmp->circuit_id_len = strlen(tmp->name); ++ ++ memset(tmp->remote_id, 0, sizeof(tmp->remote_id)); ++ tmp->remote_id_len = 0; ++ + tmp -> flags = ir; + if (interfaces) { + interface_reference (&tmp -> next, +diff --git a/includes/dhcpd.h b/includes/dhcpd.h +index 1fd12db..6cbae75 100644 +--- a/includes/dhcpd.h ++++ b/includes/dhcpd.h +@@ -1313,6 +1313,8 @@ struct dns_update_state { + }; + + /* Information about each network interface. */ ++#define CIRCUIT_ID_SIZE 64 ++#define REMOTE_ID_SIZE 64 + + struct interface_info { + OMAPI_OBJECT_PREAMBLE; +@@ -1332,12 +1334,12 @@ struct interface_info { + int v6address_max; /* Maximum number of IPv6 addresses + we can store in current buffer. */ + +- u_int8_t *circuit_id; /* Circuit ID associated with this +- interface. */ ++ char circuit_id[CIRCUIT_ID_SIZE]; /* Circuit ID associated ++ with this interface. */ + unsigned circuit_id_len; /* Length of Circuit ID, if there + is one. */ +- u_int8_t *remote_id; /* Remote ID associated with this +- interface (if any). */ ++ char remote_id[REMOTE_ID_SIZE]; /* Remote ID associated with ++ this interface (if any). */ + unsigned remote_id_len; /* Length of Remote ID. */ + + char name [IFNAMSIZ]; /* Its name... */ +diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c +index 15b4997..86443c9 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. */ @@ -14,13 +75,13 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c int max_hop_count = 10; /* Maximum hop count */ #ifdef DHCPv6 -@@ -120,6 +122,14 @@ +@@ -120,6 +122,14 @@ static void setup_streams(void); char *dhcrelay_sub_id = NULL; #endif +struct interface_name_alias_tuple { -+ char if_name[IFNAMSIZ + 1]; -+ char if_alias[IFNAMSIZ + 1]; ++ char if_name[IFNAMSIZ]; ++ char if_alias[IFNAMSIZ]; +}; + +static struct interface_name_alias_tuple *g_interface_name_alias_map = NULL; @@ -29,7 +90,7 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c static void do_relay4(struct interface_info *, struct dhcp_packet *, unsigned int, unsigned int, struct iaddr, struct hardware *); -@@ -132,6 +142,10 @@ +@@ -132,6 +142,10 @@ static int strip_relay_agent_options(struct interface_info *, struct interface_info **, struct dhcp_packet *, unsigned); @@ -40,7 +101,7 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c static const char copyright[] = "Copyright 2004-2015 Internet Systems Consortium."; static const char arr[] = "All rights reserved."; -@@ -140,28 +154,41 @@ +@@ -140,28 +154,41 @@ static const char message[] = static const char url[] = "For info, please visit https://www.isc.org/software/dhcp/"; @@ -87,23 +148,23 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c #endif static void usage() { -@@ -287,6 +314,15 @@ +@@ -287,6 +314,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 -@@ -383,6 +419,13 @@ +@@ -383,6 +419,13 @@ main(int argc, char **argv) { no_dhcrelay_pid = ISC_TRUE; } else if (!strcmp(argv[i], "--no-pid")) { no_pid_file = ISC_TRUE; @@ -117,7 +178,7 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c } else if (!strcmp(argv[i], "--version")) { log_info("isc-dhcrelay-%s", PACKAGE_VERSION); exit(0); -@@ -602,6 +645,8 @@ +@@ -602,6 +645,8 @@ main(int argc, char **argv) { dispatch(); /* In fact dispatch() never returns. */ @@ -126,7 +187,7 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c return (0); } -@@ -690,10 +735,10 @@ +@@ -690,10 +735,10 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet, &to, htop) < 0) { ++server_packet_errors; } else { @@ -141,7 +202,7 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c ++server_packets_relayed; } -@@ -732,10 +777,11 @@ +@@ -732,10 +777,11 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet, &sp->to, NULL) < 0) { ++client_packet_errors; } else { @@ -157,7 +218,30 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c ++client_packets_relayed; } } -@@ -937,6 +983,151 @@ +@@ -895,17 +941,15 @@ find_interface_by_agent_option(struct dhcp_packet *packet, + ++corrupt_agent_options; + return (-1); + } +- switch(buf[i]) { ++ else if (buf[i] == RAI_CIRCUIT_ID) { + /* Remember where the circuit ID is... */ +- case RAI_CIRCUIT_ID: + circuit_id = &buf[i + 2]; + circuit_id_len = buf[i + 1]; + i += circuit_id_len + 2; +- continue; +- +- default: +- i += buf[i + 1] + 2; +- break; ++ break; ++ } ++ else { ++ i += (buf[i + 1] + 2); + } + } + +@@ -937,6 +981,153 @@ find_interface_by_agent_option(struct dhcp_packet *packet, return (-1); } @@ -182,13 +266,13 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c + 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); @@ -198,7 +282,7 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c + pclose(cmd); + return 0; + } -+ ++ + return -1; +} + @@ -209,29 +293,30 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c +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 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 */ + /* + * Query FDB to identify the exact physical interface only when source MAC address @@ -239,116 +324,117 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c + */ + 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, ++ 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); + } -+ 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); ++ ++ // 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; -+ ++ + 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; ++ strn = 1; + } -+ ++ + // Do we have room? -+ if ((strn+len) > msgn) { ++ if ((strn+len) >= msgn) { + return 0; + } -+ -+ memcpy(buf+len, str, strn); -+ len += strn; ++ ++ 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 -@@ -948,6 +1139,8 @@ +@@ -948,6 +1139,8 @@ 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[255] = { '\0', }; -+ char remote_id_buf[255] = { '\0', }; ++ char circuit_id_buf[CIRCUIT_ID_SIZE] = { '\0' }; ++ char remote_id_buf[REMOTE_ID_SIZE] = { '\0' }; /* If we're not adding agent options to packets, we can skip this. */ -@@ -1077,6 +1270,38 @@ +@@ -1077,6 +1270,38 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet, 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; ++ strncpy(ip->circuit_id, circuit_id_buf, sizeof(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; ++ strncpy(ip->remote_id, remote_id_buf, sizeof(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); + } @@ -357,7 +443,7 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c /* 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 @@ +@@ -1102,7 +1327,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) { @@ -366,7 +452,7 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c /* Okay, cons up *our* Relay Agent Information option. */ *sp++ = DHO_DHCP_AGENT_OPTIONS; -@@ -1735,3 +1960,73 @@ +@@ -1735,3 +1960,73 @@ dhcp_set_control_state(control_object_state_t oldstate, exit(0); } @@ -380,39 +466,39 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c + 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 "" + 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; +} + @@ -422,14 +508,14 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c +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; +} + @@ -440,3 +526,6 @@ diff -ruN a/isc-dhcp/relay/dhcrelay.c b/isc-dhcp/relay/dhcrelay.c + free(g_interface_name_alias_map); + g_interface_name_alias_map_size = 0; +} +-- +2.1.4 + diff --git a/src/isc-dhcp/Makefile b/src/isc-dhcp/Makefile index ec4c185b79f..c46e47e6a97 100644 --- a/src/isc-dhcp/Makefile +++ b/src/isc-dhcp/Makefile @@ -13,13 +13,11 @@ $(addprefix $(DEST)/, $(MAIN_TARGET)): $(DEST)/% : git clone https://anonscm.debian.org/cgit/pkg-dhcp/isc-dhcp.git pushd ./isc-dhcp git checkout -f debian/$(ISC_DHCP_VERSION) - popd # Apply patch - patch -p1 < isc-dhcp-$(ISC_DHCP_VERSION)_dhcrelay-custom-circuit_id-remote_id-and-bridge-iface-support.patch + git apply ../0001-isc-dhcp-$(ISC_DHCP_VERSION)_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 -j$(SONIC_CONFIG_MAKE_JOBS) popd