From owner-svn-src-user@FreeBSD.ORG Mon May 30 18:36:15 2011 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 407EA1065670; Mon, 30 May 2011 18:36:15 +0000 (UTC) (envelope-from hrs@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2F6C48FC0C; Mon, 30 May 2011 18:36:15 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p4UIaFR6088643; Mon, 30 May 2011 18:36:15 GMT (envelope-from hrs@svn.freebsd.org) Received: (from hrs@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p4UIaFR7088637; Mon, 30 May 2011 18:36:15 GMT (envelope-from hrs@svn.freebsd.org) Message-Id: <201105301836.p4UIaFR7088637@svn.freebsd.org> From: Hiroki Sato Date: Mon, 30 May 2011 18:36:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r222504 - user/hrs/ipv6/usr.sbin/rtsold X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 30 May 2011 18:36:15 -0000 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 #include #include +#include #include #include @@ -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 ***