diff options
-rw-r--r-- | usr.sbin/rad/frontend.c | 83 | ||||
-rw-r--r-- | usr.sbin/rad/rad.c | 15 | ||||
-rw-r--r-- | usr.sbin/rad/rad.h | 3 |
3 files changed, 95 insertions, 6 deletions
diff --git a/usr.sbin/rad/frontend.c b/usr.sbin/rad/frontend.c index 536822bd439..713b6c203e0 100644 --- a/usr.sbin/rad/frontend.c +++ b/usr.sbin/rad/frontend.c @@ -1,4 +1,4 @@ -/* $OpenBSD: frontend.c,v 1.5 2018/07/11 19:05:25 florian Exp $ */ +/* $OpenBSD: frontend.c,v 1.6 2018/07/13 08:31:34 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -86,7 +86,8 @@ #include "frontend.h" #include "control.h" -#define RA_MAX_SIZE 1500 +#define RA_MAX_SIZE 1500 +#define ROUTE_SOCKET_BUF_SIZE 16384 struct icmp6_ev { struct event ev; @@ -131,10 +132,16 @@ void get_interface_prefixes(struct ra_iface *, void build_package(struct ra_iface *); void build_leaving_package(struct ra_iface *); void ra_output(struct ra_iface *, struct sockaddr_in6 *); +void get_rtaddrs(int, struct sockaddr *, + struct sockaddr **); +void route_receive(int, short, void *); +void handle_route_message(struct rt_msghdr *, + struct sockaddr **); struct rad_conf *frontend_conf; struct imsgev *iev_main; struct imsgev *iev_engine; +struct event ev_route; int icmp6sock = -1, ioctlsock = -1; struct ipv6_mreq all_routers; struct sockaddr_in6 all_nodes; @@ -406,6 +413,14 @@ frontend_dispatch_main(int fd, short event, void *bula) __func__); event_set(&icmp6ev.ev, icmp6sock, EV_READ | EV_PERSIST, icmp6_receive, NULL); + case IMSG_ROUTESOCK: + if ((fd = imsg.fd) == -1) + fatalx("%s: expected to receive imsg " + "routesocket fd but didn't receive any", + __func__); + event_set(&ev_route, fd, EV_READ | EV_PERSIST, + route_receive, NULL); + break; case IMSG_STARTUP: if (pledge("stdio inet unix route mcast", NULL) == -1) fatal("pledge"); @@ -503,13 +518,11 @@ frontend_dispatch_engine(int fd, short event, void *bula) void frontend_startup(void) { -#if 0 if (!event_initialized(&ev_route)) fatalx("%s: did not receive a route socket from the main " "process", __func__); event_add(&ev_route, NULL); -#endif if (!event_initialized(&icmp6ev.ev)) fatalx("%s: did not receive a icmp6 socket fd from the main " @@ -969,3 +982,65 @@ ra_output(struct ra_iface *ra_iface, struct sockaddr_in6 *to) log_warn("sendmsg on %s", ra_iface->name); } + +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) + +void +get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info) +{ + int i; + + for (i = 0; i < RTAX_MAX; i++) { + if (addrs & (1 << i)) { + rti_info[i] = sa; + sa = (struct sockaddr *)((char *)(sa) + + ROUNDUP(sa->sa_len)); + } else + rti_info[i] = NULL; + } +} + +void +route_receive(int fd, short events, void *arg) +{ + static uint8_t *buf; + + struct rt_msghdr *rtm; + struct sockaddr *sa, *rti_info[RTAX_MAX]; + ssize_t n; + + if (buf == NULL) { + buf = malloc(ROUTE_SOCKET_BUF_SIZE); + if (buf == NULL) + fatal("malloc"); + } + rtm = (struct rt_msghdr *)buf; + if ((n = read(fd, buf, ROUTE_SOCKET_BUF_SIZE)) == -1) { + if (errno == EAGAIN || errno == EINTR) + return; + log_warn("dispatch_rtmsg: read error"); + return; + } + + if (n == 0) + fatal("routing socket closed"); + + if (n < (ssize_t)sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen) { + log_warnx("partial rtm of %zd in buffer", n); + return; + } + + if (rtm->rtm_version != RTM_VERSION) + return; + + sa = (struct sockaddr *)(buf + rtm->rtm_hdrlen); + get_rtaddrs(rtm->rtm_addrs, sa, rti_info); + + handle_route_message(rtm, rti_info); +} + +void +handle_route_message(struct rt_msghdr *rtm, struct sockaddr **rti_info) +{ +} diff --git a/usr.sbin/rad/rad.c b/usr.sbin/rad/rad.c index 96aa5532989..59b3c073a07 100644 --- a/usr.sbin/rad/rad.c +++ b/usr.sbin/rad/rad.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rad.c,v 1.4 2018/07/11 19:05:25 florian Exp $ */ +/* $OpenBSD: rad.c,v 1.5 2018/07/13 08:31:34 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -27,6 +27,7 @@ #include <netinet/in.h> #include <net/if.h> +#include <net/route.h> #include <netinet/in.h> #include <netinet/if_ether.h> #include <netinet6/in6_var.h> @@ -129,6 +130,7 @@ main(int argc, char *argv[]) int pipe_main2frontend[2]; int pipe_main2engine[2]; int icmp6sock, on = 1; + int frontend_routesock, rtfilter; conffile = CONF_FILE; csock = RAD_SOCKET; @@ -280,7 +282,18 @@ main(int argc, char *argv[]) sizeof(filt)) == -1) fatal("ICMP6_FILTER"); + if ((frontend_routesock = socket(PF_ROUTE, SOCK_RAW | SOCK_CLOEXEC, + AF_INET6)) < 0) + fatal("route socket"); + + rtfilter = ROUTE_FILTER(RTM_IFINFO) | ROUTE_FILTER(RTM_NEWADDR) | + ROUTE_FILTER(RTM_DELADDR); + if (setsockopt(frontend_routesock, PF_ROUTE, ROUTE_MSGFILTER, + &rtfilter, sizeof(rtfilter)) < 0) + fatal("setsockopt(ROUTE_MSGFILTER)"); + main_imsg_compose_frontend_fd(IMSG_ICMP6SOCK, 0, icmp6sock); + main_imsg_compose_frontend_fd(IMSG_ROUTESOCK, 0, frontend_routesock); main_imsg_send_config(main_conf); diff --git a/usr.sbin/rad/rad.h b/usr.sbin/rad/rad.h index 388437afe5c..8faa2ee5d2c 100644 --- a/usr.sbin/rad/rad.h +++ b/usr.sbin/rad/rad.h @@ -1,4 +1,4 @@ -/* $OpenBSD: rad.h,v 1.7 2018/07/12 08:18:10 florian Exp $ */ +/* $OpenBSD: rad.h,v 1.8 2018/07/13 08:31:34 florian Exp $ */ /* * Copyright (c) 2018 Florian Obser <florian@openbsd.org> @@ -57,6 +57,7 @@ enum imsg_type { IMSG_RECONF_RA_PREFIX, IMSG_RECONF_END, IMSG_ICMP6SOCK, + IMSG_ROUTESOCK, IMSG_STARTUP, IMSG_STARTUP_DONE, IMSG_RA_RS, |