version 1.1.1.2, 2014/06/15 16:31:38
|
version 1.1.1.3, 2016/11/02 09:57:01
|
Line 1
|
Line 1
|
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley | /* dnsmasq is Copyright (c) 2000-2016 Simon Kelley |
|
|
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
Line 38
|
Line 38
|
static struct iovec iov; |
static struct iovec iov; |
static u32 netlink_pid; |
static u32 netlink_pid; |
|
|
static int nl_async(struct nlmsghdr *h); | static void nl_async(struct nlmsghdr *h); |
|
|
void netlink_init(void) |
void netlink_init(void) |
{ |
{ |
Line 142 int iface_enumerate(int family, void *parm, int (*call
|
Line 142 int iface_enumerate(int family, void *parm, int (*call
|
struct nlmsghdr *h; |
struct nlmsghdr *h; |
ssize_t len; |
ssize_t len; |
static unsigned int seq = 0; |
static unsigned int seq = 0; |
int callback_ok = 1, newaddr = 0; | int callback_ok = 1; |
|
|
struct { |
struct { |
struct nlmsghdr nlh; |
struct nlmsghdr nlh; |
Line 169 int iface_enumerate(int family, void *parm, int (*call
|
Line 169 int iface_enumerate(int family, void *parm, int (*call
|
req.g.rtgen_family = family; |
req.g.rtgen_family = family; |
|
|
/* Don't block in recvfrom if send fails */ |
/* Don't block in recvfrom if send fails */ |
while((len = sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0, | while(retry_send(sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0, |
(struct sockaddr *)&addr, sizeof(addr))) == -1 && retry_send()); | (struct sockaddr *)&addr, sizeof(addr)))); |
| |
if (len == -1) | if (errno != 0) |
return 0; |
return 0; |
|
|
while (1) |
while (1) |
Line 191 int iface_enumerate(int family, void *parm, int (*call
|
Line 191 int iface_enumerate(int family, void *parm, int (*call
|
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR) |
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR) |
{ |
{ |
/* May be multicast arriving async */ |
/* May be multicast arriving async */ |
if (nl_async(h)) | nl_async(h); |
{ | |
newaddr = 1; | |
enumerate_interfaces(1); /* reset */ | |
} | |
} |
} |
else if (h->nlmsg_type == NLMSG_DONE) |
else if (h->nlmsg_type == NLMSG_DONE) |
{ | return callback_ok; |
/* handle async new interface address arrivals, these have to be done | |
after we complete as we're not re-entrant */ | |
if (newaddr) | |
newaddress(dnsmasq_time()); | |
| |
return callback_ok; | |
} | |
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL) |
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL) |
{ |
{ |
struct ifaddrmsg *ifa = NLMSG_DATA(h); |
struct ifaddrmsg *ifa = NLMSG_DATA(h); |
Line 219 int iface_enumerate(int family, void *parm, int (*call
|
Line 208 int iface_enumerate(int family, void *parm, int (*call
|
struct in_addr netmask, addr, broadcast; |
struct in_addr netmask, addr, broadcast; |
char *label = NULL; |
char *label = NULL; |
|
|
netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen)); | netmask.s_addr = htonl(~(in_addr_t)0 << (32 - ifa->ifa_prefixlen)); |
| |
addr.s_addr = 0; |
addr.s_addr = 0; |
broadcast.s_addr = 0; |
broadcast.s_addr = 0; |
|
|
Line 298 int iface_enumerate(int family, void *parm, int (*call
|
Line 288 int iface_enumerate(int family, void *parm, int (*call
|
rta = RTA_NEXT(rta, len1); |
rta = RTA_NEXT(rta, len1); |
} |
} |
|
|
if (inaddr && mac && callback_ok) | if (!(neigh->ndm_state & (NUD_NOARP | NUD_INCOMPLETE | NUD_FAILED)) && |
| inaddr && mac && callback_ok) |
if (!((*callback)(neigh->ndm_family, inaddr, mac, maclen, parm))) |
if (!((*callback)(neigh->ndm_family, inaddr, mac, maclen, parm))) |
callback_ok = 0; |
callback_ok = 0; |
} |
} |
Line 330 int iface_enumerate(int family, void *parm, int (*call
|
Line 321 int iface_enumerate(int family, void *parm, int (*call
|
} |
} |
} |
} |
|
|
void netlink_multicast(time_t now) | void netlink_multicast(void) |
{ |
{ |
ssize_t len; |
ssize_t len; |
struct nlmsghdr *h; |
struct nlmsghdr *h; |
int flags, newaddr = 0; | int flags; |
|
|
/* don't risk blocking reading netlink messages here. */ |
/* don't risk blocking reading netlink messages here. */ |
if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 || |
if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 || |
Line 343 void netlink_multicast(time_t now)
|
Line 334 void netlink_multicast(time_t now)
|
|
|
if ((len = netlink_recv()) != -1) |
if ((len = netlink_recv()) != -1) |
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len)) |
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len)) |
if (nl_async(h)) | nl_async(h); |
newaddr = 1; | |
|
|
/* restore non-blocking status */ |
/* restore non-blocking status */ |
fcntl(daemon->netlinkfd, F_SETFL, flags); |
fcntl(daemon->netlinkfd, F_SETFL, flags); |
|
|
if (newaddr) |
|
newaddress(now); |
|
} |
} |
|
|
static int nl_async(struct nlmsghdr *h) | static void nl_async(struct nlmsghdr *h) |
{ |
{ |
if (h->nlmsg_type == NLMSG_ERROR) |
if (h->nlmsg_type == NLMSG_ERROR) |
{ |
{ |
struct nlmsgerr *err = NLMSG_DATA(h); |
struct nlmsgerr *err = NLMSG_DATA(h); |
if (err->error != 0) |
if (err->error != 0) |
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error))); |
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error))); |
return 0; |
|
} |
} |
else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE) |
else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE) |
{ |
{ |
Line 372 static int nl_async(struct nlmsghdr *h)
|
Line 358 static int nl_async(struct nlmsghdr *h)
|
struct rtmsg *rtm = NLMSG_DATA(h); |
struct rtmsg *rtm = NLMSG_DATA(h); |
|
|
if (rtm->rtm_type == RTN_UNICAST && rtm->rtm_scope == RT_SCOPE_LINK) |
if (rtm->rtm_type == RTN_UNICAST && rtm->rtm_scope == RT_SCOPE_LINK) |
{ | queue_event(EVENT_NEWROUTE); |
/* Force re-reading resolv file right now, for luck. */ | |
daemon->last_resolv = 0; | |
| |
if (daemon->srv_save) | |
{ | |
int fd; | |
| |
if (daemon->srv_save->sfd) | |
fd = daemon->srv_save->sfd->fd; | |
else if (daemon->rfd_save && daemon->rfd_save->refcount != 0) | |
fd = daemon->rfd_save->fd; | |
else | |
return 0; | |
| |
while(sendto(fd, daemon->packet, daemon->packet_len, 0, | |
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send()); | |
} | |
} | |
return 0; | |
} |
} |
else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR) |
else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR) |
return 1; /* clever bind mode - rescan */ | queue_event(EVENT_NEWADDR); |
| |
return 0; | |
} |
} |
#endif |
#endif |
|
|