s3: Add more checks and better fallback to addrchange
authorVolker Lendecke <vl@samba.org>
Fri, 11 Feb 2011 07:44:36 +0000 (08:44 +0100)
committerVolker Lendecke <vl@samba.org>
Tue, 15 Feb 2011 09:23:21 +0000 (02:23 -0700)
From http://netsplit.com/2011/02/09/the-proc-connector-and-socket-filters/ I
learned a bit more about netlink...

Autobuild-User: Volker Lendecke <vlendec@samba.org>
Autobuild-Date: Fri Feb 11 10:47:09 CET 2011 on sn-devel-104

source3/lib/addrchange.c

index 881ef95762f23f21f6d8b4d37d62404ae051fe6a..581fe53b803d990993d5057f00a5d6993a1cb44f 100644 (file)
@@ -124,6 +124,7 @@ static void addrchange_done(struct tevent_req *subreq)
                subreq, struct tevent_req);
        struct addrchange_state *state = tevent_req_data(
                req, struct addrchange_state);
+       struct sockaddr_nl *addr;
        struct nlmsghdr *h;
        struct ifaddrmsg *ifa;
        struct rtattr *rta;
@@ -139,25 +140,35 @@ static void addrchange_done(struct tevent_req *subreq)
                tevent_req_nterror(req, map_nt_error_from_unix(err));
                return;
        }
+       if ((state->fromaddr_len != sizeof(struct sockaddr_nl))
+           || (state->fromaddr.ss_family != AF_NETLINK)) {
+               DEBUG(10, ("Got message from wrong addr\n"));
+               goto retry;
+       }
+
+       addr = (struct sockaddr_nl *)(void *)&state->addr;
+       if (addr->nl_pid != 0) {
+               DEBUG(10, ("Got msg from pid %d, not from the kernel\n",
+                          (int)addr->nl_pid));
+               goto retry;
+       }
+
        if (received < sizeof(struct nlmsghdr)) {
                DEBUG(10, ("received %d, expected at least %d\n",
                           (int)received, (int)sizeof(struct nlmsghdr)));
-               tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
-               return;
+               goto retry;
        }
 
        h = (struct nlmsghdr *)state->buf;
        if (h->nlmsg_len < sizeof(struct nlmsghdr)) {
                DEBUG(10, ("nlmsg_len=%d, expected at least %d\n",
                           (int)h->nlmsg_len, (int)sizeof(struct nlmsghdr)));
-               tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
-               return;
+               goto retry;
        }
        if (h->nlmsg_len > received) {
                DEBUG(10, ("nlmsg_len=%d, expected at most %d\n",
                           (int)h->nlmsg_len, (int)received));
-               tevent_req_nterror(req, NT_STATUS_UNEXPECTED_IO_ERROR);
-               return;
+               goto retry;
        }
        switch (h->nlmsg_type) {
        case RTM_NEWADDR:
@@ -168,16 +179,7 @@ static void addrchange_done(struct tevent_req *subreq)
                break;
        default:
                DEBUG(10, ("Got unexpected type %d - ignoring\n", h->nlmsg_type));
-
-               state->fromaddr_len = sizeof(state->fromaddr);
-               subreq = recvfrom_send(state, state->ev, state->ctx->sock,
-                              state->buf, sizeof(state->buf), 0,
-                              &state->fromaddr, &state->fromaddr_len);
-               if (tevent_req_nomem(subreq, req)) {
-                       return;
-               }
-               tevent_req_set_callback(subreq, addrchange_done, req);
-               return;
+               goto retry;
        }
 
        if (h->nlmsg_len < sizeof(struct nlmsghdr)+sizeof(struct ifaddrmsg)) {
@@ -239,6 +241,17 @@ static void addrchange_done(struct tevent_req *subreq)
        }
 
        tevent_req_done(req);
+       return;
+
+retry:
+       state->fromaddr_len = sizeof(state->fromaddr);
+       subreq = recvfrom_send(state, state->ev, state->ctx->sock,
+                              state->buf, sizeof(state->buf), 0,
+                              &state->fromaddr, &state->fromaddr_len);
+       if (tevent_req_nomem(subreq, req)) {
+               return;
+       }
+       tevent_req_set_callback(subreq, addrchange_done, req);
 }
 
 NTSTATUS addrchange_recv(struct tevent_req *req, enum addrchange_type *type,