summaryrefslogtreecommitdiffstats
path: root/usr.sbin/rtadvd/config.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/rtadvd/config.c')
-rw-r--r--usr.sbin/rtadvd/config.c396
1 files changed, 317 insertions, 79 deletions
diff --git a/usr.sbin/rtadvd/config.c b/usr.sbin/rtadvd/config.c
index ec294f1..01cfb4c 100644
--- a/usr.sbin/rtadvd/config.c
+++ b/usr.sbin/rtadvd/config.c
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* $KAME: config.c,v 1.11 2000/05/16 13:34:13 itojun Exp $ */
+/* $KAME: config.c,v 1.37 2001/05/25 07:34:00 itojun Exp $ */
/*
* Copyright (C) 1998 WIDE Project.
@@ -34,6 +34,7 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
+#include <sys/sysctl.h>
#include <net/if.h>
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
@@ -62,6 +63,7 @@
#include <search.h>
#endif
#include <unistd.h>
+#include <ifaddrs.h>
#include "rtadvd.h"
#include "advcap.h"
@@ -71,6 +73,7 @@
static void makeentry __P((char *, int, char *, int));
static void get_prefix __P((struct rainfo *));
+static int getinet6sysctl __P((int));
extern struct rainfo *ralist;
@@ -82,9 +85,11 @@ getconfig(intface)
char tbuf[BUFSIZ];
struct rainfo *tmp;
long val;
+ long long val64;
char buf[BUFSIZ];
char *bp = buf;
char *addr;
+ static int forwarding = -1;
#define MUSTHAVE(var, cap) \
do { \
@@ -114,6 +119,13 @@ getconfig(intface)
tmp = (struct rainfo *)malloc(sizeof(*ralist));
memset(tmp, 0, sizeof(*tmp));
tmp->prefix.next = tmp->prefix.prev = &tmp->prefix;
+ tmp->route.next = tmp->route.prev = &tmp->route;
+
+ /* check if we are allowed to forward packets (if not determined) */
+ if (forwarding < 0) {
+ if ((forwarding = getinet6sysctl(IPV6CTL_FORWARDING)) < 0)
+ exit(1);
+ }
/* get interface information */
if (agetflag("nolladdr"))
@@ -164,12 +176,22 @@ getconfig(intface)
tmp->hoplimit = val & 0xff;
MAYHAVE(val, "raflags", 0);
- tmp->managedflg= val & ND_RA_FLAG_MANAGED;
+ tmp->managedflg = val & ND_RA_FLAG_MANAGED;
tmp->otherflg = val & ND_RA_FLAG_OTHER;
#ifdef MIP6
if (mobileip6)
tmp->haflg = val & ND_RA_FLAG_HA;
#endif
+#ifndef ND_RA_FLAG_RTPREF_MASK
+#define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */
+#define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */
+#endif
+ tmp->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
+ if (tmp->rtpref == ND_RA_FLAG_RTPREF_RSV) {
+ syslog(LOG_ERR, "<%s> invalid router preference on %s",
+ __FUNCTION__, intface);
+ exit(1);
+ }
MAYHAVE(val, "rltime", tmp->maxinterval * 3);
if (val && (val < tmp->maxinterval || val > MAXROUTERLIFETIME)) {
@@ -180,6 +202,21 @@ getconfig(intface)
tmp->maxinterval, MAXROUTERLIFETIME);
exit(1);
}
+ /*
+ * Basically, hosts MUST NOT send Router Advertisement messages at any
+ * time (RFC 2461, Section 6.2.3). However, it would sometimes be
+ * useful to allow hosts to advertise some parameters such as prefix
+ * information and link MTU. Thus, we allow hosts to invoke rtadvd
+ * only when router lifetime (on every advertising interface) is
+ * explicitly set zero. (see also the above section)
+ */
+ if (val && forwarding == 0) {
+ syslog(LOG_WARNING,
+ "<%s> non zero router lifetime is specified for %s, "
+ "which must not be allowed for hosts.",
+ __FUNCTION__, intface);
+ exit(1);
+ }
tmp->lifetime = val & 0xffff;
MAYHAVE(val, "rtime", DEF_ADVREACHABLETIME);
@@ -191,20 +228,23 @@ getconfig(intface)
}
tmp->reachabletime = (u_int32_t)val;
- MAYHAVE(val, "retrans", DEF_ADVRETRANSTIMER);
- if (val < 0 || val > 0xffffffff) {
+ MAYHAVE(val64, "retrans", DEF_ADVRETRANSTIMER);
+ if (val64 < 0 || val64 > 0xffffffff) {
syslog(LOG_ERR,
"<%s> retrans time out of range", __FUNCTION__);
exit(1);
}
- tmp->retranstimer = (u_int32_t)val;
+ tmp->retranstimer = (u_int32_t)val64;
-#ifdef MIP6
- if (!mobileip6)
+#ifndef MIP6
+ if (agetstr("hapref", &bp) || agetstr("hatime", &bp)) {
+ syslog(LOG_ERR,
+ "<%s> mobile-ip6 configuration not supported",
+ __FUNCTION__);
+ exit(1);
+ }
#else
- if (1)
-#endif
- {
+ if (!mobileip6) {
if (agetstr("hapref", &bp) || agetstr("hatime", &bp)) {
syslog(LOG_ERR,
"<%s> mobile-ip6 configuration without "
@@ -212,9 +252,7 @@ getconfig(intface)
__FUNCTION__);
exit(1);
}
- }
-#ifdef MIP6
- else {
+ } else {
tmp->hapref = 0;
if ((val = agetnum("hapref")) >= 0)
tmp->hapref = (int16_t)val;
@@ -233,6 +271,15 @@ getconfig(intface)
#endif
/* prefix information */
+
+ /*
+ * This is an implementation specific parameter to consinder
+ * link propagation delays and poorly synchronized clocks when
+ * checking consistency of advertised lifetimes.
+ */
+ MAYHAVE(val, "clockskew", 0);
+ tmp->clockskew = val;
+
if ((pfxs = agetnum("addrs")) < 0) {
/* auto configure prefix information */
if (agetstr("addr", &bp) || agetstr("addr1", &bp)) {
@@ -281,7 +328,7 @@ getconfig(intface)
{
MAYHAVE(val, entbuf,
(ND_OPT_PI_FLAG_ONLINK|ND_OPT_PI_FLAG_AUTO|
- ND_OPT_PI_FLAG_RTADDR));
+ ND_OPT_PI_FLAG_ROUTER));
} else
#endif
{
@@ -291,29 +338,44 @@ getconfig(intface)
pfx->onlinkflg = val & ND_OPT_PI_FLAG_ONLINK;
pfx->autoconfflg = val & ND_OPT_PI_FLAG_AUTO;
#ifdef MIP6
- if (mobileip6)
- pfx->routeraddr = val & ND_OPT_PI_FLAG_RTADDR;
+ pfx->routeraddr = val & ND_OPT_PI_FLAG_ROUTER;
#endif
makeentry(entbuf, i, "vltime", added);
- MAYHAVE(val, entbuf, DEF_ADVVALIDLIFETIME);
- if (val < 0 || val > 0xffffffff) {
+ MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
+ if (val64 < 0 || val64 > 0xffffffff) {
syslog(LOG_ERR,
"<%s> vltime out of range",
__FUNCTION__);
exit(1);
}
- pfx->validlifetime = (u_int32_t)val;
+ pfx->validlifetime = (u_int32_t)val64;
+
+ makeentry(entbuf, i, "vltimedecr", added);
+ if (agetflag(entbuf)) {
+ struct timeval now;
+ gettimeofday(&now, 0);
+ pfx->vltimeexpire =
+ now.tv_sec + pfx->validlifetime;
+ }
makeentry(entbuf, i, "pltime", added);
- MAYHAVE(val, entbuf, DEF_ADVPREFERREDLIFETIME);
- if (val < 0 || val > 0xffffffff) {
+ MAYHAVE(val64, entbuf, DEF_ADVPREFERREDLIFETIME);
+ if (val64 < 0 || val64 > 0xffffffff) {
syslog(LOG_ERR,
"<%s> pltime out of range",
__FUNCTION__);
exit(1);
}
- pfx->preflifetime = (u_int32_t)val;
+ pfx->preflifetime = (u_int32_t)val64;
+
+ makeentry(entbuf, i, "pltimedecr", added);
+ if (agetflag(entbuf)) {
+ struct timeval now;
+ gettimeofday(&now, 0);
+ pfx->pltimeexpire =
+ now.tv_sec + pfx->preflifetime;
+ }
makeentry(entbuf, i, "addr", added);
addr = (char *)agetstr(entbuf, &bp);
@@ -368,6 +430,106 @@ getconfig(intface)
exit(1);
}
+ /* route information */
+
+ MAYHAVE(val, "routes", 0);
+ if (val < 0 || val > 0xffffffff) {
+ syslog(LOG_ERR,
+ "<%s> number of route information improper", __FUNCTION__);
+ exit(1);
+ }
+ tmp->routes = val;
+ for (i = 0; i < tmp->routes; i++) {
+ struct rtinfo *rti;
+ char entbuf[256];
+ int added = (tmp->routes > 1) ? 1 : 0;
+
+ /* allocate memory to store prefix information */
+ if ((rti = malloc(sizeof(struct rtinfo))) == NULL) {
+ syslog(LOG_ERR,
+ "<%s> can't allocate enough memory",
+ __FUNCTION__);
+ exit(1);
+ }
+ memset(rti, 0, sizeof(*rti));
+
+ /* link into chain */
+ insque(rti, &tmp->route);
+
+ makeentry(entbuf, i, "rtrplen", added);
+ MAYHAVE(val, entbuf, 64);
+ if (val < 0 || val > 128) {
+ syslog(LOG_ERR,
+ "<%s> prefixlen out of range",
+ __FUNCTION__);
+ exit(1);
+ }
+ rti->prefixlen = (int)val;
+
+ makeentry(entbuf, i, "rtrflags", added);
+ MAYHAVE(val, entbuf, 0);
+ rti->rtpref = val & ND_RA_FLAG_RTPREF_MASK;
+ if (rti->rtpref == ND_RA_FLAG_RTPREF_RSV) {
+ syslog(LOG_ERR, "<%s> invalid router preference",
+ __FUNCTION__);
+ exit(1);
+ }
+
+ makeentry(entbuf, i, "rtrltime", added);
+ /*
+ * XXX: since default value of route lifetime is not defined in
+ * draft-draves-route-selection-01.txt, I took the default
+ * value of valid lifetime of prefix as its default.
+ * It need be much considered.
+ */
+ MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
+ if (val64 < 0 || val64 > 0xffffffff) {
+ syslog(LOG_ERR,
+ "<%s> rtrltime out of range",
+ __FUNCTION__);
+ exit(1);
+ }
+ rti->ltime = (u_int32_t)val64;
+
+ makeentry(entbuf, i, "rtrprefix", added);
+ addr = (char *)agetstr(entbuf, &bp);
+ if (addr == NULL) {
+ syslog(LOG_ERR,
+ "<%s> need %s as an route for "
+ "interface %s",
+ __FUNCTION__, entbuf, intface);
+ exit(1);
+ }
+ if (inet_pton(AF_INET6, addr, &rti->prefix) != 1) {
+ syslog(LOG_ERR,
+ "<%s> inet_pton failed for %s",
+ __FUNCTION__, addr);
+ exit(1);
+ }
+#if 0
+ /*
+ * XXX: currently there's no restriction in route information
+ * prefix according to draft-draves-route-selection-01.txt,
+ * however I think the similar restriction be necessary.
+ */
+ MAYHAVE(val64, entbuf, DEF_ADVVALIDLIFETIME);
+ if (IN6_IS_ADDR_MULTICAST(&rti->prefix)) {
+ syslog(LOG_ERR,
+ "<%s> multicast route (%s) must "
+ "not be advertised (IF=%s)",
+ __FUNCTION__, addr, intface);
+ exit(1);
+ }
+ if (IN6_IS_ADDR_LINKLOCAL(&rti->prefix)) {
+ syslog(LOG_NOTICE,
+ "<%s> link-local route (%s) must "
+ "not be advertised on %s",
+ __FUNCTION__, addr, intface);
+ exit(1);
+ }
+#endif
+ }
+
/* okey */
tmp->next = ralist;
ralist = tmp;
@@ -385,33 +547,26 @@ getconfig(intface)
static void
get_prefix(struct rainfo *rai)
{
- size_t len;
- u_char *buf, *lim, *next;
+ struct ifaddrs *ifap, *ifa;
+ struct prefix *pp;
+ struct in6_addr *a;
+ u_char *p, *ep, *m, *lim;
u_char ntopbuf[INET6_ADDRSTRLEN];
- if ((len = rtbuf_len()) < 0) {
+ if (getifaddrs(&ifap) < 0) {
syslog(LOG_ERR,
- "<%s> can't get buffer length for routing info",
+ "<%s> can't get interface addresses",
__FUNCTION__);
exit(1);
}
- if ((buf = malloc(len)) == NULL) {
- syslog(LOG_ERR,
- "<%s> can't allocate buffer", __FUNCTION__);
- exit(1);
- }
- if (get_rtinfo(buf, &len) < 0) {
- syslog(LOG_ERR,
- "<%s> can't get routing inforamtion", __FUNCTION__);
- exit(1);
- }
-
- lim = buf + len;
- next = get_next_msg(buf, lim, rai->ifindex, &len,
- RTADV_TYPE2BITMASK(RTM_GET));
- while (next < lim) {
- struct prefix *pp;
- struct in6_addr *a;
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if (strcmp(ifa->ifa_name, rai->ifname) != 0)
+ continue;
+ if (ifa->ifa_addr->sa_family != AF_INET6)
+ continue;
+ a = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
+ if (IN6_IS_ADDR_LINKLOCAL(a))
+ continue;
/* allocate memory to store prefix info. */
if ((pp = malloc(sizeof(*pp))) == NULL) {
@@ -422,21 +577,35 @@ get_prefix(struct rainfo *rai)
}
memset(pp, 0, sizeof(*pp));
- /* set prefix and its length */
- a = get_addr(next);
- memcpy(&pp->prefix, a, sizeof(*a));
- if ((pp->prefixlen = get_prefixlen(next)) < 0) {
+ /* set prefix length */
+ m = (u_char *)&((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr;
+ lim = (u_char *)(ifa->ifa_netmask) + ifa->ifa_netmask->sa_len;
+ pp->prefixlen = prefixlen(m, lim);
+ if (pp->prefixlen < 0 || pp->prefixlen > 128) {
syslog(LOG_ERR,
"<%s> failed to get prefixlen "
- "or prefixl is invalid",
+ "or prefix is invalid",
__FUNCTION__);
exit(1);
}
+
+ /* set prefix, sweep bits outside of prefixlen */
+ memcpy(&pp->prefix, a, sizeof(*a));
+ p = (u_char *)&pp->prefix;
+ ep = (u_char *)(&pp->prefix + 1);
+ while (m < lim)
+ *p++ &= *m++;
+ while (p < ep)
+ *p++ = 0x00;
+
+ if (!inet_ntop(AF_INET6, &pp->prefix, ntopbuf,
+ sizeof(ntopbuf))) {
+ syslog(LOG_ERR, "<%s> inet_ntop failed", __FUNCTION__);
+ exit(1);
+ }
syslog(LOG_DEBUG,
"<%s> add %s/%d to prefix list on %s",
- __FUNCTION__,
- inet_ntop(AF_INET6, a, ntopbuf, INET6_ADDRSTRLEN),
- pp->prefixlen, rai->ifname);
+ __FUNCTION__, ntopbuf, pp->prefixlen, rai->ifname);
/* set other fields with protocol defaults */
pp->validlifetime = DEF_ADVVALIDLIFETIME;
@@ -450,14 +619,9 @@ get_prefix(struct rainfo *rai)
/* counter increment */
rai->pfxs++;
-
- /* forward pointer and get next prefix(if any) */
- next += len;
- next = get_next_msg(next, lim, rai->ifindex,
- &len, RTADV_TYPE2BITMASK(RTM_GET));
}
- free(buf);
+ freeifaddrs(ifap);
}
static void
@@ -493,6 +657,7 @@ add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr)
__FUNCTION__);
return; /* XXX: error or exit? */
}
+ memset(prefix, 0, sizeof(*prefix));
prefix->prefix = ipr->ipr_prefix.sin6_addr;
prefix->prefixlen = ipr->ipr_plen;
prefix->validlifetime = ipr->ipr_vltime;
@@ -510,7 +675,7 @@ add_prefix(struct rainfo *rai, struct in6_prefixreq *ipr)
/* free the previous packet */
free(rai->ra_data);
- rai->ra_data = 0;
+ rai->ra_data = NULL;
/* reconstruct the packet */
rai->pfxs++;
@@ -617,10 +782,12 @@ make_packet(struct rainfo *rainfo)
struct nd_opt_prefix_info *ndopt_pi;
struct nd_opt_mtu *ndopt_mtu;
#ifdef MIP6
- struct nd_opt_advint *ndopt_advint;
- struct nd_opt_hai *ndopt_hai;
+ struct nd_opt_advinterval *ndopt_advint;
+ struct nd_opt_homeagent_info *ndopt_hai;
#endif
+ struct nd_opt_route_info *ndopt_rti;
struct prefix *pfx;
+ struct rtinfo *rti;
/* calculate total length */
packlen = sizeof(struct nd_router_advert);
@@ -641,9 +808,14 @@ make_packet(struct rainfo *rainfo)
packlen += sizeof(struct nd_opt_mtu);
#ifdef MIP6
if (mobileip6 && rainfo->maxinterval)
- packlen += sizeof(struct nd_opt_advint);
+ packlen += sizeof(struct nd_opt_advinterval);
if (mobileip6 && rainfo->hatime)
- packlen += sizeof(struct nd_opt_hai);
+ packlen += sizeof(struct nd_opt_homeagent_info);
+#endif
+#ifdef ND_OPT_ROUTE_INFO
+ for (rti = rainfo->route.next; rti != &rainfo->route; rti = rti->next)
+ packlen += sizeof(struct nd_opt_route_info) +
+ ((rti->prefixlen + 0x3f) >> 6) * 8;
#endif
/* allocate memory for the packet */
@@ -653,6 +825,11 @@ make_packet(struct rainfo *rainfo)
__FUNCTION__);
exit(1);
}
+ if (rainfo->ra_data) {
+ /* free the previous packet */
+ free(rainfo->ra_data);
+ rainfo->ra_data = NULL;
+ }
rainfo->ra_data = buf;
/* XXX: what if packlen > 576? */
rainfo->ra_datalen = packlen;
@@ -665,7 +842,12 @@ make_packet(struct rainfo *rainfo)
ra->nd_ra_code = 0;
ra->nd_ra_cksum = 0;
ra->nd_ra_curhoplimit = (u_int8_t)(0xff & rainfo->hoplimit);
- ra->nd_ra_flags_reserved = 0;
+ ra->nd_ra_flags_reserved = 0; /* just in case */
+ /*
+ * XXX: the router preference field, which is a 2-bit field, should be
+ * initialized before other fields.
+ */
+ ra->nd_ra_flags_reserved = 0xff & rainfo->rtpref;
ra->nd_ra_flags_reserved |=
rainfo->managedflg ? ND_RA_FLAG_MANAGED : 0;
ra->nd_ra_flags_reserved |=
@@ -689,36 +871,39 @@ make_packet(struct rainfo *rainfo)
ndopt_mtu->nd_opt_mtu_type = ND_OPT_MTU;
ndopt_mtu->nd_opt_mtu_len = 1;
ndopt_mtu->nd_opt_mtu_reserved = 0;
- ndopt_mtu->nd_opt_mtu_mtu = ntohl(rainfo->linkmtu);
+ ndopt_mtu->nd_opt_mtu_mtu = htonl(rainfo->linkmtu);
buf += sizeof(struct nd_opt_mtu);
}
#ifdef MIP6
if (mobileip6 && rainfo->maxinterval) {
- ndopt_advint = (struct nd_opt_advint *)buf;
- ndopt_advint->nd_opt_int_type = ND_OPT_ADV_INTERVAL;
- ndopt_advint->nd_opt_int_len = 1;
- ndopt_advint->nd_opt_int_reserved = 0;
- ndopt_advint->nd_opt_int_interval = ntohl(rainfo->maxinterval *
+ ndopt_advint = (struct nd_opt_advinterval *)buf;
+ ndopt_advint->nd_opt_adv_type = ND_OPT_ADVINTERVAL;
+ ndopt_advint->nd_opt_adv_len = 1;
+ ndopt_advint->nd_opt_adv_reserved = 0;
+ ndopt_advint->nd_opt_adv_interval = htonl(rainfo->maxinterval *
1000);
- buf += sizeof(struct nd_opt_advint);
+ buf += sizeof(struct nd_opt_advinterval);
}
#endif
#ifdef MIP6
if (rainfo->hatime) {
- ndopt_hai = (struct nd_opt_hai *)buf;
- ndopt_hai->nd_opt_hai_type = ND_OPT_HA_INFORMATION;
+ ndopt_hai = (struct nd_opt_homeagent_info *)buf;
+ ndopt_hai->nd_opt_hai_type = ND_OPT_HOMEAGENT_INFO;
ndopt_hai->nd_opt_hai_len = 1;
ndopt_hai->nd_opt_hai_reserved = 0;
- ndopt_hai->nd_opt_hai_pref = ntohs(rainfo->hapref);
- ndopt_hai->nd_opt_hai_lifetime = ntohs(rainfo->hatime);
- buf += sizeof(struct nd_opt_hai);
+ ndopt_hai->nd_opt_hai_preference = htons(rainfo->hapref);
+ ndopt_hai->nd_opt_hai_lifetime = htons(rainfo->hatime);
+ buf += sizeof(struct nd_opt_homeagent_info);
}
#endif
for (pfx = rainfo->prefix.next;
pfx != &rainfo->prefix; pfx = pfx->next) {
+ u_int32_t vltime, pltime;
+ struct timeval now;
+
ndopt_pi = (struct nd_opt_prefix_info *)buf;
ndopt_pi->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
ndopt_pi->nd_opt_pi_len = 4;
@@ -733,16 +918,69 @@ make_packet(struct rainfo *rainfo)
#ifdef MIP6
if (pfx->routeraddr)
ndopt_pi->nd_opt_pi_flags_reserved |=
- ND_OPT_PI_FLAG_RTADDR;
+ ND_OPT_PI_FLAG_ROUTER;
#endif
- ndopt_pi->nd_opt_pi_valid_time = ntohl(pfx->validlifetime);
- ndopt_pi->nd_opt_pi_preferred_time =
- ntohl(pfx->preflifetime);
+ if (pfx->vltimeexpire || pfx->pltimeexpire)
+ gettimeofday(&now, NULL);
+ if (pfx->vltimeexpire == 0)
+ vltime = pfx->validlifetime;
+ else
+ vltime = (pfx->vltimeexpire > now.tv_sec) ?
+ pfx->vltimeexpire - now.tv_sec : 0;
+ if (pfx->pltimeexpire == 0)
+ pltime = pfx->preflifetime;
+ else
+ pltime = (pfx->pltimeexpire > now.tv_sec) ?
+ pfx->pltimeexpire - now.tv_sec : 0;
+ if (vltime < pltime) {
+ /*
+ * this can happen if vltime is decrement but pltime
+ * is not.
+ */
+ pltime = vltime;
+ }
+ ndopt_pi->nd_opt_pi_valid_time = htonl(vltime);
+ ndopt_pi->nd_opt_pi_preferred_time = htonl(pltime);
ndopt_pi->nd_opt_pi_reserved2 = 0;
ndopt_pi->nd_opt_pi_prefix = pfx->prefix;
buf += sizeof(struct nd_opt_prefix_info);
}
+#ifdef ND_OPT_ROUTE_INFO
+ for (rti = rainfo->route.next; rti != &rainfo->route; rti = rti->next) {
+ u_int8_t psize = (rti->prefixlen + 0x3f) >> 6;
+
+ ndopt_rti = (struct nd_opt_route_info *)buf;
+ ndopt_rti->nd_opt_rti_type = ND_OPT_ROUTE_INFO;
+ ndopt_rti->nd_opt_rti_len = 1 + psize;
+ ndopt_rti->nd_opt_rti_prefixlen = rti->prefixlen;
+ ndopt_rti->nd_opt_rti_flags = 0xff & rti->rtpref;
+ ndopt_rti->nd_opt_rti_lifetime = rti->ltime;
+ memcpy(ndopt_rti + 1, &rti->prefix, psize * 8);
+ buf += sizeof(struct nd_opt_route_info) + psize * 8;
+ }
+#endif
+
return;
}
+
+static int
+getinet6sysctl(int code)
+{
+ int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, 0 };
+ int value;
+ size_t size;
+
+ mib[3] = code;
+ size = sizeof(value);
+ if (sysctl(mib, sizeof(mib)/sizeof(mib[0]), &value, &size, NULL, 0)
+ < 0) {
+ syslog(LOG_ERR, "<%s>: failed to get ip6 sysctl(%d): %s",
+ __FUNCTION__, code,
+ strerror(errno));
+ return(-1);
+ }
+ else
+ return(value);
+}
OpenPOWER on IntegriCloud