rtmon_linux.c revision f0c792e78a8bf77c28c7814441e514bea7c5362b
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync/* -*- indent-tabs-mode: nil; -*- */
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync#include <sys/types.h> /* must come before linux/netlink */
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsyncstatic int rtmon_check_defaults(const void *buf, size_t len);
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * Read IPv6 routing table - Linux rtnetlink version.
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * XXX: TODO: To avoid re-reading the table we should subscribe to
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * updates by binding a monitoring NETLINK_ROUTE socket to
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * sockaddr_nl::nl_groups = RTMGRP_IPV6_ROUTE.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * But that will provide updates only. Documentation is scarce, but
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * from what I've seen it seems that to get accurate routing info the
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * monitoring socket needs to be created first, then full routing
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * table requested (easier to do via spearate socket), then monitoring
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * socket polled for input. The first update(s) of the monitoring
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * socket may happen before full table is returned, so we can't just
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * count the defaults, we need to keep track of their { oif, gw } to
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * correctly ignore updates that are reported via monitoring socket,
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * but that are already reflected in the full routing table returned
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * in response to our request.
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync rtreq.nh.nlmsg_len = NLMSG_SPACE(sizeof(rtreq.rtm));
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync /* it's easier to reopen than to flush */
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync rtsock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync DPRINTF0(("rtmon: failed to create netlink socket: %s", strerror(errno)));
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync nsent = send(rtsock, &rtreq, rtreq.nh.nlmsg_len, 0);
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync DPRINTF0(("rtmon: RTM_GETROUTE failed: %s", strerror(errno)));
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync DPRINTF(("rtmon: failed to read RTM_GETROUTE response: %s",
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync (unsigned long)ssize));
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync DPRINTF2(("rtmon: RTM_GETROUTE: truncated %lu to %lu bytes, retrying\n",
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync /* try again with larger buffer */
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync ndefrts = rtmon_check_defaults(buf, (size_t)ssize);
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync DPRINTF(("rtmon: no IPv6 default routes found\n"));
5e91fc5e5ea9cccb7a40636f73253d489fbe340bvboxsync * Scan netlink message in the buffer for IPv6 default route changes.
int dfltdiff = 0;
int attrlen;
int delta = 0;
const void *gwbuf;
int oif;
gwlen = 0;
return dfltdiff;