diff options
author | Bjørn Mork <bjorn@mork.no> | 2011-09-25 13:42:30 +0200 |
---|---|---|
committer | Bjørn Mork <bjorn@mork.no> | 2011-09-25 14:12:11 +0200 |
commit | bc45bfeab24daa463d20ab22c23f2b512b8d1c06 (patch) | |
tree | f9e3a129728a38b587c6488e6c2d8e66cf34f4b2 | |
parent | 9e80cf72b366e7cdabe9cc77ef19e2ebf3609cc0 (diff) |
dhcrelay: Adding D6O_REMOTE_ID support to DHCPv6 relay
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@mork.no>
-rw-r--r-- | relay/dhcrelay.8 | 13 | ||||
-rw-r--r-- | 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, |