aboutsummaryrefslogtreecommitdiff
path: root/relay/dhcrelay.c
diff options
context:
space:
mode:
authorBjørn Mork <bjorn@mork.no>2011-09-24 12:22:01 +0200
committerBjørn Mork <bjorn@mork.no>2011-09-25 14:31:24 +0200
commit1e2c8407b40d4060407845c6f4e81dac8e5f39de (patch)
treeff419225478655408337d5b377b12d5415b84346 /relay/dhcrelay.c
parentb744aea2ce6c579d8e5c34839e51ac239d716130 (diff)
dhcrelay: Support RFC6221 Lightweight DHCPv6 Relay Agent operation
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 <bjorn@mork.no>
Diffstat (limited to 'relay/dhcrelay.c')
-rw-r--r--relay/dhcrelay.c28
1 files changed, 21 insertions, 7 deletions
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 <hops>] [-p <port>]\n" \
+" dhcrelay -6 [-d] [-q] [-I] [-L] [-c <hops>] [-p <port>]\n" \
" [-pf <pid-file>] [--no-pid]\n"\
" -e <enterprisenumber>\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) {