-/* $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>
#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;
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;
__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");
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 "
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)
+{
+}
-/* $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>
#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>
int pipe_main2frontend[2];
int pipe_main2engine[2];
int icmp6sock, on = 1;
+ int frontend_routesock, rtfilter;
conffile = CONF_FILE;
csock = RAD_SOCKET;
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);