Date: Sat, 16 Jul 2011 09:20:23 +0000 (UTC) From: Hiroki Sato <hrs@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r224087 - in user/hrs/ipv6/usr.sbin: rtadvctl rtadvd Message-ID: <201107160920.p6G9KNGi018881@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: hrs Date: Sat Jul 16 09:20:22 2011 New Revision: 224087 URL: http://svn.freebsd.org/changeset/base/224087 Log: - Implement burst unsolicited RA sending by using the ra_timer framework when AdvSendAdvertisements and/or configuration entries are changed as described in RFC 4861 6.2.4. This fixes issues that make termination of the rtadvd daemon take very long time and rtadvctl(8) utility become unresponsive after reloading the configuration file. An interface now has three states, UNCONFIGURED, TRANSITIVE, or CONFIGURED, and the burst unsolicited sending happens only in TRANSITIVE. See rtadvd.h for the details. - Remove extra make_packet(). - rtadvctl(8) now displays the RA timers. Modified: user/hrs/ipv6/usr.sbin/rtadvctl/rtadvctl.8 user/hrs/ipv6/usr.sbin/rtadvctl/rtadvctl.c user/hrs/ipv6/usr.sbin/rtadvd/config.c user/hrs/ipv6/usr.sbin/rtadvd/config.h user/hrs/ipv6/usr.sbin/rtadvd/control_server.c user/hrs/ipv6/usr.sbin/rtadvd/rtadvd.c user/hrs/ipv6/usr.sbin/rtadvd/rtadvd.h user/hrs/ipv6/usr.sbin/rtadvd/timer.c user/hrs/ipv6/usr.sbin/rtadvd/timer_subr.c Modified: user/hrs/ipv6/usr.sbin/rtadvctl/rtadvctl.8 ============================================================================== --- user/hrs/ipv6/usr.sbin/rtadvctl/rtadvctl.8 Sat Jul 16 08:51:09 2011 (r224086) +++ user/hrs/ipv6/usr.sbin/rtadvctl/rtadvctl.8 Sat Jul 16 09:20:22 2011 (r224087) @@ -25,7 +25,7 @@ .\" .\" $FreeBSD$ .\" -.Dd July 15, 2011 +.Dd July 16, 2011 .Dt RTADVCTL 8 .Os .Sh NAME @@ -80,12 +80,17 @@ Specifies to mark the interface as disab .It shutdown Makes the .Xr rtadvd 8 -daemon shut down immediately. +daemon shut down. +Note that the +.Xr rtadvd 8 +daemon will send several RAs with zero lifetime to invalidate the old +information on each interface. +It will take at most nine seconds. .It show Op interfaces... Displays information on Router Advertisement messages being sent on each interface. .Sh SEE ALSO -.Xr rtadv 8 , +.Xr rtadvd 8 , .Xr rtadvd.conf 5 .Sh HISTORY The @@ -96,16 +101,3 @@ command first appeared in .Nm was written by .An "Hiroki Sato" Aq hrs@FreeBSD.org . -.Sh BUGS -The -.Xr rtadvd 8 -daemon stops responding to -.Nm -for a while just after reloading the configuration file by the reload -subcommand. -This is because in the current implementation it cannot communicate -with -.Nm -while sending some additional RAs for graceful transition from one -configuration to another. -It will take at most nine seconds for each interface. Modified: user/hrs/ipv6/usr.sbin/rtadvctl/rtadvctl.c ============================================================================== --- user/hrs/ipv6/usr.sbin/rtadvctl/rtadvctl.c Sat Jul 16 08:51:09 2011 (r224086) +++ user/hrs/ipv6/usr.sbin/rtadvctl/rtadvctl.c Sat Jul 16 09:20:22 2011 (r224087) @@ -61,6 +61,7 @@ #include "rtadvd.h" #include "if.h" #include "timer_subr.h" +#include "timer.h" #include "control.h" #include "control_client.h" @@ -115,6 +116,9 @@ static struct dispatch_table { { NULL, NULL }, }; +static char errmsgbuf[1024]; +static char *errmsg = NULL; + static void mysyslog(int priority, const char * restrict fmt, ...) { @@ -176,13 +180,17 @@ main(int argc, char *argv[]) } } - if (action != NULL) { - error = (dtable[i].dt_act)(--argc, ++argv); - if (error) - fprintf(stderr, "%s failed.\n", dtable[i].dt_comm); - } else + if (action == NULL) usage(); + error = (dtable[i].dt_act)(--argc, ++argv); + if (error) { + fprintf(stderr, "%s failed", dtable[i].dt_comm); + if (errmsg != NULL) + fprintf(stderr, ": %s", errmsg); + fprintf(stderr, ".\n"); + } + return (error); } @@ -312,7 +320,7 @@ action_disable(int argc, char **argv) error += action_propset(action_argv); } - return(error); + return (error); } static int @@ -333,7 +341,7 @@ action_enable(int argc, char **argv) error += action_propset(action_argv); } - return(error); + return (error); } static int @@ -346,7 +354,7 @@ action_reload(int argc, char **argv) if (argc == 0) { action_argv = strdup(":reload="); - return(action_propset(action_argv)); + return (action_propset(action_argv)); } error = 0; @@ -356,7 +364,7 @@ action_reload(int argc, char **argv) error += action_propset(action_argv); } - return(error); + return (error); } static int @@ -365,7 +373,7 @@ action_echo(int argc __unused, char **ar char *action_argv; action_argv = strdup("echo"); - return(action_propset(action_argv)); + return (action_propset(action_argv)); } static int @@ -374,7 +382,7 @@ action_shutdown(int argc __unused, char char *action_argv; action_argv = strdup("shutdown"); - return(action_propset(action_argv)); + return (action_propset(action_argv)); } /* XXX */ @@ -403,6 +411,7 @@ action_show(int argc, char **argv) char argv_rai[IFNAMSIZ + sizeof(":rai=")]; char argv_rti[IFNAMSIZ + sizeof(":rti=")]; char argv_pfx[IFNAMSIZ + sizeof(":pfx=")]; + char argv_ifi_ra_timer[IFNAMSIZ + sizeof(":ifi_ra_timer=")]; char argv_rdnss[IFNAMSIZ + sizeof(":rdnss=")]; char argv_dnssl[IFNAMSIZ + sizeof(":dnssl=")]; char ssbuf[SSBUFLEN]; @@ -427,7 +436,7 @@ action_show(int argc, char **argv) while (p < endp) { ifi = malloc(sizeof(*ifi)); if (ifi == NULL) - exit(1); + return (1); memset(ifi, 0, sizeof(*ifi)); strcpy(ifi->ifi_ifname, p); @@ -439,19 +448,25 @@ action_show(int argc, char **argv) for (i = 0; i < argc; i++) { ifi = malloc(sizeof(*ifi)); if (ifi == NULL) - exit(1); + return (1); memset(ifi, 0, sizeof(*ifi)); strcpy(ifi->ifi_ifname, argv[i]); ifi->ifi_ifindex = if_nametoindex(ifi->ifi_ifname); - if (ifi->ifi_ifindex == 0) - exit(1); + if (ifi->ifi_ifindex == 0) { + sprintf(errmsgbuf, "invalid interface %s", + ifi->ifi_ifname); + errmsg = errmsgbuf; + return (1); + } + TAILQ_INSERT_TAIL(&ifl, ifi, ifi_next); } } TAILQ_FOREACH(ifi, &ifl, ifi_next) { struct ifinfo *ifi_s; + struct rtadvd_timer *rat; struct rainfo *rai; struct rtinfo *rti; struct prefix *pfx; @@ -470,28 +485,33 @@ action_show(int argc, char **argv) printf("%s: flags=<", ifi->ifi_ifname); - /* - * RA_RECV = UP + CONFIGURED + ACCEPT_RTADV - * RA_SEND = UP + CONFIGURED + IPV6FORWARDING - */ - c = 0; if (ifi_s->ifi_ifindex == 0) c += printf("NONEXISTENT"); else c += printf("%s", (ifi_s->ifi_flags & IFF_UP) ? "UP" : "DOWN"); - if (ifi_s->ifi_state == IFI_STATE_CONFIGURED) + switch (ifi_s->ifi_state) { + case IFI_STATE_CONFIGURED: c += printf("%s%s", (c) ? "," : "", "CONFIGURED"); - + break; + case IFI_STATE_TRANSITIVE: + c += printf("%s%s", (c) ? "," : "", "TRANSITIVE"); + break; + } if (ifi_s->ifi_persist) c += printf("%s%s", (c) ? "," : "", "PERSIST"); printf(">"); ra_ifstatus = RA_IFSTATUS_INACTIVE; if ((ifi_s->ifi_flags & IFF_UP) && - (ifi_s->ifi_state == IFI_STATE_CONFIGURED)) { + ((ifi_s->ifi_state == IFI_STATE_CONFIGURED) || + (ifi_s->ifi_state == IFI_STATE_TRANSITIVE))) { #if (__FreeBSD_version < 900000) + /* + * RA_RECV: !ip6.forwarding && ip6.accept_rtadv + * RA_SEND: ip6.forwarding + */ if (getinet6sysctl(IPV6CTL_FORWARDING) == 0) { if (getinet6sysctl(IPV6CTL_ACCEPT_RTADV)) ra_ifstatus = RA_IFSTATUS_RA_RECV; @@ -500,6 +520,10 @@ action_show(int argc, char **argv) } else ra_ifstatus = RA_IFSTATUS_RA_SEND; #else + /* + * RA_RECV: ND6_IFF_ACCEPT_RTADV + * RA_SEND: ip6.forwarding + */ if (ifi_s->ifi_nd_flags & ND6_IFF_ACCEPT_RTADV) ra_ifstatus = RA_IFSTATUS_RA_RECV; else if (getinet6sysctl(IPV6CTL_FORWARDING)) @@ -519,7 +543,11 @@ action_show(int argc, char **argv) printf("%s%s", (c) ? "," : "", "RA_SEND"); printf("> "); - if (ifi_s->ifi_state != IFI_STATE_CONFIGURED) { + switch (ifi_s->ifi_state) { + case IFI_STATE_CONFIGURED: + case IFI_STATE_TRANSITIVE: + break; + default: printf("\n"); continue; } @@ -574,6 +602,26 @@ action_show(int argc, char **argv) rai->rai_hoplimit); printf("\tAdvIfPrefixes: %s\n", rai->rai_advifprefix ? "yes" : "no"); + + /* RA timer */ + rat = NULL; + if (ifi_s->ifi_ra_timer != NULL) { + sprintf(argv_ifi_ra_timer, "%s:ifi_ra_timer=", + ifi->ifi_ifname); + action_argv = argv_ifi_ra_timer; + + error = action_propget(action_argv, &cp); + if (error) + return (error); + + rat = (struct rtadvd_timer *)cp.cp_val; + } + printf("\tNext RA send: %s", + (rat == NULL) ? "never\n" : + ctime((time_t *)&rat->rat_tm.tv_sec)); + printf("\tLast RA sent: %s", + (ifi_s->ifi_ra_lastsent.tv_sec == 0) ? "never\n" : + ctime((time_t *)&ifi_s->ifi_ra_lastsent.tv_sec)); if (rai->rai_clockskew) printf("\tClock skew: %" PRIu16 "sec\n", rai->rai_clockskew); @@ -650,18 +698,22 @@ action_show(int argc, char **argv) printf("\n"); - printf("\tLast RA sent: %s", - (rai->rai_lastsent.tv_sec == 0) ? "never\n" : - ctime((time_t *)&rai->rai_lastsent.tv_sec)); - printf("\tRA initcounts/waits: %d/%d\n", - rai->rai_initcounter, - rai->rai_waiting); - printf("\tRA out/in/inconsistent: " - "%" PRIu64 "/%" PRIu64 "/%" PRIu64 "\n", - ifi_s->ifi_raoutput, + printf("\tCounters\n" + "\t RA burst counts: %" PRIu16 " (interval: %s)\n" + "\t RS wait counts: %" PRIu16 "\n", + ifi_s->ifi_burstcount, + sec2str(ifi_s->ifi_burstinterval, ssbuf), + ifi_s->ifi_rs_waitcount); + + printf("\tOutputs\n" + "\t RA: %" PRIu64 "\n", ifi_s->ifi_raoutput); + + printf("\tInputs\n" + "\t RA: %" PRIu64 " (normal)\n" + "\t RA: %" PRIu64 " (inconsistent)\n" + "\t RS: %" PRIu64 "\n", ifi_s->ifi_rainput, - ifi_s->ifi_rainconsistent); - printf("\tRS in: %" PRIu64 "\n", + ifi_s->ifi_rainconsistent, ifi_s->ifi_rsinput); printf("\n"); Modified: user/hrs/ipv6/usr.sbin/rtadvd/config.c ============================================================================== --- user/hrs/ipv6/usr.sbin/rtadvd/config.c Sat Jul 16 08:51:09 2011 (r224086) +++ user/hrs/ipv6/usr.sbin/rtadvd/config.c Sat Jul 16 09:20:22 2011 (r224087) @@ -149,7 +149,6 @@ int loadconfig_ifname(char *ifname) { struct ifinfo *ifi; - int error; syslog(LOG_DEBUG, "<%s> enter", __func__); @@ -175,37 +174,21 @@ loadconfig_ifname(char *ifname) ifi->ifi_ifname); continue; } - if (getconfig(ifi->ifi_ifindex) == NULL) { + if (getconfig(ifi) == NULL) { syslog(LOG_ERR, "<%s> invalid configuration for %s. " "Ignored at this moment.", __func__, ifi->ifi_ifname); continue; } - ifi->ifi_state = IFI_STATE_CONFIGURED; - syslog(LOG_DEBUG, - "<%s> ifname=%s marked as configured.", - __func__, ifi->ifi_ifname); - - error = sock_mc_join(&sock, ifi->ifi_ifindex); - if (error) - exit(1); } return (0); } int -rmconfig(int idx) +rm_ifinfo_index(int idx) { - struct rainfo *rai; - struct prefix *pfx; - struct soliciter *sol; - struct rdnss *rdn; - struct rdnss_addr *rdna; - struct dnssl *dns; - struct rtinfo *rti; struct ifinfo *ifi; - int error; ifi = if_indextoifinfo(idx); if (ifi == NULL) { @@ -213,24 +196,39 @@ rmconfig(int idx) __func__, idx); return (-1); } - rai = ifi->ifi_rainfo; - if (ifi->ifi_state == IFI_STATE_CONFIGURED) { + return (rm_ifinfo(ifi)); +} + +int +rm_ifinfo(struct ifinfo *ifi) +{ + int error; + + syslog(LOG_DEBUG, "<%s> enter (%s).", __func__, ifi->ifi_ifname); + switch (ifi->ifi_state) { + case IFI_STATE_UNCONFIGURED: + return (0); + break; + default: ifi->ifi_state = IFI_STATE_UNCONFIGURED; syslog(LOG_DEBUG, - "<%s> ifname=%s marked as unconfigured.", + "<%s> ifname=%s marked as UNCONFIGURED.", __func__, ifi->ifi_ifname); - error = sock_mc_leave(&sock, ifi->ifi_ifindex); - if (error) - exit(1); + /* XXX: No MC leaving here becasue index is disappeared */ + + /* Inactivate timer */ + rtadvd_remove_timer(ifi->ifi_ra_timer); + ifi->ifi_ra_timer = NULL; + break; } /* clean up ifi */ if (!ifi->ifi_persist) { TAILQ_REMOVE(&ifilist, ifi, ifi_next); syslog(LOG_DEBUG, "<%s>: ifinfo (idx=%d) removed.", - __func__, idx); + __func__, ifi->ifi_ifindex); free(ifi); } else { /* recreate an empty entry */ @@ -238,16 +236,62 @@ rmconfig(int idx) syslog(LOG_DEBUG, "<%s>: ifname=%s is persistent.", __func__, ifi->ifi_ifname); } + /* clean up rai if any */ - if (rai == NULL) - return (0); + switch (ifi->ifi_state) { + case IFI_STATE_CONFIGURED: + if (ifi->ifi_rainfo != NULL) { + error = rm_rainfo(ifi->ifi_rainfo); + if (error) + return (error); + ifi->ifi_rainfo = NULL; + } + break; + case IFI_STATE_TRANSITIVE: + if (ifi->ifi_rainfo == ifi->ifi_rainfo_trans) { + if (ifi->ifi_rainfo != NULL) { + error = rm_rainfo(ifi->ifi_rainfo); + if (error) + return (error); + ifi->ifi_rainfo = NULL; + ifi->ifi_rainfo_trans = NULL; + } + } else { + if (ifi->ifi_rainfo != NULL) { + error = rm_rainfo(ifi->ifi_rainfo); + if (error) + return (error); + ifi->ifi_rainfo = NULL; + } + if (ifi->ifi_rainfo_trans != NULL) { + error = rm_rainfo(ifi->ifi_rainfo_trans); + if (error) + return (error); + ifi->ifi_rainfo_trans = NULL; + } + } + } - TAILQ_REMOVE(&railist, rai, rai_next); - syslog(LOG_DEBUG, "<%s>: rainfo (idx=%d) removed.", - __func__, idx); + syslog(LOG_DEBUG, "<%s> leave (%s).", __func__, ifi->ifi_ifname); + return (0); +} + +int +rm_rainfo(struct rainfo *rai) +{ + struct prefix *pfx; + struct soliciter *sol; + struct rdnss *rdn; + struct rdnss_addr *rdna; + struct dnssl *dns; + struct rtinfo *rti; - /* Free all of allocated memories for this entry. */ - rtadvd_remove_timer(rai->rai_timer); + syslog(LOG_DEBUG, "<%s>: enter", __func__); + + TAILQ_REMOVE(&railist, rai, rai_next); + if (rai->rai_ifinfo != NULL) + syslog(LOG_DEBUG, "<%s>: rainfo (idx=%d) removed.", + __func__, rai->rai_ifinfo->ifi_ifindex); if (rai->rai_ra_data != NULL) free(rai->rai_ra_data); @@ -277,34 +321,34 @@ rmconfig(int idx) free(rti); } free(rai); + syslog(LOG_DEBUG, "<%s>: leave", __func__); return (0); } struct ifinfo * -getconfig(int idx) +getconfig(struct ifinfo *ifi) { int stat, i; + int error; char tbuf[BUFSIZ]; struct rainfo *rai; struct rainfo *rai_old; - struct ifinfo *ifi; int32_t val; int64_t val64; char buf[BUFSIZ]; char *bp = buf; char *addr, *flagstr; - if (idx == 0) - return (NULL); - TAILQ_FOREACH(ifi, &ifilist, ifi_next) { - if (ifi->ifi_ifindex == idx) - break; - } if (ifi == NULL) /* if does not exist */ return (NULL); - rai_old = ifi->ifi_rainfo; + if (ifi->ifi_state == IFI_STATE_TRANSITIVE && + ifi->ifi_rainfo == NULL) { + syslog(LOG_INFO, "<%s> %s is shutting down. Skipped.", + __func__, ifi->ifi_ifname); + return (NULL); + } if ((stat = agetent(tbuf, ifi->ifi_ifname)) <= 0) { memset(tbuf, 0, sizeof(tbuf)); @@ -857,26 +901,102 @@ getconfig_free_dns: * Before the removal, RDNSS and DNSSL options with * zero-lifetime will be sent. */ - if (rai_old != NULL) { - const int retrans = MAX_FINAL_RTR_ADVERTISEMENTS; - struct rdnss *rdn; - struct dnssl *dns; + switch (ifi->ifi_state) { + case IFI_STATE_UNCONFIGURED: + /* UNCONFIGURED -> TRANSITIVE */ - rai_old->rai_lifetime = 0; - TAILQ_FOREACH(rdn, &rai_old->rai_rdnss, rd_next) - rdn->rd_ltime = 0; - TAILQ_FOREACH(dns, &rai_old->rai_dnssl, dn_next) - dns->dn_ltime = 0; - - make_packet(rai_old); - for (i = 0; i < retrans; i++) { - ra_output(rai_old); - sleep(MIN_DELAY_BETWEEN_RAS); + error = sock_mc_join(&sock, ifi->ifi_ifindex); + if (error) + exit(1); + + ifi->ifi_state = IFI_STATE_TRANSITIVE; + ifi->ifi_burstcount = MAX_INITIAL_RTR_ADVERTISEMENTS; + ifi->ifi_burstinterval = MAX_INITIAL_RTR_ADVERT_INTERVAL; + + /* The same two rai mean initial burst */ + ifi->ifi_rainfo = rai; + ifi->ifi_rainfo_trans = rai; + TAILQ_INSERT_TAIL(&railist, rai, rai_next); + + if (ifi->ifi_ra_timer == NULL) + ifi->ifi_ra_timer = rtadvd_add_timer(ra_timeout, + ra_timer_update, ifi, ifi); + ra_timer_update(ifi, &ifi->ifi_ra_timer->rat_tm); + rtadvd_set_timer(&ifi->ifi_ra_timer->rat_tm, + ifi->ifi_ra_timer); + + syslog(LOG_DEBUG, + "<%s> ifname=%s marked as TRANSITIVE (initial burst).", + __func__, ifi->ifi_ifname); + break; + case IFI_STATE_CONFIGURED: + /* CONFIGURED -> TRANSITIVE */ + rai_old = ifi->ifi_rainfo; + if (rai_old == NULL) { + syslog(LOG_ERR, + "<%s> ifi_rainfo is NULL" + " in IFI_STATE_CONFIGURED.", __func__); + ifi = NULL; + break; + } else { + struct rdnss *rdn; + struct dnssl *dns; + + rai_old->rai_lifetime = 0; + TAILQ_FOREACH(rdn, &rai_old->rai_rdnss, rd_next) + rdn->rd_ltime = 0; + TAILQ_FOREACH(dns, &rai_old->rai_dnssl, dn_next) + dns->dn_ltime = 0; + + ifi->ifi_rainfo_trans = rai_old; + ifi->ifi_state = IFI_STATE_TRANSITIVE; + ifi->ifi_burstcount = MAX_FINAL_RTR_ADVERTISEMENTS; + ifi->ifi_burstinterval = MIN_DELAY_BETWEEN_RAS; + + ra_timer_update(ifi, &ifi->ifi_ra_timer->rat_tm); + rtadvd_set_timer(&ifi->ifi_ra_timer->rat_tm, + ifi->ifi_ra_timer); + + syslog(LOG_DEBUG, + "<%s> ifname=%s marked as TRANSITIVE" + " (transitional burst)", + __func__, ifi->ifi_ifname); + } + ifi->ifi_rainfo = rai; + TAILQ_INSERT_TAIL(&railist, rai, rai_next); + break; + case IFI_STATE_TRANSITIVE: + if (ifi->ifi_rainfo != NULL) { + if (ifi->ifi_rainfo == ifi->ifi_rainfo_trans) { + /* Reinitialize initial burst */ + rm_rainfo(ifi->ifi_rainfo); + ifi->ifi_rainfo = rai; + ifi->ifi_rainfo_trans = rai; + ifi->ifi_burstcount = + MAX_INITIAL_RTR_ADVERTISEMENTS; + ifi->ifi_burstinterval = + MAX_INITIAL_RTR_ADVERT_INTERVAL; + } else { + /* Replace ifi_rainfo with the new one */ + rm_rainfo(ifi->ifi_rainfo); + ifi->ifi_rainfo = rai; + } + TAILQ_INSERT_TAIL(&railist, rai, rai_next); + + ra_timer_update(ifi, &ifi->ifi_ra_timer->rat_tm); + rtadvd_set_timer(&ifi->ifi_ra_timer->rat_tm, + ifi->ifi_ra_timer); + } else { + /* XXX: NOTREACHED. Being shut down. */ + syslog(LOG_ERR, + "<%s> %s is shutting down. Skipped.", + __func__, ifi->ifi_ifname); + rm_rainfo(rai); + + return (NULL); } - rmconfig(idx); + break; } - ifi->ifi_rainfo = rai; - TAILQ_INSERT_TAIL(&railist, rai, rai_next); return (ifi); @@ -913,6 +1033,7 @@ get_prefix(struct rainfo *rai) a = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr; if (IN6_IS_ADDR_LINKLOCAL(a)) continue; + /* get prefix length */ m = (char *)&((struct sockaddr_in6 *)ifa->ifa_netmask)->sin6_addr; lim = (char *)(ifa->ifa_netmask) + ifa->ifa_netmask->sa_len; @@ -1011,9 +1132,7 @@ add_prefix(struct rainfo *rai, struct in inet_ntop(AF_INET6, &ipr->ipr_prefix.sin6_addr, ntopbuf, sizeof(ntopbuf)), ipr->ipr_plen, ifi->ifi_ifname); - /* reconstruct the packet */ rai->rai_pfxs++; - make_packet(rai); } /* @@ -1038,8 +1157,8 @@ delete_prefix(struct prefix *pfx) if (pfx->pfx_timer) rtadvd_remove_timer(pfx->pfx_timer); free(pfx); + rai->rai_pfxs--; - make_packet(rai); } void Modified: user/hrs/ipv6/usr.sbin/rtadvd/config.h ============================================================================== --- user/hrs/ipv6/usr.sbin/rtadvd/config.h Sat Jul 16 08:51:09 2011 (r224086) +++ user/hrs/ipv6/usr.sbin/rtadvd/config.h Sat Jul 16 09:20:22 2011 (r224087) @@ -30,8 +30,10 @@ * SUCH DAMAGE. */ -extern struct ifinfo *getconfig(int); -extern int rmconfig(int); +extern struct ifinfo *getconfig(struct ifinfo *); +extern int rm_ifinfo(struct ifinfo *); +extern int rm_ifinfo_index(int); +extern int rm_rainfo(struct rainfo *); extern int loadconfig_ifname(char *); extern int loadconfig_index(int); extern void delete_prefix(struct prefix *); Modified: user/hrs/ipv6/usr.sbin/rtadvd/control_server.c ============================================================================== --- user/hrs/ipv6/usr.sbin/rtadvd/control_server.c Sat Jul 16 08:51:09 2011 (r224086) +++ user/hrs/ipv6/usr.sbin/rtadvd/control_server.c Sat Jul 16 09:20:22 2011 (r224087) @@ -74,8 +74,8 @@ static int cmsg_getprop_echo(struct ctrl static int cmsg_getprop_version(struct ctrl_msg_pl *); static int cmsg_getprop_ifilist(struct ctrl_msg_pl *); static int cmsg_getprop_ifi(struct ctrl_msg_pl *); +static int cmsg_getprop_ifi_ra_timer(struct ctrl_msg_pl *); static int cmsg_getprop_rai(struct ctrl_msg_pl *); -static int cmsg_getprop_rai_timer(struct ctrl_msg_pl *); static int cmsg_getprop_pfx(struct ctrl_msg_pl *); static int cmsg_getprop_rdnss(struct ctrl_msg_pl *); static int cmsg_getprop_dnssl(struct ctrl_msg_pl *); @@ -94,8 +94,8 @@ static struct dispatch_table { DEF_PL_HANDLER(version), DEF_PL_HANDLER(ifilist), DEF_PL_HANDLER(ifi), + DEF_PL_HANDLER(ifi_ra_timer), DEF_PL_HANDLER(rai), - DEF_PL_HANDLER(rai_timer), DEF_PL_HANDLER(rti), DEF_PL_HANDLER(pfx), DEF_PL_HANDLER(rdnss), @@ -235,7 +235,7 @@ cmsg_getprop_rai(struct ctrl_msg_pl *cp) } static int -cmsg_getprop_rai_timer(struct ctrl_msg_pl *cp) +cmsg_getprop_ifi_ra_timer(struct ctrl_msg_pl *cp) { struct ifinfo *ifi; struct rainfo *rai; @@ -259,8 +259,8 @@ cmsg_getprop_rai_timer(struct ctrl_msg_p cp->cp_ifname); return (1); } - if ((rtimer = rai->rai_timer) == NULL) { - syslog(LOG_ERR, "<%s> %s has no rai_timer", __func__, + if ((rtimer = ifi->ifi_ra_timer) == NULL) { + syslog(LOG_ERR, "<%s> %s has no ifi_ra_timer", __func__, cp->cp_ifname); return (1); } Modified: user/hrs/ipv6/usr.sbin/rtadvd/rtadvd.c ============================================================================== --- user/hrs/ipv6/usr.sbin/rtadvd/rtadvd.c Sat Jul 16 08:51:09 2011 (r224086) +++ user/hrs/ipv6/usr.sbin/rtadvd/rtadvd.c Sat Jul 16 09:20:22 2011 (r224087) @@ -96,6 +96,7 @@ static const char *pidfilename = _PATH_R const char *conffile = _PATH_RTADVDCONF; static struct pidfh *pfh; int dflag = 0, sflag = 0; +static int wait_shutdown; #define PFD_RAWSOCK 0 #define PFD_RTSOCK 1 @@ -162,7 +163,7 @@ static int nd6_options(struct nd_opt_hdr union nd_opt *, uint32_t); static void free_ndopts(union nd_opt *); static void rtmsg_input(struct sockinfo *); -static void set_short_delay(struct rainfo *); +static void set_short_delay(struct ifinfo *); static int check_accept_rtadv(int); int @@ -313,7 +314,7 @@ main(int argc, char *argv[]) /* timeout handler update for active interfaces */ rtadvd_update_timeout_handler(); - + /* timer expiration check and reset the timer */ timeout = rtadvd_check_timer(); @@ -347,7 +348,7 @@ main(int argc, char *argv[]) if (set[PFD_CSOCK].revents & POLLIN) { int fd; - + fd = csock_accept(&ctrlsock); if (fd == -1) syslog(LOG_ERR, "<%s> accept", __func__); @@ -361,38 +362,66 @@ main(int argc, char *argv[]) static void rtadvd_shutdown(void) { + struct ifinfo *ifi; struct rainfo *rai; struct rdnss *rdn; struct dnssl *dns; - int i; - const int retrans = MAX_FINAL_RTR_ADVERTISEMENTS; + + if (wait_shutdown) { + syslog(LOG_INFO, + "waiting expiration of the all RA timers\n"); + + TAILQ_FOREACH(ifi, &ifilist, ifi_next) { + if (ifi->ifi_ra_timer != NULL) + break; + } + if (ifi == NULL) { + syslog(LOG_INFO, "gracefully terminated.\n"); + exit(0); + } + + sleep(1); + return; + } syslog(LOG_DEBUG, "<%s> cease to be an advertising router\n", __func__); + wait_shutdown = 1; + TAILQ_FOREACH(rai, &railist, rai_next) { rai->rai_lifetime = 0; TAILQ_FOREACH(rdn, &rai->rai_rdnss, rd_next) rdn->rd_ltime = 0; TAILQ_FOREACH(dns, &rai->rai_dnssl, dn_next) dns->dn_ltime = 0; - make_packet(rai); } - for (i = 0; i < retrans; i++) { - syslog(LOG_INFO, "<%s> final RA transmission #%d/%d\n", - __func__, i, retrans - i); - TAILQ_FOREACH(rai, &railist, rai_next) - if (rai->rai_ifinfo->ifi_state - == IFI_STATE_CONFIGURED) - ra_output(rai); - syslog(LOG_INFO, "<%s> waiting for %d sec.\n", - __func__, MIN_DELAY_BETWEEN_RAS); - sleep(MIN_DELAY_BETWEEN_RAS); + TAILQ_FOREACH(ifi, &ifilist, ifi_next) { + if (!ifi->ifi_persist) + continue; + if (ifi->ifi_state == IFI_STATE_UNCONFIGURED) + continue; + if (ifi->ifi_ra_timer == NULL) + continue; + + ifi->ifi_state = IFI_STATE_TRANSITIVE; + + /* Mark as the shut-down state. */ + ifi->ifi_rainfo_trans = ifi->ifi_rainfo; + ifi->ifi_rainfo = NULL; + + ifi->ifi_burstcount = MAX_FINAL_RTR_ADVERTISEMENTS; + ifi->ifi_burstinterval = MIN_DELAY_BETWEEN_RAS; + + ra_timer_update(ifi, &ifi->ifi_ra_timer->rat_tm); + rtadvd_set_timer(&ifi->ifi_ra_timer->rat_tm, + ifi->ifi_ra_timer); } + syslog(LOG_INFO, + "<%s> final RA transmission started.\n", __func__); + pidfile_remove(pfh); csock_close(&ctrlsock); - - exit(0); } static void @@ -489,7 +518,16 @@ rtmsg_input(struct sockinfo *s) syslog(LOG_INFO, "<%s>: interface removed (idx=%d)", __func__, ifan->ifan_index); - rmconfig(ifan->ifan_index); + rm_ifinfo_index(ifan->ifan_index); + + /* Clear ifi_ifindex */ + TAILQ_FOREACH(ifi, &ifilist, ifi_next) { + if (ifi->ifi_ifindex + == ifan->ifan_index) { + ifi->ifi_ifindex = 0; + break; + } + } update_ifinfo(&ifilist, ifan->ifan_index); break; } @@ -526,7 +564,7 @@ rtmsg_input(struct sockinfo *s) case RTM_ADD: if (sflag) break; /* we aren't interested in prefixes */ - + addr = get_addr(msg); plen = get_prefixlen(msg); /* sanity check for plen */ @@ -608,29 +646,32 @@ rtmsg_input(struct sockinfo *s) syslog(LOG_INFO, "<%s> interface %s becomes down. stop timer.", __func__, ifi->ifi_ifname); - rtadvd_remove_timer(rai->rai_timer); - rai->rai_timer = NULL; + rtadvd_remove_timer(ifi->ifi_ra_timer); + ifi->ifi_ra_timer = NULL; } else if (!(oldifflags & IFF_UP) && /* DOWN to UP */ (ifi->ifi_flags & IFF_UP)) { syslog(LOG_INFO, "<%s> interface %s becomes up. restart timer.", __func__, ifi->ifi_ifname); - rai->rai_initcounter = 0; /* reset the counter */ - rai->rai_waiting = 0; /* XXX */ - rai->rai_timer = rtadvd_add_timer(ra_timeout, - ra_timer_update, rai, rai); - ra_timer_update(rai, &rai->rai_timer->rat_tm); - rtadvd_set_timer(&rai->rai_timer->rat_tm, - rai->rai_timer); + ifi->ifi_state = IFI_STATE_TRANSITIVE; + ifi->ifi_burstcount = + MAX_INITIAL_RTR_ADVERTISEMENTS; + ifi->ifi_burstinterval = + MAX_INITIAL_RTR_ADVERT_INTERVAL; + + ifi->ifi_ra_timer = rtadvd_add_timer(ra_timeout, + ra_timer_update, ifi, ifi); + ra_timer_update(ifi, &ifi->ifi_ra_timer->rat_tm); + rtadvd_set_timer(&ifi->ifi_ra_timer->rat_tm, + ifi->ifi_ra_timer); } else if (prefixchange && (ifi->ifi_flags & IFF_UP)) { /* * An advertised prefix has been added or invalidated. * Will notice the change in a short delay. */ - rai->rai_initcounter = 0; - set_short_delay(rai); + set_short_delay(ifi); } } @@ -654,7 +695,7 @@ rtadvd_input(struct sockinfo *s) struct ifinfo *ifi; syslog(LOG_DEBUG, "<%s> enter", __func__); - + if (s == NULL) { syslog(LOG_ERR, "<%s> internal error", __func__); exit(1); @@ -922,10 +963,10 @@ rs_input(int len, struct nd_router_solic * If there is already a waiting RS packet, don't * update the timer. */ - if (rai->rai_waiting++) + if (ifi->ifi_rs_waitcount++) goto done; - set_short_delay(rai); + set_short_delay(ifi); done: free_ndopts(&ndopts); @@ -933,7 +974,7 @@ rs_input(int len, struct nd_router_solic } static void -set_short_delay(struct rainfo *rai) +set_short_delay(struct ifinfo *ifi) { long delay; /* must not be greater than 1000000 */ struct timeval interval, now, min_delay, tm_tmp, *rest; @@ -952,7 +993,7 @@ set_short_delay(struct rainfo *rai) #endif interval.tv_sec = 0; interval.tv_usec = delay; - rest = rtadvd_timer_rest(rai->rai_timer); + rest = rtadvd_timer_rest(ifi->ifi_ra_timer); if (TIMEVAL_LT(rest, &interval)) { syslog(LOG_DEBUG, "<%s> random delay is larger than " "the rest of the current timer", __func__); @@ -967,21 +1008,21 @@ set_short_delay(struct rainfo *rai) * previous advertisement was sent. */ gettimeofday(&now, NULL); - TIMEVAL_SUB(&now, &rai->rai_lastsent, &tm_tmp); + TIMEVAL_SUB(&now, &ifi->ifi_ra_lastsent, &tm_tmp); min_delay.tv_sec = MIN_DELAY_BETWEEN_RAS; min_delay.tv_usec = 0; if (TIMEVAL_LT(&tm_tmp, &min_delay)) { TIMEVAL_SUB(&min_delay, &tm_tmp, &min_delay); TIMEVAL_ADD(&min_delay, &interval, &interval); } - rtadvd_set_timer(&interval, rai->rai_timer); + rtadvd_set_timer(&interval, ifi->ifi_ra_timer); } static int check_accept_rtadv(int idx) { struct ifinfo *ifi; - + TAILQ_FOREACH(ifi, &ifilist, ifi_next) { if (ifi->ifi_ifindex == idx) break; @@ -992,7 +1033,18 @@ check_accept_rtadv(int idx) __func__, idx); return (0); } -#if (__FreeBSD_version > 900000) +#if (__FreeBSD_version < 900000) + /* + * RA_RECV: !ip6.forwarding && ip6.accept_rtadv + * RA_SEND: ip6.forwarding + */ + return ((getinet6sysctl(IPV6CTL_FORWARDING) == 0) && *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201107160920.p6G9KNGi018881>