Commit 87f55f5e authored by Matthieu Boutier's avatar Matthieu Boutier Committed by Juliusz Chroboczek

Refactor netlink: address import.

parent 58dbd2f4
...@@ -105,6 +105,13 @@ kernel_route_notify(struct kernel_route *route, void *closure) ...@@ -105,6 +105,13 @@ kernel_route_notify(struct kernel_route *route, void *closure)
return -1; return -1;
} }
static int
kernel_addr_notify(struct kernel_addr *addr, void *closure)
{
kernel_addr_changed = 1;
return -1;
}
int int
main(int argc, char **argv) main(int argc, char **argv)
{ {
...@@ -597,6 +604,7 @@ main(int argc, char **argv) ...@@ -597,6 +604,7 @@ main(int argc, char **argv)
if(kernel_socket >= 0 && FD_ISSET(kernel_socket, &readfds)) { if(kernel_socket >= 0 && FD_ISSET(kernel_socket, &readfds)) {
struct kernel_filter filter = {0}; struct kernel_filter filter = {0};
filter.route = kernel_route_notify; filter.route = kernel_route_notify;
filter.addr = kernel_addr_notify;
kernel_callback(&filter); kernel_callback(&filter);
} }
......
...@@ -40,6 +40,7 @@ THE SOFTWARE. ...@@ -40,6 +40,7 @@ THE SOFTWARE.
#include "message.h" #include "message.h"
#include "route.h" #include "route.h"
#include "configuration.h" #include "configuration.h"
#include "xroute.h"
struct interface *interfaces = NULL; struct interface *interfaces = NULL;
...@@ -186,7 +187,7 @@ check_link_local_addresses(struct interface *ifp) ...@@ -186,7 +187,7 @@ check_link_local_addresses(struct interface *ifp)
free(ifp->ll); free(ifp->ll);
ifp->numll = 0; ifp->numll = 0;
ifp->ll = NULL; ifp->ll = NULL;
rc = kernel_addresses(ifp->name, ifp->ifindex, 1, ll, 32); rc = kernel_addresses(ifp->ifindex, 1, ll, 32);
if(rc < 0) { if(rc < 0) {
perror("kernel_addresses(link local)"); perror("kernel_addresses(link local)");
return -1; return -1;
......
...@@ -36,8 +36,15 @@ struct kernel_route { ...@@ -36,8 +36,15 @@ struct kernel_route {
unsigned char gw[16]; unsigned char gw[16];
}; };
struct kernel_addr {
struct in6_addr addr;
unsigned int ifindex;
};
struct kernel_filter { struct kernel_filter {
/* return -1 to interrupt search. */ /* return -1 to interrupt search. */
int (*addr)(struct kernel_addr *, void *);
void *addr_closure;
int (*route)(struct kernel_route *, void *); int (*route)(struct kernel_route *, void *);
void *route_closure; void *route_closure;
}; };
...@@ -79,8 +86,6 @@ int kernel_route(int operation, const unsigned char *dest, unsigned short plen, ...@@ -79,8 +86,6 @@ int kernel_route(int operation, const unsigned char *dest, unsigned short plen,
unsigned int newmetric); unsigned int newmetric);
int kernel_dump(int operation, struct kernel_filter *filter); int kernel_dump(int operation, struct kernel_filter *filter);
int kernel_callback(struct kernel_filter *filter); int kernel_callback(struct kernel_filter *filter);
int kernel_addresses(char *ifname, int ifindex, int ll,
struct kernel_route *routes, int maxroutes);
int if_eui64(char *ifname, int ifindex, unsigned char *eui); int if_eui64(char *ifname, int ifindex, unsigned char *eui);
int gettime(struct timeval *tv); int gettime(struct timeval *tv);
int read_random_bytes(void *buf, int len); int read_random_bytes(void *buf, int len);
......
...@@ -1228,7 +1228,9 @@ kernel_dump(int operation, struct kernel_filter *filter) ...@@ -1228,7 +1228,9 @@ kernel_dump(int operation, struct kernel_filter *filter)
if(nl_command.sock < 0) { if(nl_command.sock < 0) {
rc = netlink_socket(&nl_command, 0); rc = netlink_socket(&nl_command, 0);
if(rc < 0) { if(rc < 0) {
int save = errno;
perror("kernel_dump: netlink_socket()"); perror("kernel_dump: netlink_socket()");
errno = save;
return -1; return -1;
} }
} }
...@@ -1261,6 +1263,18 @@ kernel_dump(int operation, struct kernel_filter *filter) ...@@ -1261,6 +1263,18 @@ kernel_dump(int operation, struct kernel_filter *filter)
} }
} }
if(operation & CHANGE_ADDR) {
memset(&g, 0, sizeof(g));
g.rtgen_family = AF_UNSPEC;
rc = netlink_send_dump(RTM_GETADDR, &g, sizeof(g));
if(rc < 0)
return -1;
rc = netlink_read(&nl_command, NULL, 1, filter_netlink, (void*)filter);
if(rc < 0)
return -1;
}
return 0; return 0;
} }
...@@ -1358,64 +1372,30 @@ filter_link(struct nlmsghdr *nh, void *data) ...@@ -1358,64 +1372,30 @@ filter_link(struct nlmsghdr *nh, void *data)
data[4]. */ data[4]. */
static int static int
filter_addresses(struct nlmsghdr *nh, void *data) filter_addresses(struct nlmsghdr *nh, struct kernel_addr *addr)
{ {
int rc; int rc;
int maxroutes = 0;
struct kernel_route *routes = NULL;
struct in6_addr addr;
int *found = NULL;
int len; int len;
struct ifaddrmsg *ifa; struct ifaddrmsg *ifa;
char ifname[IFNAMSIZ]; char ifname[IFNAMSIZ];
int ifindex = 0;
int ll = 0;
if(data) {
void **args = (void **)data;
maxroutes = *(int *)args[0];
routes = (struct kernel_route*)args[1];
found = (int *)args[2];
ifindex = args[3] ? *(int*)args[3] : 0;
ll = args[4] ? !!*(int*)args[4] : 0;
}
len = nh->nlmsg_len; len = nh->nlmsg_len;
if(data && *found >= maxroutes)
return 0;
if(nh->nlmsg_type != RTM_NEWADDR && if(nh->nlmsg_type != RTM_NEWADDR &&
(data || nh->nlmsg_type != RTM_DELADDR)) nh->nlmsg_type != RTM_DELADDR)
return 0; return 0;
ifa = (struct ifaddrmsg *)NLMSG_DATA(nh); ifa = (struct ifaddrmsg *)NLMSG_DATA(nh);
len -= NLMSG_LENGTH(0); len -= NLMSG_LENGTH(0);
rc = parse_addr_rta(ifa, len, &addr); rc = parse_addr_rta(ifa, len, &addr->addr);
if(rc < 0) if(rc < 0)
return 0; return 0;
addr->ifindex = ifa->ifa_index;
if(data && ll == !IN6_IS_ADDR_LINKLOCAL(&addr))
return 0;
if(ifindex && ifa->ifa_index != ifindex)
return 0;
kdebugf("found address on interface %s(%d): %s\n", kdebugf("found address on interface %s(%d): %s\n",
if_indextoname(ifa->ifa_index, ifname), ifa->ifa_index, if_indextoname(ifa->ifa_index, ifname), ifa->ifa_index,
format_address(addr.s6_addr)); format_address(addr->addr.s6_addr));
if(data) {
struct kernel_route *route = &routes[*found];
memcpy(route->prefix, addr.s6_addr, 16);
route->plen = 128;
route->metric = 0;
route->ifindex = ifa->ifa_index;
route->proto = RTPROT_BABEL_LOCAL;
memset(route->gw, 0, 16);
*found = (*found)+1;
}
return 1; return 1;
} }
...@@ -1427,6 +1407,7 @@ filter_netlink(struct nlmsghdr *nh, struct kernel_filter *filter) ...@@ -1427,6 +1407,7 @@ filter_netlink(struct nlmsghdr *nh, struct kernel_filter *filter)
int *changed = data; int *changed = data;
union { union {
struct kernel_route route; struct kernel_route route;
struct kernel_addr addr;
} u; } u;
switch(nh->nlmsg_type) { switch(nh->nlmsg_type) {
...@@ -1444,10 +1425,10 @@ filter_netlink(struct nlmsghdr *nh, struct kernel_filter *filter) ...@@ -1444,10 +1425,10 @@ filter_netlink(struct nlmsghdr *nh, struct kernel_filter *filter)
return rc; return rc;
case RTM_NEWADDR: case RTM_NEWADDR:
case RTM_DELADDR: case RTM_DELADDR:
rc = filter_addresses(nh, &kernel_addr); if(!filter->addr) break;
if(changed && rc > 0) rc = filter_addresses(nh, &u.addr);
*changed |= CHANGE_ADDR; if(rc <= 0) break;
return rc; return filter->addr(&u.addr, filter->addr_closure);
case RTM_NEWRULE: case RTM_NEWRULE:
case RTM_DELRULE: case RTM_DELRULE:
rc = filter_kernel_rules(nh, NULL); rc = filter_kernel_rules(nh, NULL);
...@@ -1462,46 +1443,6 @@ filter_netlink(struct nlmsghdr *nh, struct kernel_filter *filter) ...@@ -1462,46 +1443,6 @@ filter_netlink(struct nlmsghdr *nh, struct kernel_filter *filter)
return 0; return 0;
} }
int
kernel_addresses(char *ifname, int ifindex, int ll,
struct kernel_route *routes, int maxroutes)
{
int maxr = maxroutes;
int found = 0;
void *data[] = { &maxr, routes, &found, &ifindex, &ll, NULL };
struct rtgenmsg g;
int rc;
if(!nl_setup) {
fprintf(stderr, "kernel_addresses: netlink not initialized.\n");
errno = ENOSYS;
return -1;
}
if(nl_command.sock < 0) {
rc = netlink_socket(&nl_command, 0);
if(rc < 0) {
int save = errno;
perror("kernel_addresses: netlink_socket()");
errno = save;
return -1;
}
}
memset(&g, 0, sizeof(g));
g.rtgen_family = AF_UNSPEC;
rc = netlink_send_dump(RTM_GETADDR, &g, sizeof(g));
if(rc < 0)
return -1;
rc = netlink_read(&nl_command, NULL, 1, filter_addresses, (void*)data);
if(rc < 0)
return -1;
return found;
}
int int
kernel_callback(struct kernel_filter *filter) kernel_callback(struct kernel_filter *filter)
{ {
......
...@@ -687,9 +687,8 @@ parse_kernel_route(const struct rt_msghdr *rtm, struct kernel_route *route) ...@@ -687,9 +687,8 @@ parse_kernel_route(const struct rt_msghdr *rtm, struct kernel_route *route)
return 0; return 0;
} }
int static int
kernel_dump(int operation, struct kernel_filter *filter) kernel_routes(struct kernel_filter *filter) {
{
int mib[6]; int mib[6];
char *buf, *p; char *buf, *p;
size_t len; size_t len;
...@@ -787,62 +786,57 @@ socket_read(int sock, struct kernel_filter *filter) ...@@ -787,62 +786,57 @@ socket_read(int sock, struct kernel_filter *filter)
} }
int static int
kernel_addresses(char *ifname, int ifindex, int ll, kernel_addresses(struct kernel_filter *filter)
struct kernel_route *routes, int maxroutes)
{ {
struct ifaddrs *ifa, *ifap; struct ifaddrs *ifa, *ifap;
int rc, i; int rc;
rc = getifaddrs(&ifa); rc = getifaddrs(&ifa);
if(rc < 0) if(rc < 0)
return -1; return -1;
ifap = ifa; for(ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) {
i = 0; struct kernel_addr addr;
addr.ifindex = if_nametoindex(ifap->ifa_name);
if(!addr.ifindex)
continue;
while(ifap && i < maxroutes) {
if((ifname != NULL && strcmp(ifap->ifa_name, ifname) != 0))
goto next;
if(ifap->ifa_addr->sa_family == AF_INET6) { if(ifap->ifa_addr->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)ifap->ifa_addr; struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)ifap->ifa_addr;
if(!!ll != !!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) memcpy(&addr.addr, &sin6->sin6_addr, 16);
goto next; if(IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
memcpy(routes[i].prefix, &sin6->sin6_addr, 16);
if(ll)
/* This a perfect example of counter-productive optimisation : /* This a perfect example of counter-productive optimisation :
KAME encodes interface index onto bytes 2 and 3, so we have KAME encodes interface index onto bytes 2 and 3, so we have
to reset those bytes to 0 before passing them to babeld. */ to reset those bytes to 0 before passing them to babeld. */
memset(routes[i].prefix + 2, 0, 2); memset(((char*)&addr.addr) + 2, 0, 2);
routes[i].plen = 128;
routes[i].metric = 0;
routes[i].ifindex = ifindex;
routes[i].proto = RTPROT_BABEL_LOCAL;
memset(routes[i].gw, 0, 16);
i++;
} else if(ifap->ifa_addr->sa_family == AF_INET) { } else if(ifap->ifa_addr->sa_family == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in*)ifap->ifa_addr; struct sockaddr_in *sin = (struct sockaddr_in*)ifap->ifa_addr;
if(ll)
goto next;
#if defined(IN_LINKLOCAL) #if defined(IN_LINKLOCAL)
if(IN_LINKLOCAL(htonl(sin->sin_addr.s_addr))) if(IN_LINKLOCAL(htonl(sin->sin_addr.s_addr)))
goto next; continue;
#endif #endif
memcpy(routes[i].prefix, v4prefix, 12); v4tov6((void*)&addr.addr, (void*) &sin->sin_addr);
memcpy(routes[i].prefix + 12, &sin->sin_addr, 4); } else {
routes[i].plen = 128; continue;
routes[i].metric = 0;
routes[i].ifindex = ifindex;
routes[i].proto = RTPROT_BABEL_LOCAL;
memset(routes[i].gw, 0, 16);
i++;
} }
next: filter->addr(&addr, filter->addr_closure);
ifap = ifap->ifa_next;
} }
freeifaddrs(ifa); freeifaddrs(ifa);
return i; return 0;
}
int
kernel_dump(int operation, struct kernel_filter *filter)
{
switch(operation) {
case CHANGE_ROUTE: return kernel_routes(filter);
case CHANGE_ADDR: return kernel_addresses(filter);
default: break;
}
return -1;
} }
int int
......
...@@ -31,6 +31,7 @@ THE SOFTWARE. ...@@ -31,6 +31,7 @@ THE SOFTWARE.
#include "interface.h" #include "interface.h"
#include "source.h" #include "source.h"
#include "neighbour.h" #include "neighbour.h"
#include "kernel.h"
#include "xroute.h" #include "xroute.h"
#include "route.h" #include "route.h"
#include "util.h" #include "util.h"
......
...@@ -35,11 +35,11 @@ THE SOFTWARE. ...@@ -35,11 +35,11 @@ THE SOFTWARE.
#include "source.h" #include "source.h"
#include "neighbour.h" #include "neighbour.h"
#include "route.h" #include "route.h"
#include "kernel.h"
#include "xroute.h" #include "xroute.h"
#include "resend.h" #include "resend.h"
#include "message.h" #include "message.h"
#include "configuration.h" #include "configuration.h"
#include "kernel.h"
unsigned char packet_header[4] = {42, 2}; unsigned char packet_header[4] = {42, 2};
......
...@@ -198,6 +198,52 @@ kernel_routes(struct kernel_route *routes, int maxroutes) ...@@ -198,6 +198,52 @@ kernel_routes(struct kernel_route *routes, int maxroutes)
return found; return found;
} }
static int
filter_address(struct kernel_addr *addr, void *data) {
void **args = (void **)data;
int maxroutes = *(int *)args[0];
struct kernel_route *routes = (struct kernel_route*)args[1];
int *found = (int *)args[2];
int ifindex = args[3] ? *(int*)args[3] : 0;
int ll = args[4] ? !!*(int*)args[4] : 0;
struct kernel_route *route = NULL;
if(*found >= maxroutes)
return 0;
if(ll == !IN6_IS_ADDR_LINKLOCAL(&addr->addr))
return 0;
if(addr->ifindex != ifindex)
return 0;
route = &routes[*found];
memcpy(route->prefix, addr->addr.s6_addr, 16);
route->plen = 128;
route->metric = 0;
route->ifindex = ifindex;
route->proto = RTPROT_BABEL_LOCAL;
memset(route->gw, 0, 16);
++ *found;
return 1;
}
int
kernel_addresses(int ifindex, int ll, struct kernel_route *routes,
int maxroutes)
{
int found = 0;
void *data[5] = { &maxroutes, routes, &found, &ifindex, &ll };
struct kernel_filter filter = {0};
filter.addr = filter_address;
filter.addr_closure = data;
kernel_dump(CHANGE_ADDR, &filter);
return found;
}
int int
check_xroutes(int send_updates) check_xroutes(int send_updates)
{ {
...@@ -215,7 +261,7 @@ check_xroutes(int send_updates) ...@@ -215,7 +261,7 @@ check_xroutes(int send_updates)
if(routes == NULL) if(routes == NULL)
return -1; return -1;
rc = kernel_addresses(NULL, 0, 0, routes, maxroutes); rc = kernel_addresses(0, 0, routes, maxroutes);
if(rc < 0) { if(rc < 0) {
perror("kernel_addresses"); perror("kernel_addresses");
numroutes = 0; numroutes = 0;
......
...@@ -42,4 +42,6 @@ int xroutes_estimate(void); ...@@ -42,4 +42,6 @@ int xroutes_estimate(void);
struct xroute_stream *xroute_stream(); struct xroute_stream *xroute_stream();
struct xroute *xroute_stream_next(struct xroute_stream *stream); struct xroute *xroute_stream_next(struct xroute_stream *stream);
void xroute_stream_done(struct xroute_stream *stream); void xroute_stream_done(struct xroute_stream *stream);
int kernel_addresses(int ifindex, int ll,
struct kernel_route *routes, int maxroutes);
int check_xroutes(int send_updates); int check_xroutes(int send_updates);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment