- Accumulate RA options instead of replacing old ones when a new RA arrived.
RFC 4861 6.3.4 clearly defines handling multiple RAs in this way. - RDNSS/DNSSL options from multiple RAs on a single link will be gathered and sent to resolvconf(8). - Call "resolvconf -d" only after at least one RDNSS or DNSSL option is received and then all of them are expired. - The rtsold.dump output now supports displaying a list of the RA options. - Use more human-readable expression for logging values of struct timeval. Discussed with: ume
This commit is contained in:
parent
d91c258074
commit
06056832ec
@ -39,6 +39,7 @@
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <syslog.h>
|
||||
#include <time.h>
|
||||
@ -53,14 +54,16 @@ static FILE *fp;
|
||||
extern struct ifinfo *iflist;
|
||||
|
||||
static void dump_interface_status(void);
|
||||
static const char *sec2str(time_t);
|
||||
static const char * const ifstatstr[] = {"IDLE", "DELAY", "PROBE", "DOWN", "TENTATIVE"};
|
||||
|
||||
static void
|
||||
dump_interface_status(void)
|
||||
{
|
||||
struct ifinfo *ifi;
|
||||
struct rainfo *rai;
|
||||
struct ra_opt *rao;
|
||||
struct timeval now;
|
||||
char ntopbuf[INET6_ADDRSTRLEN];
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
@ -91,9 +94,33 @@ dump_interface_status(void)
|
||||
(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));
|
||||
: sec2str(&ifi->expire));
|
||||
}
|
||||
fprintf(fp, " number of valid RAs: %d\n", ifi->racnt);
|
||||
|
||||
TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next) {
|
||||
fprintf(fp, " RA from %s\n",
|
||||
inet_ntop(AF_INET6, &rai->rai_saddr.sin6_addr,
|
||||
ntopbuf, sizeof(ntopbuf)));
|
||||
TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
|
||||
fprintf(fp, " option: ");
|
||||
switch (rao->rao_type) {
|
||||
case ND_OPT_RDNSS:
|
||||
fprintf(fp, "RDNSS: %s (expire: %s)\n",
|
||||
(char *)rao->rao_msg,
|
||||
sec2str(&rao->rao_expire));
|
||||
break;
|
||||
case ND_OPT_DNSSL:
|
||||
fprintf(fp, "DNSSL: %s (expire: %s)\n",
|
||||
(char *)rao->rao_msg,
|
||||
sec2str(&rao->rao_expire));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,8 +136,8 @@ rtsold_dump_file(const char *dumpfile)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static const char *
|
||||
sec2str(time_t total)
|
||||
const char *
|
||||
sec2str(const struct timeval *total)
|
||||
{
|
||||
static char result[256];
|
||||
int days, hours, mins, secs;
|
||||
@ -118,11 +145,19 @@ sec2str(time_t total)
|
||||
char *p = result;
|
||||
char *ep = &result[sizeof(result)];
|
||||
int n;
|
||||
struct timeval now;
|
||||
time_t tsec;
|
||||
|
||||
days = total / 3600 / 24;
|
||||
hours = (total / 3600) % 24;
|
||||
mins = (total / 60) % 60;
|
||||
secs = total % 60;
|
||||
gettimeofday(&now, NULL);
|
||||
tsec = total->tv_sec;
|
||||
tsec += total->tv_usec / 1000000;
|
||||
tsec -= now.tv_sec;
|
||||
tsec -= now.tv_usec / 1000000;
|
||||
|
||||
days = tsec / 3600 / 24;
|
||||
hours = (tsec / 3600) % 24;
|
||||
mins = (tsec / 60) % 60;
|
||||
secs = tsec % 60;
|
||||
|
||||
if (days) {
|
||||
first = 0;
|
||||
|
@ -85,6 +85,7 @@ static const struct sockaddr_in6 sin6_allrouters = {
|
||||
static void call_script(const int, const char *const *, void *);
|
||||
static size_t dname_labeldec(char *, size_t, const char *);
|
||||
static int safefile(const char *);
|
||||
static struct ra_opt *find_raopt(struct rainfo *, int, void *, size_t);
|
||||
|
||||
#define _ARGS_OTHER otherconf_script, ifi->ifname
|
||||
#define _ARGS_RESADD resolvconf_script, "-a", ifi->ifname
|
||||
@ -240,6 +241,7 @@ rtsol_input(int s)
|
||||
struct icmp6_hdr *icp;
|
||||
struct nd_router_advert *nd_ra;
|
||||
struct cmsghdr *cm;
|
||||
struct rainfo *rai;
|
||||
char *raoptp;
|
||||
char *p;
|
||||
struct in6_addr *addr;
|
||||
@ -251,6 +253,8 @@ rtsol_input(int s)
|
||||
char dname[NI_MAXHOST];
|
||||
struct timeval now;
|
||||
struct timeval lifetime;
|
||||
int newent_rai;
|
||||
int newent_rao;
|
||||
|
||||
/* get message. namelen and controllen must always be initialized. */
|
||||
rcvmhdr.msg_namelen = sizeof(from);
|
||||
@ -367,22 +371,20 @@ rtsol_input(int s)
|
||||
ifi->otherconfig = 1;
|
||||
CALL_SCRIPT(OTHER, NULL);
|
||||
}
|
||||
|
||||
/* Initialize ra_opt per-interface structure. */
|
||||
gettimeofday(&now, NULL);
|
||||
if (!TAILQ_EMPTY(&ifi->ifi_ra_opt))
|
||||
while ((rao = TAILQ_FIRST(&ifi->ifi_ra_opt)) != NULL) {
|
||||
if (rao->rao_msg != NULL)
|
||||
free(rao->rao_msg);
|
||||
TAILQ_REMOVE(&ifi->ifi_ra_opt, rao, rao_next);
|
||||
free(rao);
|
||||
}
|
||||
else
|
||||
TAILQ_INIT(&ifi->ifi_ra_opt);
|
||||
newent_rai = 0;
|
||||
rai = find_rainfo(ifi, &from);
|
||||
if (rai == NULL) {
|
||||
ELM_MALLOC(rai, exit(1));
|
||||
rai->rai_ifinfo = ifi;
|
||||
TAILQ_INIT(&rai->rai_ra_opt);
|
||||
memcpy(&rai->rai_saddr.sin6_addr, &from.sin6_addr,
|
||||
sizeof(rai->rai_saddr.sin6_addr));
|
||||
newent_rai = 1;
|
||||
}
|
||||
|
||||
#define RA_OPT_NEXT_HDR(x) (struct nd_opt_hdr *)((char *)x + \
|
||||
(((struct nd_opt_hdr *)x)->nd_opt_len * 8))
|
||||
|
||||
/* Process RA options. */
|
||||
warnmsg(LOG_DEBUG, __func__, "Processing RA");
|
||||
raoptp = (char *)icp + sizeof(struct nd_router_advert);
|
||||
@ -439,25 +441,35 @@ rtsol_input(int s)
|
||||
warnmsg(LOG_DEBUG, __func__, "nsbuf = %s",
|
||||
nsbuf);
|
||||
|
||||
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(rao);
|
||||
addr++;
|
||||
continue;
|
||||
newent_rao = 0;
|
||||
rao = find_raopt(rai, ndo->nd_opt_type, nsbuf,
|
||||
strlen(nsbuf));
|
||||
if (rao == 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(rao);
|
||||
addr++;
|
||||
continue;
|
||||
}
|
||||
newent_rao = 1;
|
||||
}
|
||||
/* Set expiration timer */
|
||||
memset(&rao->rao_expire, 0, sizeof(rao->rao_expire));
|
||||
memset(&rao->rao_expire, 0,
|
||||
sizeof(rao->rao_expire));
|
||||
memset(&lifetime, 0, sizeof(lifetime));
|
||||
lifetime.tv_sec = ntohl(rdnss->nd_opt_rdnss_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);
|
||||
if (newent_rao)
|
||||
TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
|
||||
rao, rao_next);
|
||||
addr++;
|
||||
}
|
||||
break;
|
||||
@ -488,24 +500,35 @@ rtsol_input(int s)
|
||||
warnmsg(LOG_DEBUG, __func__, "dname = %s",
|
||||
dname);
|
||||
|
||||
ELM_MALLOC(rao, break);
|
||||
rao->rao_type = ndo->nd_opt_type;
|
||||
rao->rao_len = strlen(dname);
|
||||
rao->rao_msg = strdup(dname);
|
||||
if (rao->rao_msg == NULL) {
|
||||
warnmsg(LOG_ERR, __func__,
|
||||
"strdup failed: %s",
|
||||
strerror(errno));
|
||||
free(rao);
|
||||
break;
|
||||
newent_rao = 0;
|
||||
rao = find_raopt(rai, ndo->nd_opt_type, dname,
|
||||
strlen(dname));
|
||||
if (rao == NULL) {
|
||||
ELM_MALLOC(rao, break);
|
||||
rao->rao_type = ndo->nd_opt_type;
|
||||
rao->rao_len = strlen(dname);
|
||||
rao->rao_msg = strdup(dname);
|
||||
if (rao->rao_msg == NULL) {
|
||||
warnmsg(LOG_ERR, __func__,
|
||||
"strdup failed: %s",
|
||||
strerror(errno));
|
||||
free(rao);
|
||||
addr++;
|
||||
continue;
|
||||
}
|
||||
newent_rao = 1;
|
||||
}
|
||||
/* Set expiration timer */
|
||||
memset(&rao->rao_expire, 0, sizeof(rao->rao_expire));
|
||||
memset(&rao->rao_expire, 0,
|
||||
sizeof(rao->rao_expire));
|
||||
memset(&lifetime, 0, sizeof(lifetime));
|
||||
lifetime.tv_sec = ntohl(dnssl->nd_opt_dnssl_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);
|
||||
if (newent_rao)
|
||||
TAILQ_INSERT_TAIL(&rai->rai_ra_opt,
|
||||
rao, rao_next);
|
||||
p += len;
|
||||
}
|
||||
break;
|
||||
@ -515,6 +538,9 @@ rtsol_input(int s)
|
||||
}
|
||||
raoptp = (char *)RA_OPT_NEXT_HDR(raoptp);
|
||||
}
|
||||
if (newent_rai)
|
||||
TAILQ_INSERT_TAIL(&ifi->ifi_rainfo, rai, rai_next);
|
||||
|
||||
ra_opt_handler(ifi);
|
||||
ifi->racnt++;
|
||||
|
||||
@ -539,6 +565,7 @@ int
|
||||
ra_opt_handler(struct ifinfo *ifi)
|
||||
{
|
||||
struct ra_opt *rao;
|
||||
struct rainfo *rai;
|
||||
struct script_msg *smp1, *smp2, *smp3;
|
||||
struct timeval now;
|
||||
TAILQ_HEAD(, script_msg) sm_rdnss_head =
|
||||
@ -550,70 +577,87 @@ ra_opt_handler(struct ifinfo *ifi)
|
||||
dcount = 0;
|
||||
dlen = strlen(resstr_sh_prefix) + strlen(resstr_nl);
|
||||
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(smp1, continue);
|
||||
ELM_MALLOC(smp2, goto free1);
|
||||
ELM_MALLOC(smp3, goto free2);
|
||||
smp1->sm_msg = resstr_ns_prefix;
|
||||
TAILQ_INSERT_TAIL(&sm_rdnss_head, smp1, sm_next);
|
||||
smp2->sm_msg = rao->rao_msg;
|
||||
TAILQ_INSERT_TAIL(&sm_rdnss_head, smp2, sm_next);
|
||||
smp3->sm_msg = resstr_nl;
|
||||
TAILQ_INSERT_TAIL(&sm_rdnss_head, smp3, 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;
|
||||
}
|
||||
dcount++;
|
||||
/* Check resolv.conf(5) restrictions. */
|
||||
if (dcount > 6) {
|
||||
warnmsg(LOG_INFO, __func__,
|
||||
"dnssl entry exceeding maximum count (%d>6)"
|
||||
": %s", dcount, (char *)rao->rao_msg);
|
||||
break;
|
||||
}
|
||||
if (256 < dlen + strlen(rao->rao_msg) +
|
||||
strlen(resstr_sp)) {
|
||||
warnmsg(LOG_INFO, __func__,
|
||||
"dnssl entry exceeding maximum length "
|
||||
"(>256): %s", (char *)rao->rao_msg);
|
||||
break;
|
||||
}
|
||||
ELM_MALLOC(smp1, continue);
|
||||
ELM_MALLOC(smp2, goto free1);
|
||||
if (TAILQ_EMPTY(&sm_dnssl_head)) {
|
||||
/*
|
||||
* All options from multiple RAs with the same or different
|
||||
* source addresses on a single interface will be gathered and
|
||||
* handled, not overridden. [RFC 4861 6.3.4]
|
||||
*/
|
||||
TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next) {
|
||||
TAILQ_FOREACH(rao, &rai->rai_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(smp1, continue);
|
||||
ELM_MALLOC(smp2, goto free1);
|
||||
ELM_MALLOC(smp3, goto free2);
|
||||
smp3->sm_msg = resstr_sh_prefix;
|
||||
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp3,
|
||||
smp1->sm_msg = resstr_ns_prefix;
|
||||
TAILQ_INSERT_TAIL(&sm_rdnss_head, smp1,
|
||||
sm_next);
|
||||
smp2->sm_msg = rao->rao_msg;
|
||||
TAILQ_INSERT_TAIL(&sm_rdnss_head, smp2,
|
||||
sm_next);
|
||||
smp3->sm_msg = resstr_nl;
|
||||
TAILQ_INSERT_TAIL(&sm_rdnss_head, smp3,
|
||||
sm_next);
|
||||
ifi->ifi_rdnss = IFI_DNSOPT_STATE_RECEIVED;
|
||||
|
||||
break;
|
||||
case ND_OPT_DNSSL:
|
||||
if (timercmp(&now, &rao->rao_expire, >)) {
|
||||
warnmsg(LOG_INFO, __func__,
|
||||
"expired dnssl entry: %s",
|
||||
(char *)rao->rao_msg);
|
||||
break;
|
||||
}
|
||||
dcount++;
|
||||
/* Check resolv.conf(5) restrictions. */
|
||||
if (dcount > 6) {
|
||||
warnmsg(LOG_INFO, __func__,
|
||||
"dnssl entry exceeding maximum count (%d>6)"
|
||||
": %s", dcount, (char *)rao->rao_msg);
|
||||
break;
|
||||
}
|
||||
if (256 < dlen + strlen(rao->rao_msg) +
|
||||
strlen(resstr_sp)) {
|
||||
warnmsg(LOG_INFO, __func__,
|
||||
"dnssl entry exceeding maximum length "
|
||||
"(>256): %s", (char *)rao->rao_msg);
|
||||
break;
|
||||
}
|
||||
ELM_MALLOC(smp1, continue);
|
||||
ELM_MALLOC(smp2, goto free1);
|
||||
if (TAILQ_EMPTY(&sm_dnssl_head)) {
|
||||
ELM_MALLOC(smp3, goto free2);
|
||||
smp3->sm_msg = resstr_sh_prefix;
|
||||
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp3,
|
||||
sm_next);
|
||||
}
|
||||
smp1->sm_msg = rao->rao_msg;
|
||||
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1,
|
||||
sm_next);
|
||||
smp2->sm_msg = resstr_sp;
|
||||
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp2,
|
||||
sm_next);
|
||||
dlen += strlen(rao->rao_msg) +
|
||||
strlen(resstr_sp);
|
||||
break;
|
||||
|
||||
ifi->ifi_dnssl = IFI_DNSOPT_STATE_RECEIVED;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
smp1->sm_msg = rao->rao_msg;
|
||||
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1, sm_next);
|
||||
smp2->sm_msg = resstr_sp;
|
||||
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp2, sm_next);
|
||||
dlen += strlen(rao->rao_msg) + strlen(resstr_sp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
continue;
|
||||
free2:
|
||||
free(smp2);
|
||||
free(smp2);
|
||||
free1:
|
||||
free(smp1);
|
||||
free(smp1);
|
||||
}
|
||||
}
|
||||
/* Add \n for DNSSL list. */
|
||||
if (!TAILQ_EMPTY(&sm_dnssl_head)) {
|
||||
@ -625,10 +669,12 @@ ra_opt_handler(struct ifinfo *ifi)
|
||||
|
||||
if (!TAILQ_EMPTY(&sm_rdnss_head))
|
||||
CALL_SCRIPT(RESADD, &sm_rdnss_head);
|
||||
#if 0
|
||||
else
|
||||
else if (ifi->ifi_rdnss == IFI_DNSOPT_STATE_RECEIVED ||
|
||||
ifi->ifi_dnssl == IFI_DNSOPT_STATE_RECEIVED) {
|
||||
CALL_SCRIPT(RESDEL, NULL);
|
||||
#endif
|
||||
ifi->ifi_rdnss = IFI_DNSOPT_STATE_NOINFO;
|
||||
ifi->ifi_dnssl = IFI_DNSOPT_STATE_NOINFO;
|
||||
}
|
||||
|
||||
ra_opt_handler_freeit:
|
||||
/* Clear script message queue. */
|
||||
@ -638,9 +684,30 @@ ra_opt_handler(struct ifinfo *ifi)
|
||||
free(smp1);
|
||||
}
|
||||
}
|
||||
if (!TAILQ_EMPTY(&sm_dnssl_head)) {
|
||||
while ((smp1 = TAILQ_FIRST(&sm_dnssl_head)) != NULL) {
|
||||
TAILQ_REMOVE(&sm_dnssl_head, smp1, sm_next);
|
||||
free(smp1);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct ra_opt *
|
||||
find_raopt(struct rainfo *rai, int type, void *msg, size_t len)
|
||||
{
|
||||
struct ra_opt *rao;
|
||||
|
||||
TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
|
||||
if (rao->rao_type == type &&
|
||||
rao->rao_len == strlen(msg) &&
|
||||
memcmp(rao->rao_msg, msg, len) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return (rao);
|
||||
}
|
||||
|
||||
static void
|
||||
call_script(const int argc, const char *const argv[], void *head)
|
||||
{
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <netinet/in_var.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <netinet6/nd6.h>
|
||||
|
||||
@ -408,7 +409,9 @@ ifconfig(char *ifname)
|
||||
}
|
||||
memset(ifi, 0, sizeof(*ifi));
|
||||
ifi->sdl = sdl;
|
||||
|
||||
ifi->ifi_rdnss = IFI_DNSOPT_STATE_NOINFO;
|
||||
ifi->ifi_dnssl = IFI_DNSOPT_STATE_NOINFO;
|
||||
TAILQ_INIT(&ifi->ifi_rainfo);
|
||||
strlcpy(ifi->ifname, ifname, sizeof(ifi->ifname));
|
||||
|
||||
/* construct a router solicitation message */
|
||||
@ -500,6 +503,19 @@ ifreconfig(char *ifname)
|
||||
}
|
||||
#endif
|
||||
|
||||
struct rainfo *
|
||||
find_rainfo(struct ifinfo *ifi, struct sockaddr_in6 *sin6)
|
||||
{
|
||||
struct rainfo *rai;
|
||||
|
||||
TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next)
|
||||
if (memcmp(&rai->rai_saddr.sin6_addr, &sin6->sin6_addr,
|
||||
sizeof(rai->rai_saddr.sin6_addr)) == 0)
|
||||
return (rai);
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
struct ifinfo *
|
||||
find_ifinfo(int ifindex)
|
||||
{
|
||||
@ -556,6 +572,7 @@ rtsol_check_timer(void)
|
||||
static struct timeval returnval;
|
||||
struct timeval now, rtsol_timer;
|
||||
struct ifinfo *ifi;
|
||||
struct rainfo *rai;
|
||||
struct ra_opt *rao;
|
||||
int flags;
|
||||
|
||||
@ -565,18 +582,21 @@ rtsol_check_timer(void)
|
||||
|
||||
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", ifi->ifname,
|
||||
ifi->state);
|
||||
warnmsg(LOG_DEBUG, __func__, "timer expiration on %s, "
|
||||
"state = %d", ifi->ifname, ifi->state);
|
||||
|
||||
/* Remove all RA options. */
|
||||
while ((rao = TAILQ_FIRST(&ifi->ifi_ra_opt)) != NULL) {
|
||||
if (rao->rao_msg != NULL)
|
||||
free(rao->rao_msg);
|
||||
TAILQ_REMOVE(&ifi->ifi_ra_opt, rao, rao_next);
|
||||
free(rao);
|
||||
while((rai = TAILQ_FIRST(&ifi->ifi_rainfo)) != NULL) {
|
||||
/* Remove all RA options. */
|
||||
TAILQ_REMOVE(&ifi->ifi_rainfo, rai, rai_next);
|
||||
while ((rao = TAILQ_FIRST(&rai->rai_ra_opt)) !=
|
||||
NULL) {
|
||||
TAILQ_REMOVE(&rai->rai_ra_opt, rao,
|
||||
rao_next);
|
||||
if (rao->rao_msg != NULL)
|
||||
free(rao->rao_msg);
|
||||
free(rao);
|
||||
}
|
||||
free(rai);
|
||||
}
|
||||
switch (ifi->state) {
|
||||
case IFS_DOWN:
|
||||
@ -645,21 +665,27 @@ rtsol_check_timer(void)
|
||||
rtsol_timer_update(ifi);
|
||||
} else {
|
||||
/* Expiration check for RA options. */
|
||||
struct ra_opt *rao_tmp;
|
||||
int expire = 0;
|
||||
|
||||
TAILQ_FOREACH_SAFE(rao, &ifi->ifi_ra_opt, rao_next, rao_tmp) {
|
||||
warnmsg(LOG_DEBUG, __func__,
|
||||
"RA expiration timer: "
|
||||
"type=%d, msg=%s, timer=%ld:%08ld",
|
||||
rao->rao_type, (char *)rao->rao_msg,
|
||||
(long)rao->rao_expire.tv_sec,
|
||||
(long)rao->rao_expire.tv_usec);
|
||||
if (timercmp(&now, &rao->rao_expire, >=)) {
|
||||
TAILQ_FOREACH(rai, &ifi->ifi_rainfo, rai_next) {
|
||||
TAILQ_FOREACH(rao, &rai->rai_ra_opt, rao_next) {
|
||||
warnmsg(LOG_DEBUG, __func__,
|
||||
"RA expiration timer: expired.");
|
||||
TAILQ_REMOVE(&ifi->ifi_ra_opt, rao, rao_next);
|
||||
expire = 1;
|
||||
"RA expiration timer: "
|
||||
"type=%d, msg=%s, expire=%s",
|
||||
rao->rao_type, (char *)rao->rao_msg,
|
||||
sec2str(&rao->rao_expire));
|
||||
if (timercmp(&now, &rao->rao_expire,
|
||||
>=)) {
|
||||
warnmsg(LOG_DEBUG, __func__,
|
||||
"RA expiration timer: "
|
||||
"expired.");
|
||||
TAILQ_REMOVE(&rai->rai_ra_opt,
|
||||
rao, rao_next);
|
||||
if (rao->rao_msg != NULL)
|
||||
free(rao->rao_msg);
|
||||
free(rao);
|
||||
expire = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (expire)
|
||||
@ -678,9 +704,10 @@ rtsol_check_timer(void)
|
||||
else
|
||||
timersub(&rtsol_timer, &now, &returnval);
|
||||
|
||||
if (dflag > 1)
|
||||
warnmsg(LOG_DEBUG, __func__, "New timer is %ld:%08ld",
|
||||
(long)returnval.tv_sec, (long)returnval.tv_usec);
|
||||
now.tv_sec += returnval.tv_sec;
|
||||
now.tv_usec += returnval.tv_usec;
|
||||
warnmsg(LOG_DEBUG, __func__, "New timer is %s",
|
||||
sec2str(&now));
|
||||
|
||||
return (&returnval);
|
||||
}
|
||||
@ -751,11 +778,10 @@ rtsol_timer_update(struct ifinfo *ifi)
|
||||
gettimeofday(&now, NULL);
|
||||
timeradd(&now, &ifi->timer, &ifi->expire);
|
||||
|
||||
if (dflag > 1)
|
||||
warnmsg(LOG_DEBUG, __func__,
|
||||
"set timer for %s to %d:%d", ifi->ifname,
|
||||
(int)ifi->timer.tv_sec,
|
||||
(int)ifi->timer.tv_usec);
|
||||
now.tv_sec += ifi->timer.tv_sec;
|
||||
now.tv_usec += ifi->timer.tv_usec;
|
||||
warnmsg(LOG_DEBUG, __func__, "set timer for %s to %s",
|
||||
ifi->ifname, sec2str(&now));
|
||||
}
|
||||
|
||||
#undef MILLION
|
||||
|
@ -46,6 +46,16 @@ struct ra_opt {
|
||||
void *rao_msg;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(rainfo_head, ra_opt);
|
||||
|
||||
struct rainfo {
|
||||
TAILQ_ENTRY(rainfo) rai_next;
|
||||
|
||||
struct ifinfo *rai_ifinfo;
|
||||
struct sockaddr_in6 rai_saddr;
|
||||
TAILQ_HEAD(, ra_opt) rai_ra_opt;
|
||||
};
|
||||
|
||||
struct ifinfo {
|
||||
TAILQ_ENTRY(ifinfo) ifi_next; /* pointer to the next interface */
|
||||
|
||||
@ -64,13 +74,16 @@ struct ifinfo {
|
||||
struct timeval timer;
|
||||
struct timeval expire;
|
||||
int errors; /* # of errors we've got - detect wedge */
|
||||
#define IFI_DNSOPT_STATE_NOINFO 0
|
||||
#define IFI_DNSOPT_STATE_RECEIVED 1
|
||||
int ifi_rdnss; /* RDNSS option state */
|
||||
int ifi_dnssl; /* DNSSL option state */
|
||||
|
||||
int racnt; /* total # of valid RAs it have got */
|
||||
TAILQ_HEAD(, rainfo) ifi_rainfo;
|
||||
|
||||
size_t rs_datalen;
|
||||
u_char *rs_data;
|
||||
|
||||
TAILQ_HEAD(, ra_opt) ifi_ra_opt;
|
||||
};
|
||||
|
||||
/* per interface status */
|
||||
@ -118,6 +131,7 @@ extern const char *resolvconf_script;
|
||||
extern int ifconfig(char *);
|
||||
extern void iflist_init(void);
|
||||
struct ifinfo *find_ifinfo(int);
|
||||
struct rainfo *find_rainfo(struct ifinfo *, struct sockaddr_in6 *);
|
||||
void rtsol_timer_update(struct ifinfo *);
|
||||
extern void warnmsg(int, const char *, const char *, ...)
|
||||
__attribute__((__format__(__printf__, 3, 4)));
|
||||
@ -145,6 +159,7 @@ extern void defrouter_probe(struct ifinfo *);
|
||||
|
||||
/* dump.c */
|
||||
extern void rtsold_dump_file(const char *);
|
||||
extern const char *sec2str(const struct timeval *);
|
||||
|
||||
/* rtsock.c */
|
||||
extern int rtsock_open(void);
|
||||
|
Loading…
Reference in New Issue
Block a user