[PATCH 2/6] dhcrelay: Adding D6O_REMOTE_ID support to DHCPv6 relay

Bjørn Mork bjorn at mork.no
Sun Sep 25 12:59:45 UTC 2011


Optionally add a D6O_REMOTE_ID option as specified by RFC4649. The
required enterprise number is set using a new command line option,
while the existing -l option is extended to allow adding a per-port
remote id.

Signed-off-by: Bjørn Mork <bjorn at mork.no>
---
 relay/dhcrelay.8 |   13 +++++++++++--
 relay/dhcrelay.c |   40 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/relay/dhcrelay.8 b/relay/dhcrelay.8
index a087d14..06408a3 100644
--- a/relay/dhcrelay.8
+++ b/relay/dhcrelay.8
@@ -103,6 +103,10 @@ dhcrelay - Dynamic Host Configuration Protocol Relay Agent
 [
 .B --no-pid
 ]
+[
+.B -e
+.I enterprisenumber
+]
 .B -l
 .I lower0
 [
@@ -221,7 +225,11 @@ in use, to disambiguate between them.  The \fB-I\fR option causes
 dhcrelay to send the option even if there is only one downstream
 interface.
 .TP
--l [\fIaddress%\fR]\fIifname\fR[\fI#index\fR]
+-e \fIenterprisenumber\fR
+Specifies the IANA allocated enterprise number to be used in REMOTE-ID
+options.  Required for adding REMOTE-ID
+.TP
+-l [\fIaddress%\fR]\fIifname\fR[\fI#index\fR][\fI!remoteid\fR]
 Specifies the ``lower'' network interface for DHCPv6 relay mode: the
 interface on which queries will be received from clients or from other
 relay agents.  At least one \fB-l\fR option must be included in the command
@@ -229,7 +237,8 @@ line when running in DHCPv6 mode.  The interface name \fIifname\fR is a
 mandatory parameter.  The link address can be specified by \fIaddress%\fR;
 if it isn't, dhcrelay will use the first non-link-local address configured
 on the interface.  The optional \fI#index\fR parameter specifies the
-interface index.
+interface index. The optional \fI!remoteid\fR parameter specifies the
+ascii remote id value (requires the \fB-e\fR option as well).
 .TP
 -u [\fIaddress%\fR]\fIifname\fR
 Specifies the ``upper'' network interface for DHCPv6 relay mode: the
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
index 1c8c522..96839cd 100644
--- a/relay/dhcrelay.c
+++ b/relay/dhcrelay.c
@@ -105,6 +105,11 @@ struct server_list {
 } *servers;
 
 #ifdef DHCPv6
+int enterprise_number = 0;	/* enterprise-number for use with remote-id */
+struct remote_id {
+	int enterprise;
+	char id[];
+};
 struct stream_list {
 	struct stream_list *next;
 	struct interface_info *ifp;
@@ -147,9 +152,10 @@ static const char url[] =
 "                     server0 [ ... serverN]\n\n" \
 "       dhcrelay -6   [-d] [-q] [-I] [-c <hops>] [-p <port>]\n" \
 "                     [-pf <pid-file>] [--no-pid]\n"\
+"                     -e <enterprisenumber>\n"\
 "                     -l lower0 [ ... -l lowerN]\n" \
 "                     -u upper0 [ ... -u upperN]\n" \
-"       lower (client link): [address%%]interface[#index]\n" \
+"       lower (client link): [address%%]interface[#index][!remoteid]\n" \
 "       upper (server link): [address%%]interface"
 #else
 #define DHCRELAY_USAGE \
@@ -331,6 +337,15 @@ main(int argc, char **argv) {
 			local_family_set = 1;
 			local_family = AF_INET6;
 			use_if_id = ISC_TRUE;
+		} else if (!strcmp(argv[i], "-e")) {
+			if (local_family_set && (local_family == AF_INET)) {
+				usage();
+			}
+			local_family_set = 1;
+			local_family = AF_INET6;
+			if (++i == argc)
+				usage();
+			enterprise_number = atoi(argv[i]);
 		} else if (!strcmp(argv[i], "-l")) {
 			if (local_family_set && (local_family == AF_INET)) {
 				usage();
@@ -1123,13 +1138,13 @@ add_relay_agent_options(struct interface_info *ip, struct dhcp_packet *packet,
 
 #ifdef DHCPv6
 /*
- * Parse a downstream argument: [address%]interface[#index].
+ * Parse a downstream argument: [address%]interface[#index][!remoteid].
  */
 static struct stream_list *
 parse_downstream(char *arg) {
 	struct stream_list *dp, *up;
 	struct interface_info *ifp = NULL;
-	char *ifname, *addr, *iid;
+	char *ifname, *addr, *iid, *rid;
 	isc_result_t status;
 
 	if (!supports_multiple_interfaces(ifp) &&
@@ -1145,6 +1160,10 @@ parse_downstream(char *arg) {
 		*ifname++ = '\0';
 		addr = arg;
 	}
+	rid = strchr(ifname, '!');
+	if (rid != NULL) {
+		*rid++ = '\0';
+	}
 	iid = strchr(ifname, '#');
 	if (iid != NULL) {
 		*iid++ = '\0';
@@ -1196,6 +1215,13 @@ parse_downstream(char *arg) {
 	} else {
 		dp->id = -1;
 	}
+	if ((rid != NULL) && ((rid - sizeof(int)) >= arg)) {
+		struct remote_id *remote_id;
+		remote_id = (struct remote_id *) (rid - sizeof(int));
+		remote_id->enterprise = htonl(enterprise_number);
+		dp->ifp->remote_id = (u_int8_t *) remote_id;
+		dp->ifp->remote_id_len = sizeof(int) + strlen(rid);
+	}
 	/* !addr case handled by setup. */
 	if (addr && (inet_pton(AF_INET6, addr, &dp->link.sin6_addr) <= 0))
 		log_fatal("Bad link address '%s'", addr);
@@ -1329,6 +1355,7 @@ setup_streams(void) {
  */
 static const int required_forw_opts[] = {
 	D6O_INTERFACE_ID,
+	D6O_REMOTE_ID,
 	D6O_RELAY_MSG,
 	0
 };
@@ -1433,6 +1460,13 @@ opt_error:
 					D6O_INTERFACE_ID, 0))
 		goto opt_error;
 
+       /* add remote id */
+	if (dp->ifp->remote_id && !save_option_buffer(&dhcpv6_universe, opts,
+					NULL, dp->ifp->remote_id,
+					dp->ifp->remote_id_len,
+					D6O_REMOTE_ID, 0))
+		goto opt_error;
+
 	/* Add the relay-msg carrying the packet. */
 	if (!save_option_buffer(&dhcpv6_universe, opts,
 				NULL, (unsigned char *) packet->raw,
-- 
1.7.2.5




More information about the dhcp-users mailing list