Support SIGHUP for reloading /etc/rtadvd.conf.

This commit is contained in:
Hiroki Sato 2011-06-11 03:25:10 +00:00
parent 52737ec557
commit 729d2abb51
5 changed files with 142 additions and 51 deletions

View File

@ -141,6 +141,33 @@ dname_labelenc(char *dst, const char *src)
memset(p, 0, sizeof(*p)); \
} while(0)
int
loadconfig(char *ifl_names[], const int ifl_len)
{
int i;
int idx;
int error;
for (i = 0; i < ifl_len; i++) {
idx = if_nametoindex(ifl_names[i]);
if (idx == 0) {
syslog(LOG_ERR,
"<%s> interface %s not found. "
"Ignored at this moment.", __func__, ifl_names[i]);
continue;
}
syslog(LOG_INFO,
"<%s> loading config for %s.", __func__, ifl_names[i]);
error = getconfig(idx);
if (error)
syslog(LOG_ERR,
"<%s> invalid configuration for %s. "
"Ignored at this moment.", __func__, ifl_names[i]);
}
return (0);
}
int
rmconfig(int idx)
{
@ -207,6 +234,7 @@ getconfig(int idx)
int stat, i;
char tbuf[BUFSIZ];
struct rainfo *rai;
struct rainfo *rai_old;
long val;
int64_t val64;
char buf[BUFSIZ];
@ -220,6 +248,10 @@ getconfig(int idx)
return (-1);
}
TAILQ_FOREACH(rai_old, &railist, rai_next)
if (idx == rai_old->rai_ifindex)
break;
if ((stat = agetent(tbuf, intface)) <= 0) {
memset(tbuf, 0, sizeof(tbuf));
syslog(LOG_INFO,
@ -254,7 +286,7 @@ getconfig(int idx)
syslog(LOG_ERR,
"<%s> can't get information of %s",
__func__, intface);
return (-1);
goto getconfig_free_rai;
}
rai->rai_ifindex = rai->rai_sdl->sdl_index;
} else
@ -280,7 +312,7 @@ getconfig(int idx)
"<%s> maxinterval (%ld) on %s is invalid "
"(must be between %u and %u)", __func__, val,
intface, MIN_MAXINTERVAL, MAX_MAXINTERVAL);
return (-1);
goto getconfig_free_rai;
}
rai->rai_maxinterval = (u_int)val;
@ -292,7 +324,7 @@ getconfig(int idx)
"(must be between %d and %d)",
__func__, val, intface, MIN_MININTERVAL,
(rai->rai_maxinterval * 3) / 4);
return (-1);
goto getconfig_free_rai;
}
rai->rai_mininterval = (u_int)val;
@ -311,7 +343,7 @@ getconfig(int idx)
if ((val & ND_RA_FLAG_RTPREF_HIGH)) {
syslog(LOG_ERR, "<%s> the \'h\' and \'l\'"
" router flags are exclusive", __func__);
return (-1);
goto getconfig_free_rai;
}
val |= ND_RA_FLAG_RTPREF_LOW;
}
@ -328,7 +360,7 @@ getconfig(int idx)
if (rai->rai_rtpref == ND_RA_FLAG_RTPREF_RSV) {
syslog(LOG_ERR, "<%s> invalid router preference (%02x) on %s",
__func__, rai->rai_rtpref, intface);
return (-1);
goto getconfig_free_rai;
}
MAYHAVE(val, "rltime", rai->rai_maxinterval * 3);
@ -339,7 +371,7 @@ getconfig(int idx)
"(must be 0 or between %d and %d)",
__func__, val, intface, rai->rai_maxinterval,
MAXROUTERLIFETIME);
return (-1);
goto getconfig_free_rai;
}
rai->rai_lifetime = val & 0xffff;
@ -349,7 +381,7 @@ getconfig(int idx)
"<%s> reachable time (%ld) on %s is invalid "
"(must be no greater than %d)",
__func__, val, intface, MAXREACHABLETIME);
return (-1);
goto getconfig_free_rai;
}
rai->rai_reachabletime = (u_int32_t)val;
@ -357,7 +389,7 @@ getconfig(int idx)
if (val64 < 0 || val64 > 0xffffffff) {
syslog(LOG_ERR, "<%s> retrans time (%lld) on %s out of range",
__func__, (long long)val64, intface);
return (-1);
goto getconfig_free_rai;
}
rai->rai_retranstimer = (u_int32_t)val64;
@ -365,7 +397,7 @@ getconfig(int idx)
syslog(LOG_ERR,
"<%s> mobile-ip6 configuration not supported",
__func__);
return (-1);
goto getconfig_free_rai;
}
/* prefix information */
@ -395,14 +427,14 @@ getconfig(int idx)
syslog(LOG_ERR,
"<%s> inet_pton failed for %s",
__func__, addr);
return (-1);
goto getconfig_free_pfx;
}
if (IN6_IS_ADDR_MULTICAST(&pfx->pfx_prefix)) {
syslog(LOG_ERR,
"<%s> multicast prefix (%s) must "
"not be advertised on %s",
__func__, addr, intface);
return (-1);
goto getconfig_free_pfx;
}
if (IN6_IS_ADDR_LINKLOCAL(&pfx->pfx_prefix))
syslog(LOG_NOTICE,
@ -416,7 +448,7 @@ getconfig(int idx)
syslog(LOG_ERR, "<%s> prefixlen (%ld) for %s "
"on %s out of range",
__func__, val, addr, intface);
return (-1);
goto getconfig_free_pfx;
}
pfx->pfx_prefixlen = (int)val;
@ -441,7 +473,7 @@ getconfig(int idx)
"%s/%d on %s is out of range",
__func__, (long long)val64,
addr, pfx->pfx_prefixlen, intface);
return (-1);
goto getconfig_free_pfx;
}
pfx->pfx_validlifetime = (u_int32_t)val64;
@ -461,7 +493,7 @@ getconfig(int idx)
"is out of range",
__func__, (long long)val64,
addr, pfx->pfx_prefixlen, intface);
return (-1);
goto getconfig_free_pfx;
}
pfx->pfx_preflifetime = (u_int32_t)val64;
@ -475,6 +507,9 @@ getconfig(int idx)
/* link into chain */
TAILQ_INSERT_TAIL(&rai->rai_prefix, pfx, pfx_next);
rai->rai_pfxs++;
continue;
getconfig_free_pfx:
free(pfx);
}
if (rai->rai_advifprefix && rai->rai_pfxs == 0)
get_prefix(rai);
@ -484,7 +519,7 @@ getconfig(int idx)
syslog(LOG_ERR,
"<%s> mtu (%ld) on %s out of range",
__func__, val, intface);
return (-1);
goto getconfig_free_rai;
}
rai->rai_linkmtu = (u_int32_t)val;
if (rai->rai_linkmtu == 0) {
@ -501,7 +536,7 @@ getconfig(int idx)
"be between least MTU (%d) and physical link MTU (%d)",
__func__, (unsigned long)rai->rai_linkmtu, intface,
IPV6_MMTU, rai->rai_phymtu);
return (-1);
goto getconfig_free_rai;
}
#ifdef SIOCSIFINFO_IN6
@ -553,14 +588,10 @@ getconfig(int idx)
/* allocate memory to store prefix information */
ELM_MALLOC(rti, exit(1));
/* link into chain */
TAILQ_INSERT_TAIL(&rai->rai_route, rti, rti_next);
rai->rai_routes++;
if (inet_pton(AF_INET6, addr, &rti->rti_prefix) != 1) {
syslog(LOG_ERR, "<%s> inet_pton failed for %s",
__func__, addr);
return (-1);
goto getconfig_free_rti;
}
#if 0
/*
@ -575,14 +606,14 @@ getconfig(int idx)
"<%s> multicast route (%s) must "
"not be advertised on %s",
__func__, addr, intface);
return (-1);
goto getconfig_free_rti;
}
if (IN6_IS_ADDR_LINKLOCAL(&rti->prefix)) {
syslog(LOG_NOTICE,
"<%s> link-local route (%s) will "
"be advertised on %s",
__func__, addr, intface);
return (-1);
goto getconfig_free_rti;
}
#endif
@ -602,7 +633,7 @@ getconfig(int idx)
syslog(LOG_ERR, "<%s> prefixlen (%ld) for %s on %s "
"out of range",
__func__, val, addr, intface);
return (-1);
goto getconfig_free_rti;
}
rti->rti_prefixlen = (int)val;
@ -617,7 +648,7 @@ getconfig(int idx)
"<%s> the \'h\' and \'l\' route"
" preferences are exclusive",
__func__);
exit(1);
goto getconfig_free_rti;
}
val |= ND_RA_FLAG_RTPREF_LOW;
}
@ -638,7 +669,7 @@ getconfig(int idx)
"for %s/%d on %s",
__func__, rti->rti_rtpref, addr,
rti->rti_prefixlen, intface);
return (-1);
goto getconfig_free_rti;
}
/*
@ -665,9 +696,16 @@ getconfig(int idx)
syslog(LOG_ERR, "<%s> route lifetime (%lld) for "
"%s/%d on %s out of range", __func__,
(long long)val64, addr, rti->rti_prefixlen, intface);
return (-1);
goto getconfig_free_rti;
}
rti->rti_ltime = (u_int32_t)val64;
/* link into chain */
TAILQ_INSERT_TAIL(&rai->rai_route, rti, rti_next);
rai->rai_routes++;
continue;
getconfig_free_rti:
free(rti);
}
#endif
/* DNS server and DNS search list information */
@ -689,12 +727,12 @@ getconfig(int idx)
c = strcspn(ap, ",");
strncpy(abuf, ap, c);
abuf[c] = '\0';
ELM_MALLOC(rdna, exit(1));
ELM_MALLOC(rdna, goto getconfig_free_rdn);
if (inet_pton(AF_INET6, abuf, &rdna->ra_dns) != 1) {
syslog(LOG_ERR, "<%s> inet_pton failed for %s",
__func__, abuf);
free(rdna);
return (-1);
goto getconfig_free_rdn;
}
TAILQ_INSERT_TAIL(&rdn->rd_list, rdna, ra_next);
}
@ -707,12 +745,19 @@ getconfig(int idx)
"(must be between %d and %d)",
entbuf, val, intface, rai->rai_maxinterval,
rai->rai_maxinterval * 2);
return (-1);
goto getconfig_free_rdn;
}
rdn->rd_ltime = val;
/* link into chain */
TAILQ_INSERT_TAIL(&rai->rai_rdnss, rdn, rd_next);
continue;
getconfig_free_rdn:
while ((rdna = TAILQ_FIRST(&rdn->rd_list)) != NULL) {
TAILQ_REMOVE(&rdn->rd_list, rdna, ra_next);
free(rdna);
}
free(rdn);
}
for (i = -1; i < MAXDNSSLENT ; i++) {
@ -734,7 +779,7 @@ getconfig(int idx)
c = strcspn(ap, ",");
strncpy(abuf, ap, c);
abuf[c] = '\0';
ELM_MALLOC(dnsa, exit(1));
ELM_MALLOC(dnsa, goto getconfig_free_dns);
dnsa->da_len = dname_labelenc(dnsa->da_dom, abuf);
syslog(LOG_DEBUG, "<%s>: dnsa->da_len = %d", __func__,
dnsa->da_len);
@ -749,15 +794,46 @@ getconfig(int idx)
"(must be between %d and %d)",
entbuf, val, intface, rai->rai_maxinterval,
rai->rai_maxinterval * 2);
return (-1);
goto getconfig_free_dns;
}
dns->dn_ltime = val;
/* link into chain */
TAILQ_INSERT_TAIL(&rai->rai_dnssl, dns, dn_next);
continue;
getconfig_free_dns:
while ((dnsa = TAILQ_FIRST(&dns->dn_list)) != NULL) {
TAILQ_REMOVE(&dns->dn_list, dnsa, da_next);
free(dnsa);
}
free(dns);
}
/* construct the sending packet */
make_packet(rai);
/*
* If an entry with the same ifindex exists, remove it first.
* 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;
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);
}
rmconfig(idx);
}
TAILQ_INSERT_TAIL(&railist, rai, rai_next);
/* set timer */
@ -767,6 +843,9 @@ getconfig(int idx)
rtadvd_set_timer(&rai->rai_timer->rat_tm, rai->rai_timer);
return (0);
getconfig_free_rai:
free(rai);
return (-1);
}
void

