summaryrefslogtreecommitdiffstats
path: root/usr.sbin
diff options
context:
space:
mode:
authorhrs <hrs@FreeBSD.org>2011-05-30 18:36:14 +0000
committerhrs <hrs@FreeBSD.org>2011-05-30 18:36:14 +0000
commit3644d505b2da182f8f50471889aa0d3ade50cfff (patch)
tree2034ad01f8f7f9da91646d5b616f5cf44fdfa005 /usr.sbin
parent512c7bb8e59bf37585e63f3600f8ebf483a04ccd (diff)
downloadFreeBSD-src-3644d505b2da182f8f50471889aa0d3ade50cfff.zip
FreeBSD-src-3644d505b2da182f8f50471889aa0d3ade50cfff.tar.gz
- Add initial support for expiration timer for RNDSS and DNSSL options.
- Use queue(3) for the interface list. - Separate a list to one for RA options and another for resolvconf(8) string. - Remove SCOPE_DELIM hack. resolvconf(8) has to be corrected.
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/rtsold/dump.c37
-rw-r--r--usr.sbin/rtsold/rtsol.c293
-rw-r--r--usr.sbin/rtsold/rtsold.c194
-rw-r--r--usr.sbin/rtsold/rtsold.h43
4 files changed, 319 insertions, 248 deletions
diff --git a/usr.sbin/rtsold/dump.c b/usr.sbin/rtsold/dump.c
index e9a07db..2e6b4ca 100644
--- a/usr.sbin/rtsold/dump.c
+++ b/usr.sbin/rtsold/dump.c
@@ -34,6 +34,7 @@
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
+#include <sys/queue.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -58,41 +59,41 @@ static const char * const ifstatstr[] = {"IDLE", "DELAY", "PROBE", "DOWN", "TENT
static void
dump_interface_status(void)
{
- struct ifinfo *ifinfo;
+ struct ifinfo *ifi;
struct timeval now;
gettimeofday(&now, NULL);
- for (ifinfo = iflist; ifinfo; ifinfo = ifinfo->next) {
- fprintf(fp, "Interface %s\n", ifinfo->ifname);
+ TAILQ_FOREACH(ifi, &ifinfo_head, ifi_next) {
+ fprintf(fp, "Interface %s\n", ifi->ifname);
fprintf(fp, " probe interval: ");
- if (ifinfo->probeinterval) {
- fprintf(fp, "%d\n", ifinfo->probeinterval);
- fprintf(fp, " probe timer: %d\n", ifinfo->probetimer);
+ if (ifi->probeinterval) {
+ fprintf(fp, "%d\n", ifi->probeinterval);
+ fprintf(fp, " probe timer: %d\n", ifi->probetimer);
} else {
fprintf(fp, "infinity\n");
fprintf(fp, " no probe timer\n");
}
fprintf(fp, " interface status: %s\n",
- ifinfo->active > 0 ? "active" : "inactive");
+ ifi->active > 0 ? "active" : "inactive");
fprintf(fp, " other config: %s\n",
- ifinfo->otherconfig ? "on" : "off");
- fprintf(fp, " rtsold status: %s\n", ifstatstr[ifinfo->state]);
+ ifi->otherconfig ? "on" : "off");
+ fprintf(fp, " rtsold status: %s\n", ifstatstr[ifi->state]);
fprintf(fp, " carrier detection: %s\n",
- ifinfo->mediareqok ? "available" : "unavailable");
+ ifi->mediareqok ? "available" : "unavailable");
fprintf(fp, " probes: %d, dadcount = %d\n",
- ifinfo->probes, ifinfo->dadcount);
- if (ifinfo->timer.tv_sec == tm_max.tv_sec &&
- ifinfo->timer.tv_usec == tm_max.tv_usec)
+ ifi->probes, ifi->dadcount);
+ if (ifi->timer.tv_sec == tm_max.tv_sec &&
+ ifi->timer.tv_usec == tm_max.tv_usec)
fprintf(fp, " no timer\n");
else {
fprintf(fp, " timer: interval=%d:%d, expire=%s\n",
- (int)ifinfo->timer.tv_sec,
- (int)ifinfo->timer.tv_usec,
- (ifinfo->expire.tv_sec < now.tv_sec) ? "expired"
- : sec2str(ifinfo->expire.tv_sec - now.tv_sec));
+ (int)ifi->timer.tv_sec,
+ (int)ifi->timer.tv_usec,
+ (ifi->expire.tv_sec < now.tv_sec) ? "expired"
+ : sec2str(ifi->expire.tv_sec - now.tv_sec));
}
- fprintf(fp, " number of valid RAs: %d\n", ifinfo->racnt);
+ fprintf(fp, " number of valid RAs: %d\n", ifi->racnt);
}
}
diff --git a/usr.sbin/rtsold/rtsol.c b/usr.sbin/rtsold/rtsol.c
index f2c8a17..02659c8 100644
--- a/usr.sbin/rtsold/rtsol.c
+++ b/usr.sbin/rtsold/rtsol.c
@@ -71,51 +71,38 @@ static struct sockaddr_in6 from;
static int rcvcmsglen;
int rssock;
-/*
- * RFC 3542 API deprecates IPV6_PKTINFO in favor of
- * IPV6_RECVPKTINFO
- */
-#ifndef IPV6_RECVPKTINFO
-#ifdef IPV6_PKTINFO
-#define IPV6_RECVPKTINFO IPV6_PKTINFO
-#endif
-#endif
-/*
- * RFC 3542 API deprecates IPV6_HOPLIMIT in favor of
- * IPV6_RECVHOPLIMIT
- */
-#ifndef IPV6_RECVHOPLIMIT
-#ifdef IPV6_HOPLIMIT
-#define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
-#endif
-#endif
-
-#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \
- {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}}
+struct ifinfo_head_t ifinfo_head =
+ TAILQ_HEAD_INITIALIZER(ifinfo_head);
+
static const struct sockaddr_in6 sin6_allrouters = {
.sin6_len = sizeof(sin6_allrouters),
.sin6_family = AF_INET6,
.sin6_addr = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT,
};
-struct script_msg {
- TAILQ_ENTRY(script_msg) sm_next;
-
- char *sm_msg;
-};
-
static void call_script(const int, const char *const *, void *);
static size_t dname_labeldec(char *, const char *);
static int safefile(const char *);
+static int ra_opt_handler(struct ifinfo *);
#define _ARGS_OTHER otherconf_script, ifi->ifname
-#define _ARGS_RESCONF resolvconf_script, "-a", ifi->ifname
-#define CALL_SCRIPT(name, sm_head) \
- do { \
+#define _ARGS_RESADD resolvconf_script, "-a", ifi->ifname
+#define _ARGS_RESDEL resolvconf_script, "-d", ifi->ifname
+#define CALL_SCRIPT(name, sm_head) \
+ do { \
const char *const sarg[] = { _ARGS_##name, NULL }; \
call_script(sizeof(sarg), sarg, sm_head); \
} while(0);
+#define ELM_MALLOC(p,error_action) \
+ do { \
+ p = malloc(sizeof(*p)); \
+ if (p == NULL) { \
+ warnmsg(LOG_ERR, __func__, "malloc failed: %s", \
+ strerror(errno)); \
+ error_action; \
+ } \
+ memset(p, 0, sizeof(*p)); \
+ } while(0);
int
sockopen(void)
@@ -189,7 +176,7 @@ sockopen(void)
}
void
-sendpacket(struct ifinfo *ifinfo)
+sendpacket(struct ifinfo *ifi)
{
struct in6_pktinfo *pi;
struct cmsghdr *cm;
@@ -198,11 +185,11 @@ sendpacket(struct ifinfo *ifinfo)
struct sockaddr_in6 dst;
dst = sin6_allrouters;
- dst.sin6_scope_id = ifinfo->linkid;
+ dst.sin6_scope_id = ifi->linkid;
sndmhdr.msg_name = (caddr_t)&dst;
- sndmhdr.msg_iov[0].iov_base = (caddr_t)ifinfo->rs_data;
- sndmhdr.msg_iov[0].iov_len = ifinfo->rs_datalen;
+ sndmhdr.msg_iov[0].iov_base = (caddr_t)ifi->rs_data;
+ sndmhdr.msg_iov[0].iov_len = ifi->rs_datalen;
cm = CMSG_FIRSTHDR(&sndmhdr);
/* specify the outgoing interface */
@@ -211,7 +198,7 @@ sendpacket(struct ifinfo *ifinfo)
cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
pi = (struct in6_pktinfo *)CMSG_DATA(cm);
memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr)); /*XXX*/
- pi->ipi6_ifindex = ifinfo->sdl->sdl_index;
+ pi->ipi6_ifindex = ifi->sdl->sdl_index;
/* specify the hop limit of the packet */
cm = CMSG_NXTHDR(&sndmhdr, cm);
@@ -222,20 +209,20 @@ sendpacket(struct ifinfo *ifinfo)
warnmsg(LOG_DEBUG, __func__,
"send RS on %s, whose state is %d",
- ifinfo->ifname, ifinfo->state);
+ ifi->ifname, ifi->state);
i = sendmsg(rssock, &sndmhdr, 0);
- if (i < 0 || (size_t)i != ifinfo->rs_datalen) {
+ if (i < 0 || (size_t)i != ifi->rs_datalen) {
/*
* ENETDOWN is not so serious, especially when using several
* network cards on a mobile node. We ignore it.
*/
if (errno != ENETDOWN || dflag > 0)
warnmsg(LOG_ERR, __func__, "sendmsg on %s: %s",
- ifinfo->ifname, strerror(errno));
+ ifi->ifname, strerror(errno));
}
/* update counter */
- ifinfo->probes++;
+ ifi->probes++;
}
void
@@ -246,6 +233,7 @@ rtsol_input(int s)
ssize_t msglen;
struct in6_pktinfo *pi = NULL;
struct ifinfo *ifi = NULL;
+ struct ra_opt *rao = NULL;
struct icmp6_hdr *icp;
struct nd_router_advert *nd_ra;
struct cmsghdr *cm;
@@ -256,16 +244,13 @@ rtsol_input(int s)
struct nd_opt_rdnss *rdnss;
struct nd_opt_dnssl *dnssl;
size_t len;
- struct script_msg *smp;
- TAILQ_HEAD(, script_msg) sm_ns_head =
- TAILQ_HEAD_INITIALIZER(sm_ns_head);
char nsbuf[11 + INET6_ADDRSTRLEN + 1 + IFNAMSIZ + 1 + 1];
/* 11 = sizeof("nameserver "), 1+1 = \n\0 termination */
- TAILQ_HEAD(, script_msg) sm_sl_head =
- TAILQ_HEAD_INITIALIZER(sm_sl_head);
char slbuf[7 + NI_MAXHOST + 1 + 1];
/* 7 = sizeof("search "), 1+1 = \n\0 termination */
char dname[NI_MAXHOST + 1];
+ struct timeval now;
+ struct timeval lifetime;
/* get message. namelen and controllen must always be initialized. */
rcvmhdr.msg_namelen = sizeof(from);
@@ -387,6 +372,20 @@ rtsol_input(int s)
(((struct nd_opt_hdr *)x)->nd_opt_len * 8))
raoptp = (char *)icp + sizeof(struct nd_router_advert);
+ /* Initialize ra_opt per-interface structure. */
+ gettimeofday(&now, NULL);
+ if (!TAILQ_EMPTY(&ifi->ifi_ra_opt)) {
+ struct ra_opt *rao_tmp;
+
+ rao = TAILQ_FIRST(&ifi->ifi_ra_opt);
+ while (rao != NULL) {
+ rao_tmp = TAILQ_NEXT(rao, rao_next);
+ free(rao);
+ rao = rao_tmp;
+ }
+ } else
+ TAILQ_INIT(&ifi->ifi_ra_opt);
+
warnmsg(LOG_DEBUG, __func__, "Processing RA");
/* Process RA options. */
while (raoptp < (char *)icp + msglen) {
@@ -399,10 +398,7 @@ rtsol_input(int s)
switch (ndo->nd_opt_type) {
case ND_OPT_RDNSS:
- if (resolvconf_script == NULL)
- break;
rdnss = (struct nd_opt_rdnss *)raoptp;
- /* XXX: no lifetime handling now */
addr = (struct in6_addr *)(raoptp + sizeof(*rdnss));
while ((char *)addr < (char *)RA_OPT_NEXT_HDR(raoptp)) {
@@ -418,65 +414,38 @@ rtsol_input(int s)
}
if (IN6_IS_ADDR_LINKLOCAL(addr))
/* XXX: % has to be escaped here */
- sprintf(nsbuf, "nameserver "
- "%s%c%c%c%c%s\n",
+ sprintf(nsbuf, "%s%c%s",
ntopbuf,
SCOPE_DELIMITER,
- SCOPE_DELIMITER,
- SCOPE_DELIMITER,
- SCOPE_DELIMITER,
ifi->ifname);
else
- sprintf(nsbuf, "nameserver %s\n",
- ntopbuf);
+ sprintf(nsbuf, "%s", ntopbuf);
warnmsg(LOG_DEBUG, __func__, "nsbuf = %s",
nsbuf);
- smp = malloc(sizeof(*smp));
- if (smp == NULL) {
- warnmsg(LOG_ERR, __func__,
- "malloc failed: %s",
- strerror(errno));
- continue;
- }
- memset(smp, 0, sizeof(*smp));
- smp->sm_msg = strdup(nsbuf);
- if (smp->sm_msg == NULL) {
+ ELM_MALLOC(rao, break);
+ rao->rao_type = ndo->nd_opt_type;
+ rao->rao_len = strlen(nsbuf);
+ rao->rao_msg = strdup(nsbuf);
+ if (rao->rao_msg == NULL) {
warnmsg(LOG_ERR, __func__,
"strdup failed: %s",
strerror(errno));
- free(smp);
+ free(rao);
continue;
}
- TAILQ_INSERT_TAIL(&sm_ns_head, smp, sm_next);
+ /* Set expiration timer */
+ memset(&rao->rao_expire, 0, sizeof(rao->rao_expire));
+ memset(&lifetime, 0, sizeof(lifetime));
+ lifetime.tv_sec = ntohl(rdnss->nd_opt_rdnss_lifetime);
+ timeradd(&now, &lifetime, &rao->rao_expire);
+
+ TAILQ_INSERT_TAIL(&ifi->ifi_ra_opt, rao, rao_next);
addr++;
}
break;
case ND_OPT_DNSSL:
- if (resolvconf_script == NULL)
- break;
dnssl = (struct nd_opt_dnssl *)raoptp;
- /* XXX: no lifetime handling now */
-
- if (TAILQ_EMPTY(&sm_sl_head)) {
- smp = malloc(sizeof(*smp));
- if (smp == NULL) {
- warnmsg(LOG_ERR, __func__,
- "malloc failed: %s",
- strerror(errno));
- break;
- }
- smp = malloc(sizeof(*smp));
- smp->sm_msg = strdup("search ");
- if (smp->sm_msg == NULL) {
- warnmsg(LOG_ERR, __func__,
- "strdup failed: %s",
- strerror(errno));
- free(smp);
- break;
- }
- TAILQ_INSERT_TAIL(&sm_sl_head, smp, sm_next);
- }
p = raoptp + sizeof(*dnssl);
while (0 < (len = dname_labeldec(dname, p))) {
@@ -484,23 +453,24 @@ rtsol_input(int s)
warnmsg(LOG_DEBUG, __func__, "slbuf = %s",
slbuf);
- smp = malloc(sizeof(*smp));
- if (smp == NULL) {
- warnmsg(LOG_ERR, __func__,
- "malloc failed: %s",
- strerror(errno));
- break;
- }
- memset(smp, 0, sizeof(*smp));
- smp->sm_msg = strdup(slbuf);
- if (smp->sm_msg == NULL) {
+ ELM_MALLOC(rao, break);
+ rao->rao_type = ndo->nd_opt_type;
+ rao->rao_len = strlen(nsbuf);
+ rao->rao_msg = strdup(slbuf);
+ if (rao->rao_msg == NULL) {
warnmsg(LOG_ERR, __func__,
"strdup failed: %s",
strerror(errno));
- free(smp);
+ free(rao);
break;
}
- TAILQ_INSERT_TAIL(&sm_sl_head, smp, sm_next);
+ /* Set expiration timer */
+ memset(&rao->rao_expire, 0, sizeof(rao->rao_expire));
+ memset(&lifetime, 0, sizeof(lifetime));
+ lifetime.tv_sec = ntohl(dnssl->nd_opt_dnssl_lifetime);
+ timeradd(&now, &lifetime, &rao->rao_expire);
+
+ TAILQ_INSERT_TAIL(&ifi->ifi_ra_opt, rao, rao_next);
p += len;
}
break;
@@ -510,37 +480,7 @@ rtsol_input(int s)
}
raoptp = (char *)RA_OPT_NEXT_HDR(raoptp);
}
- if (!TAILQ_EMPTY(&sm_sl_head)) {
- smp = malloc(sizeof(*smp));
- if (smp == NULL) {
- warnmsg(LOG_ERR, __func__, "malloc failed: %s",
- strerror(errno));
- return;
- }
- smp = malloc(sizeof(*smp));
- smp->sm_msg = strdup("\n");
- if (smp->sm_msg == NULL) {
- warnmsg(LOG_ERR, __func__, "strdup failed: %s",
- strerror(errno));
- free(smp);
- return;
- }
- TAILQ_INSERT_TAIL(&sm_sl_head, smp, sm_next);
- }
- TAILQ_CONCAT(&sm_ns_head, &sm_sl_head, sm_next);
- if (!TAILQ_EMPTY(&sm_ns_head) || !TAILQ_EMPTY(&sm_sl_head)) {
- struct script_msg *sm_tmp;
-
- CALL_SCRIPT(RESCONF, &sm_ns_head);
-
- /* Clear script message queue. */
- smp = TAILQ_FIRST(&sm_ns_head);
- while(smp != NULL) {
- sm_tmp = TAILQ_NEXT(smp, sm_next);
- free(smp);
- smp = sm_tmp;
- }
- }
+ ra_opt_handler(ifi);
ifi->racnt++;
switch (ifi->state) {
@@ -555,6 +495,93 @@ rtsol_input(int s)
}
}
+static char resstr_ns_prefix[] = "nameserver ";
+static char resstr_sh_prefix[] = "search ";
+static char resstr_nl[] = "\n";
+
+static int
+ra_opt_handler(struct ifinfo *ifi)
+{
+ struct ra_opt *rao;
+ struct script_msg *smp;
+ struct timeval now;
+ TAILQ_HEAD(, script_msg) sm_rdnss_head =
+ TAILQ_HEAD_INITIALIZER(sm_rdnss_head);
+ TAILQ_HEAD(, script_msg) sm_dnssl_head =
+ TAILQ_HEAD_INITIALIZER(sm_dnssl_head);
+
+ gettimeofday(&now, NULL);
+ TAILQ_FOREACH(rao, &ifi->ifi_ra_opt, rao_next) {
+ switch (rao->rao_type) {
+ case ND_OPT_RDNSS:
+ if (timercmp(&now, &rao->rao_expire, >)) {
+ warnmsg(LOG_INFO, __func__,
+ "expired rdnss entry: %s",
+ (char *)rao->rao_msg);
+ break;
+ }
+ ELM_MALLOC(smp, continue);
+ smp->sm_msg = resstr_ns_prefix;
+ TAILQ_INSERT_TAIL(&sm_rdnss_head, smp, sm_next);
+
+ ELM_MALLOC(smp, continue);
+ smp->sm_msg = rao->rao_msg;
+ TAILQ_INSERT_TAIL(&sm_rdnss_head, smp, sm_next);
+
+ ELM_MALLOC(smp, continue);
+ smp->sm_msg = resstr_nl;
+ TAILQ_INSERT_TAIL(&sm_rdnss_head, smp, sm_next);
+
+ break;
+ case ND_OPT_DNSSL:
+ if (timercmp(&now, &rao->rao_expire, >)) {
+ warnmsg(LOG_INFO, __func__,
+ "expired dnssl entry: %s",
+ (char *)rao->rao_msg);
+ break;
+ }
+ if (TAILQ_EMPTY(&sm_dnssl_head)) {
+ ELM_MALLOC(smp, continue);
+ smp->sm_msg = resstr_sh_prefix;
+ TAILQ_INSERT_TAIL(&sm_dnssl_head, smp, sm_next);
+ }
+ ELM_MALLOC(smp, continue);
+ smp->sm_msg = rao->rao_msg;
+ TAILQ_INSERT_TAIL(&sm_dnssl_head, smp, sm_next);
+ break;
+ default:
+ break;
+ }
+ }
+ /* Add \n for DNSSL list. */
+ if (!TAILQ_EMPTY(&sm_dnssl_head)) {
+ ELM_MALLOC(smp, goto ra_opt_handler_freeit);
+ smp->sm_msg = resstr_nl;
+ TAILQ_INSERT_TAIL(&sm_dnssl_head, smp, sm_next);
+ }
+ TAILQ_CONCAT(&sm_rdnss_head, &sm_dnssl_head, sm_next);
+
+ if (!TAILQ_EMPTY(&sm_rdnss_head)) {
+ CALL_SCRIPT(RESADD, &sm_rdnss_head);
+ } else {
+ CALL_SCRIPT(RESDEL, NULL);
+ }
+
+ra_opt_handler_freeit:
+ /* Clear script message queue. */
+ if (!TAILQ_EMPTY(&sm_rdnss_head)) {
+ struct script_msg *sm_tmp;
+
+ smp = TAILQ_FIRST(&sm_rdnss_head);
+ while(smp != NULL) {
+ sm_tmp = TAILQ_NEXT(smp, sm_next);
+ free(smp);
+ smp = sm_tmp;
+ }
+ }
+ return (0);
+}
+
static void
call_script(const int argc, const char *const argv[], void *head)
{
diff --git a/usr.sbin/rtsold/rtsold.c b/usr.sbin/rtsold/rtsold.c
index 0346da3..42768b5 100644
--- a/usr.sbin/rtsold/rtsold.c
+++ b/usr.sbin/rtsold/rtsold.c
@@ -92,6 +92,7 @@ const char *resolvconf_script = "/sbin/resolvconf";
/* static variables and functions */
static int mobile_node = 0;
static const char *pidfilename = RTSOL_PIDFILE;
+
#ifndef SMALL
static int do_dump;
static const char *dumpfilename = RTSOL_DUMPFILE;
@@ -100,6 +101,7 @@ static const char *dumpfilename = RTSOL_DUMPFILE;
#if 0
static int ifreconfig(char *);
#endif
+
static int make_packet(struct ifinfo *);
static struct timeval *rtsol_check_timer(void);
@@ -338,7 +340,7 @@ main(int argc, char **argv)
break;
/* if all interfaces have got RA packet, we are done */
- for (ifi = iflist; ifi; ifi = ifi->next) {
+ TAILQ_FOREACH(ifi, &ifinfo_head, ifi_next) {
if (ifi->state != IFS_DOWN && ifi->racnt == 0)
break;
}
@@ -380,7 +382,7 @@ main(int argc, char **argv)
int
ifconfig(char *ifname)
{
- struct ifinfo *ifinfo;
+ struct ifinfo *ifi;
struct sockaddr_dl *sdl;
int flags;
@@ -396,80 +398,78 @@ ifconfig(char *ifname)
return (-1);
}
- if ((ifinfo = malloc(sizeof(*ifinfo))) == NULL) {
+ if ((ifi = malloc(sizeof(*ifi))) == NULL) {
warnmsg(LOG_ERR, __func__, "memory allocation failed");
free(sdl);
return (-1);
}
- memset(ifinfo, 0, sizeof(*ifinfo));
- ifinfo->sdl = sdl;
+ memset(ifi, 0, sizeof(*ifi));
+ ifi->sdl = sdl;
- strlcpy(ifinfo->ifname, ifname, sizeof(ifinfo->ifname));
+ strlcpy(ifi->ifname, ifname, sizeof(ifi->ifname));
/* construct a router solicitation message */
- if (make_packet(ifinfo))
+ if (make_packet(ifi))
goto bad;
/* set link ID of this interface. */
#ifdef HAVE_SCOPELIB
- if (inet_zoneid(AF_INET6, 2, ifname, &ifinfo->linkid))
+ if (inet_zoneid(AF_INET6, 2, ifname, &ifi->linkid))
goto bad;
#else
/* XXX: assume interface IDs as link IDs */
- ifinfo->linkid = ifinfo->sdl->sdl_index;
+ ifi->linkid = ifi->sdl->sdl_index;
#endif
/*
* check if the interface is available.
* also check if SIOCGIFMEDIA ioctl is OK on the interface.
*/
- ifinfo->mediareqok = 1;
- ifinfo->active = interface_status(ifinfo);
- if (!ifinfo->mediareqok) {
+ ifi->mediareqok = 1;
+ ifi->active = interface_status(ifi);
+ if (!ifi->mediareqok) {
/*
* probe routers periodically even if the link status
* does not change.
*/
- ifinfo->probeinterval = PROBE_INTERVAL;
+ ifi->probeinterval = PROBE_INTERVAL;
}
/* activate interface: interface_up returns 0 on success */
- flags = interface_up(ifinfo->ifname);
+ flags = interface_up(ifi->ifname);
if (flags == 0)
- ifinfo->state = IFS_DELAY;
+ ifi->state = IFS_DELAY;
else if (flags == IFS_TENTATIVE)
- ifinfo->state = IFS_TENTATIVE;
+ ifi->state = IFS_TENTATIVE;
else
- ifinfo->state = IFS_DOWN;
+ ifi->state = IFS_DOWN;
- rtsol_timer_update(ifinfo);
-
- /* link into chain */
- if (iflist)
- ifinfo->next = iflist;
- iflist = ifinfo;
+ rtsol_timer_update(ifi);
+ TAILQ_INSERT_TAIL(&ifinfo_head, ifi, ifi_next);
return (0);
bad:
- free(ifinfo->sdl);
- free(ifinfo);
+ free(ifi->sdl);
+ free(ifi);
return (-1);
}
void
iflist_init(void)
{
- struct ifinfo *ifi, *next;
+ struct ifinfo *ifi;
+ struct ifinfo *ifi_tmp;
- for (ifi = iflist; ifi; ifi = next) {
- next = ifi->next;
- if (ifi->sdl)
+ ifi = TAILQ_FIRST(&ifinfo_head);
+ while (ifi != NULL) {
+ if (ifi->sdl != NULL)
free(ifi->sdl);
- if (ifi->rs_data)
+ if (ifi->rs_data != NULL)
free(ifi->rs_data);
+ ifi_tmp = TAILQ_NEXT(ifi, ifi_next);
free(ifi);
- iflist = NULL;
+ ifi = ifi_tmp;
}
}
@@ -481,7 +481,7 @@ ifreconfig(char *ifname)
int rv;
prev = NULL;
- for (ifi = iflist; ifi; ifi = ifi->next) {
+ TAILQ_FOREACH(ifi, &ifinfo_head, ifi_next) {
if (strncmp(ifi->ifname, ifname, sizeof(ifi->ifname)) == 0)
break;
prev = ifi;
@@ -495,6 +495,7 @@ ifreconfig(char *ifname)
free(ifi->rs_data);
free(ifi->sdl);
free(ifi);
+
return (rv);
}
#endif
@@ -504,34 +505,35 @@ find_ifinfo(int ifindex)
{
struct ifinfo *ifi;
- for (ifi = iflist; ifi; ifi = ifi->next)
+ TAILQ_FOREACH(ifi, &ifinfo_head, ifi_next) {
if (ifi->sdl->sdl_index == ifindex)
return (ifi);
+ }
return (NULL);
}
static int
-make_packet(struct ifinfo *ifinfo)
+make_packet(struct ifinfo *ifi)
{
size_t packlen = sizeof(struct nd_router_solicit), lladdroptlen = 0;
struct nd_router_solicit *rs;
char *buf;
- if ((lladdroptlen = lladdropt_length(ifinfo->sdl)) == 0) {
+ if ((lladdroptlen = lladdropt_length(ifi->sdl)) == 0) {
warnmsg(LOG_INFO, __func__,
"link-layer address option has null length"
- " on %s. Treat as not included.", ifinfo->ifname);
+ " on %s. Treat as not included.", ifi->ifname);
}
packlen += lladdroptlen;
- ifinfo->rs_datalen = packlen;
+ ifi->rs_datalen = packlen;
/* allocate buffer */
if ((buf = malloc(packlen)) == NULL) {
warnmsg(LOG_ERR, __func__,
- "memory allocation failed for %s", ifinfo->ifname);
+ "memory allocation failed for %s", ifi->ifname);
return (-1);
}
- ifinfo->rs_data = buf;
+ ifi->rs_data = buf;
/* fill in the message */
rs = (struct nd_router_solicit *)buf;
@@ -543,7 +545,7 @@ make_packet(struct ifinfo *ifinfo)
/* fill in source link-layer address option */
if (lladdroptlen)
- lladdropt_fill(ifinfo->sdl, (struct nd_opt_hdr *)buf);
+ lladdropt_fill(ifi->sdl, (struct nd_opt_hdr *)buf);
return (0);
}
@@ -553,56 +555,56 @@ rtsol_check_timer(void)
{
static struct timeval returnval;
struct timeval now, rtsol_timer;
- struct ifinfo *ifinfo;
+ struct ifinfo *ifi;
int flags;
gettimeofday(&now, NULL);
rtsol_timer = tm_max;
- for (ifinfo = iflist; ifinfo; ifinfo = ifinfo->next) {
- if (timercmp(&ifinfo->expire, &now, <=)) {
+ TAILQ_FOREACH(ifi, &ifinfo_head, ifi_next) {
+ if (timercmp(&ifi->expire, &now, <=)) {
if (dflag > 1)
warnmsg(LOG_DEBUG, __func__,
"timer expiration on %s, "
- "state = %d", ifinfo->ifname,
- ifinfo->state);
+ "state = %d", ifi->ifname,
+ ifi->state);
- switch (ifinfo->state) {
+ switch (ifi->state) {
case IFS_DOWN:
case IFS_TENTATIVE:
/* interface_up returns 0 on success */
- flags = interface_up(ifinfo->ifname);
+ flags = interface_up(ifi->ifname);
if (flags == 0)
- ifinfo->state = IFS_DELAY;
+ ifi->state = IFS_DELAY;
else if (flags == IFS_TENTATIVE)
- ifinfo->state = IFS_TENTATIVE;
+ ifi->state = IFS_TENTATIVE;
else
- ifinfo->state = IFS_DOWN;
+ ifi->state = IFS_DOWN;
break;
case IFS_IDLE:
{
- int oldstatus = ifinfo->active;
+ int oldstatus = ifi->active;
int probe = 0;
- ifinfo->active = interface_status(ifinfo);
+ ifi->active = interface_status(ifi);
- if (oldstatus != ifinfo->active) {
+ if (oldstatus != ifi->active) {
warnmsg(LOG_DEBUG, __func__,
"%s status is changed"
" from %d to %d",
- ifinfo->ifname,
- oldstatus, ifinfo->active);
+ ifi->ifname,
+ oldstatus, ifi->active);
probe = 1;
- ifinfo->state = IFS_DELAY;
- } else if (ifinfo->probeinterval &&
- (ifinfo->probetimer -=
- ifinfo->timer.tv_sec) <= 0) {
+ ifi->state = IFS_DELAY;
+ } else if (ifi->probeinterval &&
+ (ifi->probetimer -=
+ ifi->timer.tv_sec) <= 0) {
/* probe timer expired */
- ifinfo->probetimer =
- ifinfo->probeinterval;
+ ifi->probetimer =
+ ifi->probeinterval;
probe = 1;
- ifinfo->state = IFS_PROBE;
+ ifi->state = IFS_PROBE;
}
/*
@@ -610,33 +612,33 @@ rtsol_check_timer(void)
* status wrt the "other" configuration.
*/
if (probe)
- ifinfo->otherconfig = 0;
+ ifi->otherconfig = 0;
if (probe && mobile_node)
- defrouter_probe(ifinfo);
+ defrouter_probe(ifi);
break;
}
case IFS_DELAY:
- ifinfo->state = IFS_PROBE;
- sendpacket(ifinfo);
+ ifi->state = IFS_PROBE;
+ sendpacket(ifi);
break;
case IFS_PROBE:
- if (ifinfo->probes < MAX_RTR_SOLICITATIONS)
- sendpacket(ifinfo);
+ if (ifi->probes < MAX_RTR_SOLICITATIONS)
+ sendpacket(ifi);
else {
warnmsg(LOG_INFO, __func__,
"No answer after sending %d RSs",
- ifinfo->probes);
- ifinfo->probes = 0;
- ifinfo->state = IFS_IDLE;
+ ifi->probes);
+ ifi->probes = 0;
+ ifi->state = IFS_IDLE;
}
break;
}
- rtsol_timer_update(ifinfo);
+ rtsol_timer_update(ifi);
}
- if (timercmp(&ifinfo->expire, &rtsol_timer, <))
- rtsol_timer = ifinfo->expire;
+ if (timercmp(&ifi->expire, &rtsol_timer, <))
+ rtsol_timer = ifi->expire;
}
if (timercmp(&rtsol_timer, &tm_max, ==)) {
@@ -656,31 +658,31 @@ rtsol_check_timer(void)
}
void
-rtsol_timer_update(struct ifinfo *ifinfo)
+rtsol_timer_update(struct ifinfo *ifi)
{
#define MILLION 1000000
#define DADRETRY 10 /* XXX: adhoc */
long interval;
struct timeval now;
- bzero(&ifinfo->timer, sizeof(ifinfo->timer));
+ bzero(&ifi->timer, sizeof(ifi->timer));
- switch (ifinfo->state) {
+ switch (ifi->state) {
case IFS_DOWN:
case IFS_TENTATIVE:
- if (++ifinfo->dadcount > DADRETRY) {
- ifinfo->dadcount = 0;
- ifinfo->timer.tv_sec = PROBE_INTERVAL;
+ if (++ifi->dadcount > DADRETRY) {
+ ifi->dadcount = 0;
+ ifi->timer.tv_sec = PROBE_INTERVAL;
} else
- ifinfo->timer.tv_sec = 1;
+ ifi->timer.tv_sec = 1;
break;
case IFS_IDLE:
if (mobile_node) {
/* XXX should be configurable */
- ifinfo->timer.tv_sec = 3;
+ ifi->timer.tv_sec = 3;
}
else
- ifinfo->timer = tm_max; /* stop timer(valid?) */
+ ifi->timer = tm_max; /* stop timer(valid?) */
break;
case IFS_DELAY:
#ifndef HAVE_ARC4RANDOM
@@ -688,12 +690,12 @@ rtsol_timer_update(struct ifinfo *ifinfo)
#else
interval = arc4random_uniform(MAX_RTR_SOLICITATION_DELAY * MILLION);
#endif
- ifinfo->timer.tv_sec = interval / MILLION;
- ifinfo->timer.tv_usec = interval % MILLION;
+ ifi->timer.tv_sec = interval / MILLION;
+ ifi->timer.tv_usec = interval % MILLION;
break;
case IFS_PROBE:
- if (ifinfo->probes < MAX_RTR_SOLICITATIONS)
- ifinfo->timer.tv_sec = RTR_SOLICITATION_INTERVAL;
+ if (ifi->probes < MAX_RTR_SOLICITATIONS)
+ ifi->timer.tv_sec = RTR_SOLICITATION_INTERVAL;
else {
/*
* After sending MAX_RTR_SOLICITATIONS solicitations,
@@ -702,30 +704,30 @@ rtsol_timer_update(struct ifinfo *ifinfo)
* the timer value to MAX_RTR_SOLICITATION_DELAY based
* on RFC 2461, Section 6.3.7.
*/
- ifinfo->timer.tv_sec = MAX_RTR_SOLICITATION_DELAY;
+ ifi->timer.tv_sec = MAX_RTR_SOLICITATION_DELAY;
}
break;
default:
warnmsg(LOG_ERR, __func__,
"illegal interface state(%d) on %s",
- ifinfo->state, ifinfo->ifname);
+ ifi->state, ifi->ifname);
return;
}
/* reset the timer */
- if (timercmp(&ifinfo->timer, &tm_max, ==)) {
- ifinfo->expire = tm_max;
+ if (timercmp(&ifi->timer, &tm_max, ==)) {
+ ifi->expire = tm_max;
warnmsg(LOG_DEBUG, __func__,
- "stop timer for %s", ifinfo->ifname);
+ "stop timer for %s", ifi->ifname);
} else {
gettimeofday(&now, NULL);
- timeradd(&now, &ifinfo->timer, &ifinfo->expire);
+ timeradd(&now, &ifi->timer, &ifi->expire);
if (dflag > 1)
warnmsg(LOG_DEBUG, __func__,
- "set timer for %s to %d:%d", ifinfo->ifname,
- (int)ifinfo->timer.tv_sec,
- (int)ifinfo->timer.tv_usec);
+ "set timer for %s to %d:%d", ifi->ifname,
+ (int)ifi->timer.tv_sec,
+ (int)ifi->timer.tv_usec);
}
#undef MILLION
diff --git a/usr.sbin/rtsold/rtsold.h b/usr.sbin/rtsold/rtsold.h
index 2a10192..8964c42 100644
--- a/usr.sbin/rtsold/rtsold.h
+++ b/usr.sbin/rtsold/rtsold.h
@@ -31,8 +31,21 @@
* $FreeBSD$
*/
+struct script_msg {
+ TAILQ_ENTRY(script_msg) sm_next;
+
+ char *sm_msg;
+};
+struct ra_opt {
+ TAILQ_ENTRY(ra_opt) rao_next;
+
+ u_int8_t rao_type;
+ struct timeval rao_expire;
+ size_t rao_len;
+ void *rao_msg;
+};
struct ifinfo {
- struct ifinfo *next; /* pointer to the next interface */
+ TAILQ_ENTRY(ifinfo) ifi_next; /* pointer to the next interface */
struct sockaddr_dl *sdl; /* link-layer address */
char ifname[IF_NAMESIZE]; /* interface name */
@@ -54,6 +67,8 @@ struct ifinfo {
size_t rs_datalen;
u_char *rs_data;
+
+ TAILQ_HEAD(, ra_opt) ifi_ra_opt;
};
/* per interface status */
@@ -63,6 +78,32 @@ struct ifinfo {
#define IFS_DOWN 3
#define IFS_TENTATIVE 4
+/* Interface list */
+extern TAILQ_HEAD(ifinfo_head_t, ifinfo) ifinfo_head;
+
+/*
+ * RFC 3542 API deprecates IPV6_PKTINFO in favor of
+ * IPV6_RECVPKTINFO
+ */
+#ifndef IPV6_RECVPKTINFO
+#ifdef IPV6_PKTINFO
+#define IPV6_RECVPKTINFO IPV6_PKTINFO
+#endif
+#endif
+/*
+ * RFC 3542 API deprecates IPV6_HOPLIMIT in favor of
+ * IPV6_RECVHOPLIMIT
+ */
+#ifndef IPV6_RECVHOPLIMIT
+#ifdef IPV6_HOPLIMIT
+#define IPV6_RECVHOPLIMIT IPV6_HOPLIMIT
+#endif
+#endif
+
+#define IN6ADDR_LINKLOCAL_ALLROUTERS_INIT \
+ {{{ 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }}}
+
/* rtsold.c */
extern struct timeval tm_max;
extern int dflag;
OpenPOWER on IntegriCloud