diff options
author | Volker Lendecke <vl@samba.org> | 2011-02-11 08:44:36 +0100 |
---|---|---|
committer | Volker Lendecke <vlendec@samba.org> | 2011-02-11 10:47:09 +0100 |
commit | 90c8de54a002d2038a1382c0d147026921a64227 (patch) | |
tree | 38130a1e9944e4f28c4f7d8cc83d951a69bba44f /source3/lib | |
parent | 44f2344a927fb28fa698de4ac6378b92d4333062 (diff) | |
download | samba-90c8de54a002d2038a1382c0d147026921a64227.tar.gz samba-90c8de54a002d2038a1382c0d147026921a64227.tar.bz2 samba-90c8de54a002d2038a1382c0d147026921a64227.zip |
s3: Add more checks and better fallback to addrchange
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
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/addrchange.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/source3/lib/addrchange.c b/source3/lib/addrchange.c index 8cd3c19ab5..bd4bfbaa46 100644 --- a/source3/lib/addrchange.c +++ b/source3/lib/addrchange.c @@ -125,6 +125,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; @@ -140,25 +141,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: @@ -169,16 +180,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)) { @@ -240,6 +242,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, |