aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2011-09-25 13:42:30 +0200
committerBjørn Mork <bjorn@mork.no>2011-09-25 14:12:11 +0200
commitbc45bfeab24daa463d20ab22c23f2b512b8d1c06 (patch)
treef9e3a129728a38b587c6488e6c2d8e66cf34f4b2
parent9e80cf72b366e7cdabe9cc77ef19e2ebf3609cc0 (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.813
-rw-r--r--relay/dhcrelay.c40
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,