Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 May 2011 18:36:15 +0000 (UTC)
From:      Hiroki Sato <hrs@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r222504 - user/hrs/ipv6/usr.sbin/rtsold
Message-ID:  <201105301836.p4UIaFR7088637@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hrs
Date: Mon May 30 18:36:14 2011
New Revision: 222504
URL: http://svn.freebsd.org/changeset/base/222504

Log:
  - 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.

Modified:
  user/hrs/ipv6/usr.sbin/rtsold/dump.c
  user/hrs/ipv6/usr.sbin/rtsold/rtsol.c
  user/hrs/ipv6/usr.sbin/rtsold/rtsold.c
  user/hrs/ipv6/usr.sbin/rtsold/rtsold.h

Modified: user/hrs/ipv6/usr.sbin/rtsold/dump.c
==============================================================================
--- user/hrs/ipv6/usr.sbin/rtsold/dump.c	Mon May 30 18:07:35 2011	(r222503)
+++ user/hrs/ipv6/usr.sbin/rtsold/dump.c	Mon May 30 18:36:14 2011	(r222504)
@@ -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[] = 
 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);
 	}
 }
 

Modified: user/hrs/ipv6/usr.sbin/rtsold/rtsol.c
==============================================================================
--- user/hrs/ipv6/usr.sbin/rtsold/rtsol.c	Mon May 30 18:07:35 2011	(r222503)
+++ user/hrs/ipv6/usr.sbin/rtsold/rtsol.c	Mon May 30 18:36:14 2011	(r222504)
@@ -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)
 {

Modified: user/hrs/ipv6/usr.sbin/rtsold/rtsold.c
==============================================================================
--- user/hrs/ipv6/usr.sbin/rtsold/rtsold.c	Mon May 30 18:07:35 2011	(r222503)
+++ user/hrs/ipv6/usr.sbin/rtsold/rtsold.c	Mon May 30 18:36:14 2011	(r222504)
@@ -92,6 +92,7 @@ const char *resolvconf_script = "/sbin/r
 /* 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_
 #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

Modified: user/hrs/ipv6/usr.sbin/rtsold/rtsold.h
==============================================================================
--- user/hrs/ipv6/usr.sbin/rtsold/rtsold.h	Mon May 30 18:07:35 2011	(r222503)
+++ user/hrs/ipv6/usr.sbin/rtsold/rtsold.h	Mon May 30 18:36:14 2011	(r222504)
@@ -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
+ */

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201105301836.p4UIaFR7088637>