View File

@ -32,6 +32,7 @@
extern int getconfig(int);
extern int rmconfig(int);
extern int loadconfig(char *[], const int);
extern void delete_prefix(struct prefix *);
extern void invalidate_prefix(struct prefix *);
extern void update_prefix(struct prefix *);

View File

@ -169,6 +169,18 @@ or the file specified with option
.Fl F .
.Pp
Use
.Dv SIGHUP
to reload the configuration file
.Pa /etc/rtadvd.conf .
If an invalid parameter is found in the configuration file upon the reload,
the entry will be ignored and the old configuration will be used.
When parameters in an existing entry are updated,
.Nm
will send Router Advertisement messages with the old configuration but
zero router lifetime to the interface first, and then start to send a new
message.
.Pp
Use
.Dv SIGTERM
to kill
.Nm

View File

@ -83,6 +83,7 @@ static u_char *sndcmsgbuf = NULL;
static size_t sndcmsgbuflen;
volatile sig_atomic_t do_dump;
volatile sig_atomic_t do_die;
volatile sig_atomic_t do_reload;
struct msghdr sndmhdr;
struct iovec rcviov[2];
struct iovec sndiov[2];
@ -161,6 +162,7 @@ struct sockaddr_in6 sin6_sitelocal_allrouters = {
.sin6_addr = IN6ADDR_SITELOCAL_ALLROUTERS_INIT,
};
static void set_reload(int);
static void set_die(int);
static void die(void);
static void sock_open(void);
@ -175,7 +177,6 @@ static int prefix_check(struct nd_opt_prefix_info *, struct rainfo *,
static int nd6_options(struct nd_opt_hdr *, int,
union nd_opt *, u_int32_t);
static void free_ndopts(union nd_opt *);
static void ra_output(struct rainfo *);
static void rtmsg_input(void);
static void rtadvd_set_dump_file(int);
static void set_short_delay(struct rainfo *);
@ -197,7 +198,6 @@ main(int argc, char *argv[])
int i, ch;
int fflag = 0, logopt;
pid_t pid, otherpid;
int error;
/* get command line options and arguments */
while ((ch = getopt(argc, argv, "c:dDfF:M:p:Rs")) != -1) {
@ -273,22 +273,7 @@ main(int argc, char *argv[])
ifl_names = argv;
ifl_len = argc;
for (i = 0; i < ifl_len; i++) {
int idx;
idx = if_nametoindex(ifl_names[i]);
if (idx == 0) {
syslog(LOG_INFO,
"<%s> interface %s not found."
"Ignored at this moment.", __func__, ifl_names[i]);
continue;
}
error = getconfig(idx);
if (error)
syslog(LOG_INFO,
"<%s> invalid configuration for %s."
"Ignored at this moment.", __func__, ifl_names[i]);
}
loadconfig(argv, argc);
pfh = pidfile_open(pidfilename, 0600, &otherpid);
if (pfh == NULL) {
@ -343,6 +328,7 @@ main(int argc, char *argv[])
#endif
signal(SIGTERM, set_die);
signal(SIGUSR1, rtadvd_set_dump_file);
signal(SIGHUP, set_reload);
while (1) {
#ifndef HAVE_POLL_H
@ -358,6 +344,11 @@ main(int argc, char *argv[])
/*NOTREACHED*/
}
if (do_reload) {
loadconfig(argv, argc);
do_reload = 0;
}
/* timer expiration check and reset the timer */
timeout = rtadvd_check_timer();
@ -420,6 +411,13 @@ rtadvd_set_dump_file(int sig __unused)
do_dump = 1;
}
static void
set_reload(int sig __unused)
{
do_reload = 1;
}
static void
set_die(int sig __unused)
{
@ -1698,7 +1696,7 @@ if_indextorainfo(int idx)
return (NULL); /* search failed */
}
static void
void
ra_output(struct rainfo *rai)
{
int i;

View File

@ -233,6 +233,7 @@ extern TAILQ_HEAD(railist_head_t, rainfo) railist;
struct rtadvd_timer *ra_timeout(void *);
void ra_timer_update(void *, struct timeval *);
void ra_output(struct rainfo *);
int prefix_match(struct in6_addr *, int,
struct in6_addr *, int);