From 1e2c8407b40d4060407845c6f4e81dac8e5f39de Mon Sep 17 00:00:00 2001 From: Bjørn Mork Date: Sat, 24 Sep 2011 12:22:01 +0200 Subject: dhcrelay: Support RFC6221 Lightweight DHCPv6 Relay Agent operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There really isn't much required for layer2 operation. Just set the link address to :: and you're basically done. Signed-off-by: Bjørn Mork --- relay/dhcrelay.8 | 18 ++++++++++++++---- relay/dhcrelay.c | 28 +++++++++++++++++++++------- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/relay/dhcrelay.8 b/relay/dhcrelay.8 index 06408a3..c4115cb 100644 --- a/relay/dhcrelay.8 +++ b/relay/dhcrelay.8 @@ -86,7 +86,7 @@ dhcrelay - Dynamic Host Configuration Protocol Relay Agent .PP .B dhcrelay -6 [ -.B -dqI +.B -dqIL ] [ .B -p @@ -225,6 +225,15 @@ 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 +Enable Lightweight DHCPv6 Relay Agent (layer 2) operation according to +RFC6221. This forces the \fB-I\fR option on, and uses the unspecified +address (::) as link address in all relayed packets, enabling operation +on a layer 2 brigde with no global address at all. Note that this +option makes both the \fB-I\fR option and the \fIaddress%\fR parameter +of the \fB-l\fR option redundant. Any configured \fIaddress%\fR will +be silently ignored. +.TP -e \fIenterprisenumber\fR Specifies the IANA allocated enterprise number to be used in REMOTE-ID options. Required for adding REMOTE-ID @@ -236,9 +245,10 @@ relay agents. At least one \fB-l\fR option must be included in the command 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. The optional \fI!remoteid\fR parameter specifies the -ascii remote id value (requires the \fB-e\fR option as well). +on the interface unless configured for LDRA with the \fB-L\fR option. +The optional \fI#index\fR parameter specifies the 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 780b59a..f00aa2f 100644 --- a/relay/dhcrelay.c +++ b/relay/dhcrelay.c @@ -83,6 +83,7 @@ int max_hop_count = 10; /* Maximum hop count */ #ifdef DHCPv6 /* Force use of DHCPv6 interface-id option. */ isc_boolean_t use_if_id = ISC_FALSE; +isc_boolean_t rfc6221_ldra = ISC_FALSE; /* implement RFC6221 LDRA */ #endif /* Maximum size of a packet with agent options added. */ @@ -150,7 +151,7 @@ static const char url[] = " [-m append|replace|forward|discard]\n" \ " [-i interface0 [ ... -i interfaceN]\n" \ " server0 [ ... serverN]\n\n" \ -" dhcrelay -6 [-d] [-q] [-I] [-c ] [-p ]\n" \ +" dhcrelay -6 [-d] [-q] [-I] [-L] [-c ] [-p ]\n" \ " [-pf ] [--no-pid]\n"\ " -e \n"\ " -l lower0 [ ... -l lowerN]\n" \ @@ -337,6 +338,14 @@ main(int argc, char **argv) { local_family_set = 1; local_family = AF_INET6; use_if_id = ISC_TRUE; + } else if (!strcmp(argv[i], "-L")) { + if (local_family_set && (local_family == AF_INET)) { + usage(); + } + local_family_set = 1; + local_family = AF_INET6; + rfc6221_ldra = ISC_TRUE; + use_if_id = ISC_TRUE; /* required by RFC6221 */ } else if (!strcmp(argv[i], "-e")) { if (local_family_set && (local_family == AF_INET)) { usage(); @@ -1223,8 +1232,9 @@ parse_downstream(char *arg) { 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); + if (!rfc6221_ldra && /* silently ignore any addr for LDRA */ + addr && (inet_pton(AF_INET6, addr, &dp->link.sin6_addr) <= 0)) + log_fatal("Bad link address '%s'", addr); return dp; } @@ -1304,6 +1314,14 @@ setup_streams(void) { isc_boolean_t link_is_set; for (dp = downstreams; dp; dp = dp->next) { + /* Set interface-id. */ + if (dp->id == -1) + dp->id = htonl(dp->ifp->index); + + /* link address must be :: for LDRA according to RFC6221 */ + if (rfc6221_ldra) + continue; + /* Check interface */ if (dp->ifp->v6address_count == 0) log_fatal("Interface '%s' has no IPv6 addresses.", @@ -1331,10 +1349,6 @@ setup_streams(void) { memcpy(&dp->link.sin6_addr, &dp->ifp->v6addresses[i], sizeof(dp->link.sin6_addr)); - - /* Set interface-id. */ - if (dp->id == -1) - dp->id = htonl(dp->ifp->index); } for (up = upstreams; up; up = up->next) { -- cgit v1.2.3