ndp: harden netlink event socket error handling
authorHans Dedecker <dedeckeh@gmail.com>
Thu, 9 Feb 2017 15:52:50 +0000 (16:52 +0100)
committerHans Dedecker <dedeckeh@gmail.com>
Thu, 9 Feb 2017 17:06:27 +0000 (18:06 +0100)
Start with a netlink receive buffersize of 130k for the netlink event socket;
double the netlink receive buffer size in case an ENOBUFS is reported.
Also align function naming and its parameters.

Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
src/ndp.c
src/odhcpd.c
src/odhcpd.h

index 8bed4ea..c6e4eda 100644 (file)
--- a/src/ndp.c
+++ b/src/ndp.c
 struct event_socket {
        struct odhcpd_event ev;
        struct nl_sock *sock;
+       int sock_bufsize;
 };
 
 static void handle_solicit(void *addr, void *data, size_t len,
                struct interface *iface, void *dest);
 static void handle_rtnl_event(struct odhcpd_event *ev);
 static int cb_rtnl_valid(struct nl_msg *msg, void *arg);
-static void catch_rtnetlink(int error);
+static void catch_rtnl_err(struct odhcpd_event *e, int error);
 
 static int ping_socket = -1;
 static struct event_socket rtnl_event = {
        .ev = {
                .uloop = {.fd = - 1, },
                .handle_dgram = NULL,
-               .handle_error = catch_rtnetlink,
+               .handle_error = catch_rtnl_err,
                .recv_msgs = handle_rtnl_event,
        },
        .sock = NULL,
+       .sock_bufsize = 133120,
 };
 
 // Filter ICMPv6 messages of type neighbor soliciation
@@ -75,7 +77,7 @@ static const struct sock_fprog bpf_prog = {sizeof(bpf) / sizeof(*bpf), bpf};
 // Initialize NDP-proxy
 int init_ndp(void)
 {
-       int val = 256 * 1024;
+       int val = 2;
 
        rtnl_event.sock = odhcpd_create_nl_socket(NETLINK_ROUTE);
        if (!rtnl_event.sock)
@@ -83,7 +85,7 @@ int init_ndp(void)
 
        rtnl_event.ev.uloop.fd = nl_socket_get_fd(rtnl_event.sock);
 
-       if (nl_socket_set_buffer_size(rtnl_event.sock, val, 0))
+       if (nl_socket_set_buffer_size(rtnl_event.sock, rtnl_event.sock_bufsize, 0))
                goto err;
 
        nl_socket_disable_seq_check(rtnl_event.sock);
@@ -105,7 +107,6 @@ int init_ndp(void)
                        return -1;
        }
 
-       val = 2;
        setsockopt(ping_socket, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val));
 
        // This is required by RFC 4861
@@ -533,8 +534,18 @@ static int cb_rtnl_valid(struct nl_msg *msg, _unused void *arg)
        return NL_OK;
 }
 
-static void catch_rtnetlink(int error)
+static void catch_rtnl_err(struct odhcpd_event *e, int error)
 {
-       if (error == ENOBUFS)
-               dump_addr_table();
+       struct event_socket *ev_sock = container_of(e, struct event_socket, ev);
+
+       if (error != ENOBUFS)
+               return;
+
+       /* Double netlink event buffer size */
+       ev_sock->sock_bufsize *= 2;
+
+       if (nl_socket_set_buffer_size(ev_sock->sock, ev_sock->sock_bufsize, 0))
+               return;
+
+       dump_addr_table();
 }
index 97d33e1..22a27a4 100644 (file)
@@ -476,7 +476,7 @@ static void odhcpd_receive_packets(struct uloop_fd *u, _unused unsigned int even
                getsockopt(u->fd, SOL_SOCKET, SO_ERROR, &ret, &ret_len);
                u->error = false;
                if (e->handle_error)
-                       e->handle_error(ret);
+                       e->handle_error(e, ret);
        }
 
        if (e->recv_msgs) {
index fb6b182..393194c 100644 (file)
@@ -66,8 +66,8 @@ struct odhcpd_event {
        struct uloop_fd uloop;
        void (*handle_dgram)(void *addr, void *data, size_t len,
                        struct interface *iface, void *dest_addr);
-       void (*handle_error)(int error);
-       void (*recv_msgs)(struct odhcpd_event *ev);
+       void (*handle_error)(struct odhcpd_event *e, int error);
+       void (*recv_msgs)(struct odhcpd_event *e);
 };