- Add ":origin" label to the interface id for resolvconf(8). (r223149)
- Add -u option to enable adding :[RA-source-address] to the interface id. (r223149) - s/INET6_ADDRSTRLEN/sizeof(ntopbuf)/ (r223149) - Fix a bug that can prevent -D from being overridden by -d. (r223149) - /-P pidfile/-p pidfile/ for consistency with rtadvd(8). (r223149) - Fix -F flag handling to support receiving RAs even when ip6.forwarding=1. (r225150) Approved by: re (kib)
This commit is contained in:
parent
aed378729e
commit
489e04d0da
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=225520
@ -73,6 +73,7 @@ static struct sockaddr_in6 from;
|
||||
static int rcvcmsglen;
|
||||
|
||||
int rssock;
|
||||
static char rsid[IFNAMSIZ + 1 + sizeof(DNSINFO_ORIGIN_LABEL) + 1 + NI_MAXHOST];
|
||||
struct ifinfo_head_t ifinfo_head =
|
||||
TAILQ_HEAD_INITIALIZER(ifinfo_head);
|
||||
|
||||
@ -82,14 +83,18 @@ static const struct sockaddr_in6 sin6_allrouters = {
|
||||
.sin6_addr = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT,
|
||||
};
|
||||
|
||||
static void call_script(const int, const char *const *, void *);
|
||||
static void call_script(const int, const char *const *,
|
||||
struct script_msg_head_t *);
|
||||
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);
|
||||
static int ra_opt_rdnss_dispatch(struct ifinfo *, struct rainfo *,
|
||||
struct script_msg_head_t *, struct script_msg_head_t *);
|
||||
static char *make_rsid(const char *, const char *, struct rainfo *);
|
||||
|
||||
#define _ARGS_OTHER otherconf_script, ifi->ifname
|
||||
#define _ARGS_RESADD resolvconf_script, "-a", ifi->ifname
|
||||
#define _ARGS_RESDEL resolvconf_script, "-d", ifi->ifname
|
||||
#define _ARGS_RESADD resolvconf_script, "-a", rsid
|
||||
#define _ARGS_RESDEL resolvconf_script, "-d", rsid
|
||||
|
||||
#define CALL_SCRIPT(name, sm_head) \
|
||||
do { \
|
||||
@ -306,7 +311,7 @@ rtsol_input(int s)
|
||||
warnmsg(LOG_ERR, __func__,
|
||||
"invalid icmp type(%d) from %s on %s", icp->icmp6_type,
|
||||
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
|
||||
INET6_ADDRSTRLEN),
|
||||
sizeof(ntopbuf)),
|
||||
if_indextoname(pi->ipi6_ifindex, ifnamebuf));
|
||||
return;
|
||||
}
|
||||
@ -315,7 +320,7 @@ rtsol_input(int s)
|
||||
warnmsg(LOG_INFO, __func__,
|
||||
"invalid icmp code(%d) from %s on %s", icp->icmp6_code,
|
||||
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
|
||||
INET6_ADDRSTRLEN),
|
||||
sizeof(ntopbuf)),
|
||||
if_indextoname(pi->ipi6_ifindex, ifnamebuf));
|
||||
return;
|
||||
}
|
||||
@ -325,7 +330,7 @@ rtsol_input(int s)
|
||||
"invalid RA with hop limit(%d) from %s on %s",
|
||||
*hlimp,
|
||||
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
|
||||
INET6_ADDRSTRLEN),
|
||||
sizeof(ntopbuf)),
|
||||
if_indextoname(pi->ipi6_ifindex, ifnamebuf));
|
||||
return;
|
||||
}
|
||||
@ -334,7 +339,7 @@ rtsol_input(int s)
|
||||
warnmsg(LOG_INFO, __func__,
|
||||
"invalid RA with non link-local source from %s on %s",
|
||||
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
|
||||
INET6_ADDRSTRLEN),
|
||||
sizeof(ntopbuf)),
|
||||
if_indextoname(pi->ipi6_ifindex, ifnamebuf));
|
||||
return;
|
||||
}
|
||||
@ -345,14 +350,14 @@ rtsol_input(int s)
|
||||
warnmsg(LOG_INFO, __func__,
|
||||
"received RA from %s on an unexpected IF(%s)",
|
||||
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf,
|
||||
INET6_ADDRSTRLEN),
|
||||
sizeof(ntopbuf)),
|
||||
if_indextoname(pi->ipi6_ifindex, ifnamebuf));
|
||||
return;
|
||||
}
|
||||
|
||||
warnmsg(LOG_DEBUG, __func__,
|
||||
"received RA from %s on %s, state is %d",
|
||||
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, INET6_ADDRSTRLEN),
|
||||
inet_ntop(AF_INET6, &from.sin6_addr, ntopbuf, sizeof(ntopbuf)),
|
||||
ifi->ifname, ifi->state);
|
||||
|
||||
nd_ra = (struct nd_router_advert *)icp;
|
||||
@ -378,6 +383,8 @@ rtsol_input(int s)
|
||||
ELM_MALLOC(rai, exit(1));
|
||||
rai->rai_ifinfo = ifi;
|
||||
TAILQ_INIT(&rai->rai_ra_opt);
|
||||
rai->rai_saddr.sin6_family = AF_INET6;
|
||||
rai->rai_saddr.sin6_len = sizeof(rai->rai_saddr);
|
||||
memcpy(&rai->rai_saddr.sin6_addr, &from.sin6_addr,
|
||||
sizeof(rai->rai_saddr.sin6_addr));
|
||||
newent_rai = 1;
|
||||
@ -406,19 +413,19 @@ rtsol_input(int s)
|
||||
"too short RDNSS option"
|
||||
"in RA from %s was ignored.",
|
||||
inet_ntop(AF_INET6, &from.sin6_addr,
|
||||
ntopbuf, INET6_ADDRSTRLEN));
|
||||
ntopbuf, sizeof(ntopbuf)));
|
||||
break;
|
||||
}
|
||||
|
||||
addr = (struct in6_addr *)(raoptp + sizeof(*rdnss));
|
||||
while ((char *)addr < (char *)RA_OPT_NEXT_HDR(raoptp)) {
|
||||
if (inet_ntop(AF_INET6, addr, ntopbuf,
|
||||
INET6_ADDRSTRLEN) == NULL) {
|
||||
sizeof(ntopbuf)) == NULL) {
|
||||
warnmsg(LOG_INFO, __func__,
|
||||
"an invalid address in RDNSS option"
|
||||
" in RA from %s was ignored.",
|
||||
inet_ntop(AF_INET6, &from.sin6_addr,
|
||||
ntopbuf, INET6_ADDRSTRLEN));
|
||||
ntopbuf, sizeof(ntopbuf)));
|
||||
addr++;
|
||||
continue;
|
||||
}
|
||||
@ -482,7 +489,7 @@ rtsol_input(int s)
|
||||
"too short DNSSL option"
|
||||
"in RA from %s was ignored.",
|
||||
inet_ntop(AF_INET6, &from.sin6_addr,
|
||||
ntopbuf, INET6_ADDRSTRLEN));
|
||||
ntopbuf, sizeof(ntopbuf)));
|
||||
break;
|
||||
}
|
||||
|
||||
@ -568,10 +575,11 @@ ra_opt_handler(struct ifinfo *ifi)
|
||||
struct rainfo *rai;
|
||||
struct script_msg *smp1, *smp2, *smp3;
|
||||
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);
|
||||
struct script_msg_head_t sm_rdnss_head =
|
||||
TAILQ_HEAD_INITIALIZER(sm_rdnss_head);
|
||||
struct script_msg_head_t sm_dnssl_head =
|
||||
TAILQ_HEAD_INITIALIZER(sm_dnssl_head);
|
||||
|
||||
int dcount, dlen;
|
||||
|
||||
dcount = 0;
|
||||
@ -658,17 +666,69 @@ ra_opt_handler(struct ifinfo *ifi)
|
||||
free1:
|
||||
free(smp1);
|
||||
}
|
||||
/* Call the script for each information source. */
|
||||
if (uflag)
|
||||
ra_opt_rdnss_dispatch(ifi, rai, &sm_rdnss_head,
|
||||
&sm_dnssl_head);
|
||||
}
|
||||
/* Add \n for DNSSL list. */
|
||||
if (!TAILQ_EMPTY(&sm_dnssl_head)) {
|
||||
ELM_MALLOC(smp1, goto ra_opt_handler_freeit);
|
||||
smp1->sm_msg = resstr_nl;
|
||||
TAILQ_INSERT_TAIL(&sm_dnssl_head, smp1, sm_next);
|
||||
}
|
||||
TAILQ_CONCAT(&sm_rdnss_head, &sm_dnssl_head, sm_next);
|
||||
/* Call the script for each interface. */
|
||||
if (!uflag)
|
||||
ra_opt_rdnss_dispatch(ifi, NULL, &sm_rdnss_head,
|
||||
&sm_dnssl_head);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (!TAILQ_EMPTY(&sm_rdnss_head))
|
||||
CALL_SCRIPT(RESADD, &sm_rdnss_head);
|
||||
char *
|
||||
make_rsid(const char *ifname, const char *origin, struct rainfo *rai)
|
||||
{
|
||||
char hbuf[NI_MAXHOST];
|
||||
|
||||
if (rai == NULL)
|
||||
sprintf(rsid, "%s:%s", ifname, origin);
|
||||
else {
|
||||
if (!IN6_IS_ADDR_LINKLOCAL(&rai->rai_saddr.sin6_addr))
|
||||
return (NULL);
|
||||
if (getnameinfo((struct sockaddr *)&rai->rai_saddr,
|
||||
rai->rai_saddr.sin6_len, hbuf, sizeof(hbuf), NULL, 0,
|
||||
NI_NUMERICHOST) != 0)
|
||||
return (NULL);
|
||||
sprintf(rsid, "%s:%s:[%s]", ifname, origin, hbuf);
|
||||
}
|
||||
warnmsg(LOG_DEBUG, __func__, "rsid = [%s]", rsid);
|
||||
return (rsid);
|
||||
}
|
||||
|
||||
int
|
||||
ra_opt_rdnss_dispatch(struct ifinfo *ifi,
|
||||
struct rainfo *rai,
|
||||
struct script_msg_head_t *sm_rdnss_head,
|
||||
struct script_msg_head_t *sm_dnssl_head)
|
||||
{
|
||||
const char *r;
|
||||
struct script_msg *smp1;
|
||||
int error;
|
||||
|
||||
error = 0;
|
||||
/* Add \n for DNSSL list. */
|
||||
if (!TAILQ_EMPTY(sm_dnssl_head)) {
|
||||
ELM_MALLOC(smp1, goto ra_opt_rdnss_freeit);
|
||||
smp1->sm_msg = resstr_nl;
|
||||
TAILQ_INSERT_TAIL(sm_dnssl_head, smp1, sm_next);
|
||||
}
|
||||
TAILQ_CONCAT(sm_rdnss_head, sm_dnssl_head, sm_next);
|
||||
|
||||
if (rai != NULL && uflag)
|
||||
r = make_rsid(ifi->ifname, DNSINFO_ORIGIN_LABEL, rai);
|
||||
else
|
||||
r = make_rsid(ifi->ifname, DNSINFO_ORIGIN_LABEL, NULL);
|
||||
if (r == NULL) {
|
||||
warnmsg(LOG_ERR, __func__, "make_rsid() failed. "
|
||||
"Script was not invoked.");
|
||||
error = 1;
|
||||
goto ra_opt_rdnss_freeit;
|
||||
}
|
||||
if (!TAILQ_EMPTY(sm_rdnss_head))
|
||||
CALL_SCRIPT(RESADD, sm_rdnss_head);
|
||||
else if (ifi->ifi_rdnss == IFI_DNSOPT_STATE_RECEIVED ||
|
||||
ifi->ifi_dnssl == IFI_DNSOPT_STATE_RECEIVED) {
|
||||
CALL_SCRIPT(RESDEL, NULL);
|
||||
@ -676,21 +736,21 @@ ra_opt_handler(struct ifinfo *ifi)
|
||||
ifi->ifi_dnssl = IFI_DNSOPT_STATE_NOINFO;
|
||||
}
|
||||
|
||||
ra_opt_handler_freeit:
|
||||
ra_opt_rdnss_freeit:
|
||||
/* Clear script message queue. */
|
||||
if (!TAILQ_EMPTY(&sm_rdnss_head)) {
|
||||
while ((smp1 = TAILQ_FIRST(&sm_rdnss_head)) != NULL) {
|
||||
TAILQ_REMOVE(&sm_rdnss_head, smp1, sm_next);
|
||||
if (!TAILQ_EMPTY(sm_rdnss_head)) {
|
||||
while ((smp1 = TAILQ_FIRST(sm_rdnss_head)) != NULL) {
|
||||
TAILQ_REMOVE(sm_rdnss_head, smp1, sm_next);
|
||||
free(smp1);
|
||||
}
|
||||
}
|
||||
if (!TAILQ_EMPTY(&sm_dnssl_head)) {
|
||||
while ((smp1 = TAILQ_FIRST(&sm_dnssl_head)) != NULL) {
|
||||
TAILQ_REMOVE(&sm_dnssl_head, smp1, sm_next);
|
||||
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);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static struct ra_opt *
|
||||
@ -709,19 +769,18 @@ find_raopt(struct rainfo *rai, int type, void *msg, size_t len)
|
||||
}
|
||||
|
||||
static void
|
||||
call_script(const int argc, const char *const argv[], void *head)
|
||||
call_script(const int argc, const char *const argv[],
|
||||
struct script_msg_head_t *sm_head)
|
||||
{
|
||||
const char *scriptpath;
|
||||
int fd[2];
|
||||
int error;
|
||||
pid_t pid, wpid;
|
||||
TAILQ_HEAD(, script_msg) *sm_head;
|
||||
|
||||
if ((scriptpath = argv[0]) == NULL)
|
||||
return;
|
||||
|
||||
fd[0] = fd[1] = -1;
|
||||
sm_head = head;
|
||||
if (sm_head != NULL && !TAILQ_EMPTY(sm_head)) {
|
||||
error = pipe(fd);
|
||||
if (error) {
|
||||
|
@ -29,7 +29,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd May 28, 2011
|
||||
.Dd June 14, 2011
|
||||
.Dt RTSOLD 8
|
||||
.Os
|
||||
.\"
|
||||
@ -39,24 +39,24 @@
|
||||
.\"
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl dDfFm1
|
||||
.Op Fl dDfFmu1
|
||||
.Op Fl O Ar script-name
|
||||
.Op Fl P Ar pidfile
|
||||
.Op Fl p Ar pidfile
|
||||
.Op Fl R Ar script-name
|
||||
.Ar interface ...
|
||||
.Nm
|
||||
.Op Fl dDfFm1
|
||||
.Op Fl dDfFmu1
|
||||
.Op Fl O Ar script-name
|
||||
.Op Fl P Ar pidfile
|
||||
.Op Fl p Ar pidfile
|
||||
.Op Fl R Ar script-name
|
||||
.Fl a
|
||||
.Nm rtsol
|
||||
.Op Fl dD
|
||||
.Op Fl dDu
|
||||
.Op Fl O Ar script-name
|
||||
.Op Fl R Ar script-name
|
||||
.Ar interface ...
|
||||
.Nm rtsol
|
||||
.Op Fl dD
|
||||
.Op Fl dDu
|
||||
.Op Fl O Ar script-name
|
||||
.Op Fl R Ar script-name
|
||||
.Fl a
|
||||
@ -227,7 +227,7 @@ configuration.
|
||||
must be the absolute path from root to the script file, be a regular
|
||||
file, and be created by the same owner who runs
|
||||
.Nm .
|
||||
.It Fl P Ar pidfile
|
||||
.It Fl p Ar pidfile
|
||||
Writes the process ID of
|
||||
.Nm
|
||||
to
|
||||
@ -245,6 +245,18 @@ standard input of this script.
|
||||
The
|
||||
.Xr resolvconf 8
|
||||
script is used by default.
|
||||
.It Fl u
|
||||
Specifies whether adding the source address of Router Advertisement
|
||||
messages to the interface name in an argument of the RDNSS and DNSSL
|
||||
script.
|
||||
.Pp
|
||||
If
|
||||
.Fl u
|
||||
is specified, the interface name in the script argument will be
|
||||
.Ql ifname:slaac:[RA-source-address] .
|
||||
.Pp
|
||||
If not, it will be
|
||||
.Ql ifname:slaac .
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/run/rtsold.dump -compact
|
||||
|
@ -75,6 +75,7 @@ static int fflag = 0;
|
||||
int Fflag = 0; /* force setting sysctl parameters */
|
||||
int aflag = 0;
|
||||
int dflag = 0;
|
||||
int uflag = 0;
|
||||
|
||||
const char *otherconf_script;
|
||||
const char *resolvconf_script = "/sbin/resolvconf";
|
||||
@ -129,10 +130,10 @@ main(int argc, char **argv)
|
||||
|
||||
#ifndef SMALL
|
||||
/* rtsold */
|
||||
opts = "adDfFm1O:P:R:";
|
||||
opts = "adDfFm1O:p:R:u";
|
||||
#else
|
||||
/* rtsol */
|
||||
opts = "adDFO:P:R:";
|
||||
opts = "adDFO:R:u";
|
||||
fflag = 1;
|
||||
once = 1;
|
||||
#endif
|
||||
@ -144,10 +145,10 @@ main(int argc, char **argv)
|
||||
aflag = 1;
|
||||
break;
|
||||
case 'd':
|
||||
dflag = 1;
|
||||
dflag += 1;
|
||||
break;
|
||||
case 'D':
|
||||
dflag = 2;
|
||||
dflag += 2;
|
||||
break;
|
||||
case 'f':
|
||||
fflag = 1;
|
||||
@ -164,12 +165,15 @@ main(int argc, char **argv)
|
||||
case 'O':
|
||||
otherconf_script = optarg;
|
||||
break;
|
||||
case 'P':
|
||||
case 'p':
|
||||
pidfilename = optarg;
|
||||
break;
|
||||
case 'R':
|
||||
resolvconf_script = optarg;
|
||||
break;
|
||||
case 'u':
|
||||
uflag = 1;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
exit(1);
|
||||
@ -184,8 +188,13 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
/* set log level */
|
||||
if (dflag == 0)
|
||||
if (dflag > 1)
|
||||
log_upto = LOG_DEBUG;
|
||||
else if (dflag > 0)
|
||||
log_upto = LOG_INFO;
|
||||
else
|
||||
log_upto = LOG_NOTICE;
|
||||
|
||||
if (!fflag) {
|
||||
char *ident;
|
||||
|
||||
@ -216,6 +225,7 @@ main(int argc, char **argv)
|
||||
srandom((u_long)time(NULL));
|
||||
#endif
|
||||
|
||||
#if (__FreeBSD_version < 900000)
|
||||
if (Fflag) {
|
||||
setinet6sysctl(IPV6CTL_FORWARDING, 0);
|
||||
} else {
|
||||
@ -223,6 +233,7 @@ main(int argc, char **argv)
|
||||
if (getinet6sysctl(IPV6CTL_FORWARDING))
|
||||
warnx("kernel is configured as a router, not a host");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SMALL
|
||||
/* initialization to dump internal status to a file */
|
||||
@ -402,6 +413,32 @@ ifconfig(char *ifname)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (Fflag) {
|
||||
struct in6_ndireq nd;
|
||||
int s;
|
||||
|
||||
if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
|
||||
warnmsg(LOG_ERR, __func__, "socket() failed.");
|
||||
return (-1);
|
||||
}
|
||||
memset(&nd, 0, sizeof(nd));
|
||||
strlcpy(nd.ifname, ifname, sizeof(nd.ifname));
|
||||
if (ioctl(s, SIOCGIFINFO_IN6, (caddr_t)&nd) < 0) {
|
||||
warnmsg(LOG_ERR, __func__,
|
||||
"cannot get accept_rtadv flag");
|
||||
close(s);
|
||||
return (-1);
|
||||
}
|
||||
nd.ndi.flags |= ND6_IFF_ACCEPT_RTADV;
|
||||
if (ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd) < 0) {
|
||||
warnmsg(LOG_ERR, __func__,
|
||||
"cannot set accept_rtadv flag");
|
||||
close(s);
|
||||
return (-1);
|
||||
}
|
||||
close(s);
|
||||
}
|
||||
|
||||
if ((ifi = malloc(sizeof(*ifi))) == NULL) {
|
||||
warnmsg(LOG_ERR, __func__, "memory allocation failed");
|
||||
free(sdl);
|
||||
|
@ -37,6 +37,8 @@ struct script_msg {
|
||||
char *sm_msg;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(script_msg_head_t, script_msg);
|
||||
|
||||
struct ra_opt {
|
||||
TAILQ_ENTRY(ra_opt) rao_next;
|
||||
|
||||
@ -60,7 +62,7 @@ struct ifinfo {
|
||||
TAILQ_ENTRY(ifinfo) ifi_next; /* pointer to the next interface */
|
||||
|
||||
struct sockaddr_dl *sdl; /* link-layer address */
|
||||
char ifname[IF_NAMESIZE]; /* interface name */
|
||||
char ifname[IFNAMSIZ]; /* interface name */
|
||||
u_int32_t linkid; /* link ID of this interface */
|
||||
int active; /* interface status */
|
||||
int probeinterval; /* interval of probe timer (if necessary) */
|
||||
@ -96,6 +98,7 @@ struct ifinfo {
|
||||
/* Interface list */
|
||||
extern TAILQ_HEAD(ifinfo_head_t, ifinfo) ifinfo_head;
|
||||
|
||||
#define DNSINFO_ORIGIN_LABEL "slaac"
|
||||
/*
|
||||
* RFC 3542 API deprecates IPV6_PKTINFO in favor of
|
||||
* IPV6_RECVPKTINFO
|
||||
@ -126,6 +129,7 @@ extern struct timeval tm_max;
|
||||
extern int dflag;
|
||||
extern int aflag;
|
||||
extern int Fflag;
|
||||
extern int uflag;
|
||||
extern const char *otherconf_script;
|
||||
extern const char *resolvconf_script;
|
||||
extern int ifconfig(char *);
|
||||
|
Loading…
Reference in New Issue
Block a user