Let rad(8) handle all rdomains in a single daemon, similar to previous
work in slaacd.
Suggested / requested by tb who showed me previous work by reyk which
unfortunately predated my work in slaacd and followed a different
pattern.
There has already been a fair bit of testing and input from tb on
previous iterations.
More tests, OKs?
diff --git frontend.c frontend.c
index 8947f616e73..014e5700588 100644
--- frontend.c
+++ frontend.c
@@ -95,19 +95,22 @@ struct icmp6_ev {
struct msghdr rcvmhdr;
struct iovec rcviov[1];
struct sockaddr_in6 from;
-} icmp6ev;
+ int refcnt;
+};
struct ra_iface {
- TAILQ_ENTRY(ra_iface) entry;
- struct ra_prefix_conf_head prefixes;
- char name[IF_NAMESIZE];
- char conf_name[IF_NAMESIZE];
- uint32_t if_index;
- int removed;
- int link_state;
- int prefix_count;
- size_t datalen;
- uint8_t data[RA_MAX_SIZE];
+ TAILQ_ENTRY(ra_iface) entry;
+ struct icmp6_ev *icmp6ev;
+ struct ra_prefix_conf_head prefixes;
+ char name[IF_NAMESIZE];
+ char conf_name[IF_NAMESIZE];
+ uint32_t if_index;
+ int rdomain;
+ int removed;
+ int link_state;
+ int prefix_count;
+ size_t datalen;
+ uint8_t data[RA_MAX_SIZE];
};
TAILQ_HEAD(, ra_iface) ra_interfaces;
@@ -119,6 +122,7 @@ void icmp6_receive(int, short, void
*);
void join_all_routers_mcast_group(struct ra_iface *);
void leave_all_routers_mcast_group(struct ra_iface *);
int get_link_state(char *);
+int get_ifrdomain(char *);
void merge_ra_interface(char *, char *);
void merge_ra_interfaces(void);
struct ra_iface *find_ra_iface_by_id(uint32_t);
@@ -127,6 +131,9 @@ struct ra_iface_conf *find_ra_iface_conf(struct
ra_iface_conf_head *,
char *);
struct ra_prefix_conf *find_ra_prefix_conf(struct ra_prefix_conf_head*,
struct in6_addr *, int);
+struct icmp6_ev *get_icmp6ev_by_rdomain(int);
+void unref_icmp6ev(struct ra_iface *);
+void set_icmp6sock(int, int);
void add_new_prefix_to_ra_iface(struct ra_iface *r,
struct in6_addr *, int, struct ra_prefix_conf *);
void free_ra_iface(struct ra_iface *);
@@ -147,7 +154,7 @@ struct rad_conf *frontend_conf;
struct imsgev *iev_main;
struct imsgev *iev_engine;
struct event ev_route;
-int icmp6sock = -1, ioctlsock = -1, routesock = -1;
+int ioctlsock = -1, routesock = -1;
struct ipv6_mreq all_routers;
struct sockaddr_in6 all_nodes;
struct msghdr sndmhdr;
@@ -175,8 +182,7 @@ frontend(int debug, int verbose)
{
struct event ev_sigint, ev_sigterm;
struct passwd *pw;
- size_t rcvcmsglen, sndcmsgbuflen;
- uint8_t *rcvcmsgbuf;
+ size_t sndcmsgbuflen;
uint8_t *sndcmsgbuf = NULL;
frontend_conf = config_new_empty();
@@ -229,20 +235,6 @@ frontend(int debug, int verbose)
iev_main->handler, iev_main);
event_add(&iev_main->ev, NULL);
- rcvcmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
- CMSG_SPACE(sizeof(int));
- if((rcvcmsgbuf = malloc(rcvcmsglen)) == NULL)
- fatal("malloc");
-
- icmp6ev.rcviov[0].iov_base = (caddr_t)icmp6ev.answer;
- icmp6ev.rcviov[0].iov_len = sizeof(icmp6ev.answer);
- icmp6ev.rcvmhdr.msg_name = (caddr_t)&icmp6ev.from;
- icmp6ev.rcvmhdr.msg_namelen = sizeof(icmp6ev.from);
- icmp6ev.rcvmhdr.msg_iov = icmp6ev.rcviov;
- icmp6ev.rcvmhdr.msg_iovlen = 1;
- icmp6ev.rcvmhdr.msg_control = (caddr_t) rcvcmsgbuf;
- icmp6ev.rcvmhdr.msg_controllen = rcvcmsglen;
-
if (inet_pton(AF_INET6, "ff02::2",
&all_routers.ipv6mr_multiaddr.s6_addr) == -1)
fatal("inet_pton");
@@ -316,7 +308,7 @@ frontend_dispatch_main(int fd, short event, void *bula)
struct ra_prefix_conf *ra_prefix_conf;
struct ra_rdnss_conf *ra_rdnss_conf;
struct ra_dnssl_conf *ra_dnssl_conf;
- int n, shut = 0;
+ int n, shut = 0, icmp6sock, rdomain;
if (event & EV_READ) {
if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
@@ -414,7 +406,7 @@ frontend_dispatch_main(int fd, short event, void *bula)
ra_prefix_conf))
fatalx("%s: IMSG_RECONF_RA_PREFIX wrong "
"length: %lu", __func__,
- IMSG_DATA_SIZE(imsg));
+ IMSG_DATA_SIZE(imsg));
if ((ra_prefix_conf = malloc(sizeof(struct
ra_prefix_conf))) == NULL)
fatal(NULL);
@@ -458,15 +450,15 @@ frontend_dispatch_main(int fd, short event, void *bula)
nconf = NULL;
break;
case IMSG_ICMP6SOCK:
- if (icmp6sock != -1)
- fatalx("%s: received unexpected icmp6 fd",
- __func__);
if ((icmp6sock = imsg.fd) == -1)
fatalx("%s: expected to receive imsg "
"ICMPv6 fd but didn't receive any",
__func__);
- event_set(&icmp6ev.ev, icmp6sock, EV_READ | EV_PERSIST,
- icmp6_receive, NULL);
+ if (IMSG_DATA_SIZE(imsg) != sizeof(rdomain))
+ fatalx("%s: IMSG_ICMP6SOCK wrong length: "
+ "%lu", __func__, IMSG_DATA_SIZE(imsg));
+ memcpy(&rdomain, imsg.data, sizeof(rdomain));
+ set_icmp6sock(icmp6sock, rdomain);
break;
case IMSG_ROUTESOCK:
if (routesock != -1)
@@ -480,8 +472,6 @@ frontend_dispatch_main(int fd, short event, void *bula)
route_receive, NULL);
break;
case IMSG_STARTUP:
- if (pledge("stdio inet unix route mcast", NULL) == -1)
- fatal("pledge");
frontend_startup();
break;
case IMSG_CONTROLFD:
@@ -588,20 +578,14 @@ frontend_startup(void)
"process", __func__);
event_add(&ev_route, NULL);
-
- if (!event_initialized(&icmp6ev.ev))
- fatalx("%s: did not receive a icmp6 socket fd from the main "
- "process", __func__);
-
- event_add(&icmp6ev.ev, NULL);
-
- frontend_imsg_compose_main(IMSG_STARTUP_DONE, 0, NULL, 0);
}
void
icmp6_receive(int fd, short events, void *arg)
{
+ struct icmp6_ev *icmp6ev;
+ struct icmp6_hdr *icmp6_hdr;
struct imsg_ra_rs ra_rs;
struct in6_pktinfo *pi = NULL;
struct cmsghdr *cm;
@@ -609,14 +593,23 @@ icmp6_receive(int fd, short events, void *arg)
int if_index = 0, *hlimp = NULL;
char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ];
- if ((len = recvmsg(fd, &icmp6ev.rcvmhdr, 0)) == -1) {
+ icmp6ev = arg;
+ if ((len = recvmsg(fd, &icmp6ev->rcvmhdr, 0)) == -1) {
log_warn("recvmsg");
return;
}
+ if ((size_t)len < sizeof(struct icmp6_hdr))
+ return;
+
+ icmp6_hdr = (struct icmp6_hdr *)icmp6ev->answer;
+ if (icmp6_hdr->icmp6_type != ND_ROUTER_ADVERT &&
+ icmp6_hdr->icmp6_type != ND_ROUTER_SOLICIT)
+ return;
+
/* extract optional information via Advanced API */
- for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&icmp6ev.rcvmhdr); cm;
- cm = (struct cmsghdr *)CMSG_NXTHDR(&icmp6ev.rcvmhdr, cm)) {
+ for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&icmp6ev->rcvmhdr); cm;
+ cm = (struct cmsghdr *)CMSG_NXTHDR(&icmp6ev->rcvmhdr, cm)) {
if (cm->cmsg_level == IPPROTO_IPV6 &&
cm->cmsg_type == IPV6_PKTINFO &&
cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) {
@@ -641,29 +634,29 @@ icmp6_receive(int fd, short events, void *arg)
if (*hlimp != 255) {
log_warnx("invalid RA or RS with hop limit of %d from %s on %s",
- *hlimp, inet_ntop(AF_INET6, &icmp6ev.from.sin6_addr,
+ *hlimp, inet_ntop(AF_INET6, &icmp6ev->from.sin6_addr,
ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index,
ifnamebuf));
return;
}
log_debug("RA or RS with hop limit of %d from %s on %s",
- *hlimp, inet_ntop(AF_INET6, &icmp6ev.from.sin6_addr,
+ *hlimp, inet_ntop(AF_INET6, &icmp6ev->from.sin6_addr,
ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index,
ifnamebuf));
if ((size_t)len > sizeof(ra_rs.packet)) {
log_warnx("invalid RA or RS with size %ld from %s on %s",
- len, inet_ntop(AF_INET6, &icmp6ev.from.sin6_addr,
+ len, inet_ntop(AF_INET6, &icmp6ev->from.sin6_addr,
ntopbuf, INET6_ADDRSTRLEN), if_indextoname(if_index,
ifnamebuf));
return;
}
ra_rs.if_index = if_index;
- memcpy(&ra_rs.from, &icmp6ev.from, sizeof(ra_rs.from));
+ memcpy(&ra_rs.from, &icmp6ev->from, sizeof(ra_rs.from));
ra_rs.len = len;
- memcpy(ra_rs.packet, icmp6ev.answer, len);
+ memcpy(ra_rs.packet, icmp6ev->answer, len);
frontend_imsg_compose_engine(IMSG_RA_RS, 0, &ra_rs, sizeof(ra_rs));
}
@@ -671,20 +664,24 @@ icmp6_receive(int fd, short events, void *arg)
void
join_all_routers_mcast_group(struct ra_iface *ra_iface)
{
+ if (!event_initialized(&ra_iface->icmp6ev->ev))
+ return;
log_debug("joining multicast group on %s", ra_iface->name);
all_routers.ipv6mr_interface = ra_iface->if_index;
- if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
- &all_routers, sizeof(all_routers)) == -1)
+ if (setsockopt(EVENT_FD(&ra_iface->icmp6ev->ev), IPPROTO_IPV6,
+ IPV6_JOIN_GROUP, &all_routers, sizeof(all_routers)) == -1)
fatal("IPV6_JOIN_GROUP(%s)", ra_iface->name);
}
void
leave_all_routers_mcast_group(struct ra_iface *ra_iface)
{
+ if (!event_initialized(&ra_iface->icmp6ev->ev))
+ return;
log_debug("leaving multicast group on %s", ra_iface->name);
all_routers.ipv6mr_interface = ra_iface->if_index;
- setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
- &all_routers, sizeof(all_routers));
+ setsockopt(EVENT_FD(&ra_iface->icmp6ev->ev), IPPROTO_IPV6,
+ IPV6_LEAVE_GROUP, &all_routers, sizeof(all_routers));
}
struct ra_iface*
@@ -746,15 +743,29 @@ get_link_state(char *if_name)
return ls;
}
+int
+get_ifrdomain(char *if_name)
+{
+ struct ifreq ifr;
+
+ (void) strlcpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
+ if (ioctl(ioctlsock, SIOCGIFRDOMAIN, (caddr_t)&ifr) == -1) {
+ log_warn("SIOCGIFRDOMAIN");
+ return -1;
+ }
+ return ifr.ifr_rdomainid;
+}
+
void
merge_ra_interface(char *name, char *conf_name)
{
struct ra_iface *ra_iface;
uint32_t if_index;
- int link_state, has_linklocal;
+ int link_state, has_linklocal, ifrdomain;
link_state = get_link_state(name);
has_linklocal = interface_has_linklocal_address(name);
+ ifrdomain = get_ifrdomain(name);
if ((ra_iface = find_ra_iface_by_name(name)) != NULL) {
ra_iface->link_state = link_state;
@@ -765,6 +776,16 @@ merge_ra_interface(char *name, char *conf_name)
log_debug("%s has no IPv6 link-local address, "
"removing", name);
ra_iface->removed = 1;
+ } else if (ifrdomain == -1) {
+ log_debug("can't get rdomain for %s, removing", name);
+ ra_iface->removed = 1;
+ } else if (ra_iface->rdomain != ifrdomain) {
+ leave_all_routers_mcast_group(ra_iface);
+ unref_icmp6ev(ra_iface);
+ ra_iface->rdomain = ifrdomain;
+ ra_iface->icmp6ev = get_icmp6ev_by_rdomain(ifrdomain);
+ join_all_routers_mcast_group(ra_iface);
+ ra_iface->removed = 0;
} else {
log_debug("keeping interface %s", name);
ra_iface->removed = 0;
@@ -795,9 +816,13 @@ merge_ra_interface(char *name, char *conf_name)
sizeof(ra_iface->conf_name));
ra_iface->if_index = if_index;
+ ra_iface->rdomain = ifrdomain;
+
SIMPLEQ_INIT(&ra_iface->prefixes);
- TAILQ_INSERT_TAIL(&ra_interfaces, ra_iface, entry);
+
+ ra_iface->icmp6ev = get_icmp6ev_by_rdomain(ifrdomain);
join_all_routers_mcast_group(ra_iface);
+ TAILQ_INSERT_TAIL(&ra_interfaces, ra_iface, entry);
}
void
@@ -901,6 +926,7 @@ free_ra_iface(struct ra_iface *ra_iface)
free(prefix);
}
+ unref_icmp6ev(ra_iface);
free(ra_iface);
}
@@ -1182,8 +1208,9 @@ build_packet(struct ra_iface *ra_iface)
memcpy(ra_iface->data, buf, len);
ra_iface->datalen = len;
/* packet changed; tell engine to send new advertisments */
- frontend_imsg_compose_engine(IMSG_UPDATE_IF, 0,
- &ra_iface->if_index, sizeof(ra_iface->if_index));
+ if (event_initialized(&ra_iface->icmp6ev->ev))
+ frontend_imsg_compose_engine(IMSG_UPDATE_IF, 0,
+ &ra_iface->if_index, sizeof(ra_iface->if_index));
}
}
@@ -1237,7 +1264,7 @@ ra_output(struct ra_iface *ra_iface, struct sockaddr_in6
*to)
log_debug("send RA on %s", ra_iface->name);
- len = sendmsg(icmp6sock, &sndmhdr, 0);
+ len = sendmsg(EVENT_FD(&ra_iface->icmp6ev->ev), &sndmhdr, 0);
if (len == -1)
log_warn("sendmsg on %s", ra_iface->name);
@@ -1318,3 +1345,91 @@ handle_route_message(struct rt_msghdr *rtm, struct
sockaddr **rti_info)
break;
}
}
+
+struct icmp6_ev*
+get_icmp6ev_by_rdomain(int rdomain)
+{
+ struct ra_iface *ra_iface;
+ struct icmp6_ev *icmp6ev = NULL;
+
+ TAILQ_FOREACH (ra_iface, &ra_interfaces, entry) {
+ if (ra_iface->rdomain == rdomain) {
+ icmp6ev = ra_iface->icmp6ev;
+ break;
+ }
+ }
+
+ if (icmp6ev == NULL) {
+ if ((icmp6ev = calloc(1, sizeof(*icmp6ev))) == NULL)
+ fatal("calloc");
+
+ icmp6ev->rcviov[0].iov_base = (caddr_t)icmp6ev->answer;
+ icmp6ev->rcviov[0].iov_len = sizeof(icmp6ev->answer);
+ icmp6ev->rcvmhdr.msg_name = (caddr_t)&icmp6ev->from;
+ icmp6ev->rcvmhdr.msg_namelen = sizeof(icmp6ev->from);
+ icmp6ev->rcvmhdr.msg_iov = icmp6ev->rcviov;
+ icmp6ev->rcvmhdr.msg_iovlen = 1;
+ icmp6ev->rcvmhdr.msg_controllen =
+ CMSG_SPACE(sizeof(struct in6_pktinfo)) +
+ CMSG_SPACE(sizeof(int));
+ if ((icmp6ev->rcvmhdr.msg_control = malloc(icmp6ev->
+ rcvmhdr.msg_controllen)) == NULL)
+ fatal("malloc");
+ frontend_imsg_compose_main(IMSG_OPEN_ICMP6SOCK, 0,
+ &rdomain, sizeof(rdomain));
+ }
+
+ icmp6ev->refcnt++;
+ return (icmp6ev);
+}
+
+void
+unref_icmp6ev(struct ra_iface *ra_iface)
+{
+ struct icmp6_ev *icmp6ev = ra_iface->icmp6ev;
+
+ ra_iface->icmp6ev = NULL;
+
+ if (icmp6ev != NULL) {
+ icmp6ev->refcnt--;
+ if (icmp6ev->refcnt == 0) {
+ event_del(&icmp6ev->ev);
+ close(EVENT_FD(&icmp6ev->ev));
+ free(icmp6ev);
+ }
+ }
+}
+
+void
+set_icmp6sock(int icmp6sock, int rdomain)
+{
+ struct ra_iface *ra_iface;
+
+ TAILQ_FOREACH (ra_iface, &ra_interfaces, entry) {
+ if (!event_initialized(&ra_iface->icmp6ev->ev) &&
+ ra_iface->rdomain == rdomain) {
+ event_set(&ra_iface->icmp6ev->ev, icmp6sock, EV_READ |
+ EV_PERSIST, icmp6_receive, ra_iface->icmp6ev);
+ event_add(&ra_iface->icmp6ev->ev, NULL);
+ icmp6sock = -1;
+ break;
+ }
+ }
+
+ if (icmp6sock != -1) {
+ /*
+ * The interface disappeared or changed rdomain while we were
+ * waiting for the parent process to open the raw socket.
+ */
+ close(icmp6sock);
+ return;
+ }
+
+ TAILQ_FOREACH (ra_iface, &ra_interfaces, entry) {
+ if (ra_iface->rdomain == rdomain) {
+ join_all_routers_mcast_group(ra_iface);
+ frontend_imsg_compose_engine(IMSG_UPDATE_IF, 0,
+ &ra_iface->if_index, sizeof(ra_iface->if_index));
+ }
+ }
+}
diff --git rad.c rad.c
index 6d4e18c1215..9dc85e6fb52 100644
--- rad.c
+++ rad.c
@@ -61,6 +61,7 @@ static pid_t start_child(int, char *, int, int, int);
void main_dispatch_frontend(int, short, void *);
void main_dispatch_engine(int, short, void *);
+void open_icmp6sock(int);
static int main_imsg_send_ipc_sockets(struct imsgbuf *, struct imsgbuf *);
static int main_imsg_send_config(struct rad_conf *);
@@ -118,13 +119,11 @@ int
main(int argc, char *argv[])
{
struct event ev_sigint, ev_sigterm, ev_sighup;
- struct icmp6_filter filt;
int ch;
int debug = 0, engine_flag = 0, frontend_flag = 0;
char *saved_argv0;
int pipe_main2frontend[2];
int pipe_main2engine[2];
- int icmp6sock, on = 1, off = 0;
int frontend_routesock, rtfilter;
int control_fd;
char *csock;
@@ -259,30 +258,6 @@ main(int argc, char *argv[])
if (main_imsg_send_ipc_sockets(&iev_frontend->ibuf, &iev_engine->ibuf))
fatal("could not establish imsg links");
- if ((icmp6sock = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC,
- IPPROTO_ICMPV6)) == -1)
- fatal("ICMPv6 socket");
-
- if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
- sizeof(on)) == -1)
- fatal("IPV6_RECVPKTINFO");
-
- if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
- sizeof(on)) == -1)
- fatal("IPV6_RECVHOPLIMIT");
-
- if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off,
- sizeof(off)) == -1)
- fatal("IPV6_RECVHOPLIMIT");
-
- /* only router advertisements and solicitations */
- ICMP6_FILTER_SETBLOCKALL(&filt);
- ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
- ICMP6_FILTER_SETPASS(ND_ROUTER_SOLICIT, &filt);
- if (setsockopt(icmp6sock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
- sizeof(filt)) == -1)
- fatal("ICMP6_FILTER");
-
if ((frontend_routesock = socket(AF_ROUTE, SOCK_RAW | SOCK_CLOEXEC,
AF_INET6)) == -1)
fatal("route socket");
@@ -296,15 +271,15 @@ main(int argc, char *argv[])
if ((control_fd = control_init(csock)) == -1)
fatalx("control socket setup failed");
- main_imsg_compose_frontend_fd(IMSG_ICMP6SOCK, 0, icmp6sock);
- main_imsg_compose_frontend_fd(IMSG_ROUTESOCK, 0, frontend_routesock);
- main_imsg_compose_frontend_fd(IMSG_CONTROLFD, 0, control_fd);
+ main_imsg_compose_frontend(IMSG_ROUTESOCK, frontend_routesock,
+ NULL, 0);
+ main_imsg_compose_frontend(IMSG_CONTROLFD, control_fd, NULL, 0);
main_imsg_send_config(main_conf);
- if (pledge("stdio rpath sendfd", NULL) == -1)
+ if (pledge("stdio inet rpath sendfd mcast wroute", NULL) == -1)
fatal("pledge");
- main_imsg_compose_frontend(IMSG_STARTUP, 0, NULL, 0);
+ main_imsg_compose_frontend(IMSG_STARTUP, -1, NULL, 0);
event_dispatch();
@@ -397,6 +372,7 @@ main_dispatch_frontend(int fd, short event, void *bula)
struct imsg imsg;
ssize_t n;
int shut = 0, verbose;
+ int rdomain;
ibuf = &iev->ibuf;
@@ -420,9 +396,13 @@ main_dispatch_frontend(int fd, short event, void *bula)
break;
switch (imsg.hdr.type) {
- case IMSG_STARTUP_DONE:
- if (pledge("stdio rpath", NULL) == -1)
- fatal("pledge");
+ case IMSG_OPEN_ICMP6SOCK:
+ log_debug("IMSG_OPEN_ICMP6SOCK");
+ if (IMSG_DATA_SIZE(imsg) != sizeof(rdomain))
+ fatalx("%s: IMSG_OPEN_ICMP6SOCK wrong length: "
+ "%lu", __func__, IMSG_DATA_SIZE(imsg));
+ memcpy(&rdomain, imsg.data, sizeof(rdomain));
+ open_icmp6sock(rdomain);
break;
case IMSG_CTL_RELOAD:
if (main_reload() == -1)
@@ -500,22 +480,16 @@ main_dispatch_engine(int fd, short event, void *bula)
}
}
-void
-main_imsg_compose_frontend(int type, pid_t pid, void *data, uint16_t datalen)
+int
+main_imsg_compose_frontend(int type, int fd, void *data, uint16_t datalen)
{
if (iev_frontend)
- imsg_compose_event(iev_frontend, type, 0, pid, -1, data,
- datalen);
+ return (imsg_compose_event(iev_frontend, type, 0, 0, fd, data,
+ datalen));
+ else
+ return (-1);
}
-void
-main_imsg_compose_frontend_fd(int type, pid_t pid, int fd)
-{
- if (iev_frontend)
- imsg_compose_event(iev_frontend, type, 0, pid, fd, NULL, 0);
-}
-
-
void
main_imsg_compose_engine(int type, pid_t pid, void *data, uint16_t datalen)
{
@@ -810,3 +784,38 @@ in6_to_str(struct in6_addr *in6)
return (sin6_to_str(&sin6));
}
+
+void
+open_icmp6sock(int rdomain)
+{
+ int icmp6sock, on = 1, off = 0;
+
+ log_debug("%s: %d", __func__, rdomain);
+
+ if ((icmp6sock = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC,
+ IPPROTO_ICMPV6)) == -1)
+ fatal("ICMPv6 socket");
+
+ if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
+ sizeof(on)) == -1)
+ fatal("IPV6_RECVPKTINFO");
+
+ if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &on,
+ sizeof(on)) == -1)
+ fatal("IPV6_RECVHOPLIMIT");
+
+ if (setsockopt(icmp6sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off,
+ sizeof(off)) == -1)
+ fatal("IPV6_RECVHOPLIMIT");
+
+ if (setsockopt(icmp6sock, SOL_SOCKET, SO_RTABLE, &rdomain,
+ sizeof(rdomain)) == -1) {
+ /* we might race against removal of the rdomain */
+ log_warn("setsockopt SO_RTABLE");
+ close(icmp6sock);
+ return;
+ }
+
+ main_imsg_compose_frontend(IMSG_ICMP6SOCK, icmp6sock, &rdomain,
+ sizeof(rdomain));
+}
diff --git rad.h rad.h
index 823a2a9d633..c65f4554388 100644
--- rad.h
+++ rad.h
@@ -67,10 +67,10 @@ enum imsg_type {
IMSG_RECONF_RA_DNSSL,
IMSG_RECONF_END,
IMSG_ICMP6SOCK,
+ IMSG_OPEN_ICMP6SOCK,
IMSG_ROUTESOCK,
IMSG_CONTROLFD,
IMSG_STARTUP,
- IMSG_STARTUP_DONE,
IMSG_RA_RS,
IMSG_SEND_RA,
IMSG_UPDATE_IF,
@@ -145,9 +145,7 @@ struct imsg_send_ra {
extern uint32_t cmd_opts;
/* rad.c */
-void main_imsg_compose_frontend(int, pid_t, void *, uint16_t);
-void main_imsg_compose_frontend_fd(int, pid_t, int);
-
+int main_imsg_compose_frontend(int, int, void *, uint16_t);
void main_imsg_compose_engine(int, pid_t, void *, uint16_t);
void merge_config(struct rad_conf *, struct rad_conf *);
void imsg_event_add(struct imsgev *);
--
I'm not entirely sure you are real.