import of dnsmasq-2.59.tar.gz

This commit is contained in:
Simon Kelley
2011-10-19 09:33:39 +01:00
parent 7de060b08d
commit 74c95c2542
17 changed files with 629 additions and 611 deletions

View File

@@ -184,7 +184,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
}
if (!((*callback)(addr,
(int)((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_scope_id,
(int)if_nametoindex(ifr->ifr_name),
(int)if_nametoindex(ifr->ifr_name), 0,
parm)))
goto err;
}

View File

@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define VERSION "2.58"
#define VERSION "2.59"
#define FTABSIZ 150 /* max number of outstanding requests (default) */
#define MAX_PROCS 20 /* max no children for TCP requests */
@@ -74,7 +74,6 @@
#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
#define LOG_MAX 5 /* log-queue length */
#define RANDFILE "/dev/urandom"
#define DAD_WAIT 20 /* retry binding IPv6 sockets for this long */
#define EDNS0_OPTION_MAC 5 /* dyndns.org temporary assignment */
/* DBUS interface specifics */

View File

@@ -190,7 +190,7 @@ int main (int argc, char **argv)
if (option_bool(OPT_NOWILD))
{
daemon->listeners = create_bound_listeners();
create_bound_listeners(1);
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
if (if_tmp->name && !if_tmp->used)
@@ -204,7 +204,7 @@ int main (int argc, char **argv)
}
}
else
daemon->listeners = create_wildcard_listeners();
create_wildcard_listeners();
if (daemon->port != 0)
cache_init();
@@ -397,11 +397,17 @@ int main (int argc, char **argv)
if (ent_pw && ent_pw->pw_uid != 0)
{
#if defined(HAVE_LINUX_NETWORK)
#if defined(HAVE_LINUX_NETWORK)
/* On linux, we keep CAP_NETADMIN (for ARP-injection) and
CAP_NET_RAW (for icmp) if we're doing dhcp */
data->effective = data->permitted = data->inheritable =
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
ports because of DAD, we need CAP_NET_BIND_SERVICE too. */
if (is_dad_listeners())
data->effective = data->permitted = data->inheritable =
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
(1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
else
data->effective = data->permitted = data->inheritable =
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
/* Tell kernel to not clear capabilities when dropping root */
if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
@@ -443,8 +449,12 @@ int main (int argc, char **argv)
}
#ifdef HAVE_LINUX_NETWORK
data->effective = data->permitted =
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
if (is_dad_listeners())
data->effective = data->permitted =
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
else
data->effective = data->permitted =
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
data->inheritable = 0;
/* lose the setuid and setgid capbilities */
@@ -605,6 +615,13 @@ int main (int argc, char **argv)
t.tv_usec = 250000;
tp = &t;
}
/* Wake every second whilst waiting for DAD to complete */
else if (is_dad_listeners())
{
t.tv_sec = 1;
t.tv_usec = 0;
tp = &t;
}
#ifdef HAVE_DBUS
set_dbus_listeners(&maxfd, &rset, &wset, &eset);
@@ -659,6 +676,15 @@ int main (int argc, char **argv)
now = dnsmasq_time();
check_log_writer(&wset);
/* Check the interfaces to see if any have exited DAD state
and if so, bind the address. */
if (is_dad_listeners())
{
enumerate_interfaces();
/* NB, is_dad_listeners() == 1 --> we're binding interfaces */
create_bound_listeners(0);
}
#ifdef HAVE_LINUX_NETWORK
if (FD_ISSET(daemon->netlinkfd, &rset))

View File

@@ -363,7 +363,7 @@ struct server {
struct irec {
union mysockaddr addr;
struct in_addr netmask; /* only valid for IPv4 */
int tftp_ok, mtu;
int tftp_ok, mtu, done, dad;
char *name;
struct irec *next;
};
@@ -829,8 +829,9 @@ void pre_allocate_sfds(void);
int reload_servers(char *fname);
void check_servers(void);
int enumerate_interfaces();
struct listener *create_wildcard_listeners(void);
struct listener *create_bound_listeners(void);
void create_wildcard_listeners(void);
void create_bound_listeners(int die);
int is_dad_listeners(void);
int iface_check(int family, struct all_addr *addr, char *name, int *indexp);
int fix_fd(int fd);
struct in_addr get_ifaddr(char *intr);

View File

@@ -222,7 +222,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
}
if (addrp)
if (!((*callback)(addrp, ifa->ifa_scope, ifa->ifa_index, parm)))
if (!((*callback)(addrp, ifa->ifa_index,
ifa->ifa_index, ifa->ifa_flags & IFA_F_TENTATIVE, parm)))
return 0;
}
#endif

View File

@@ -187,7 +187,7 @@ int iface_check(int family, struct all_addr *addr, char *name, int *indexp)
}
static int iface_allowed(struct irec **irecp, int if_index,
union mysockaddr *addr, struct in_addr netmask)
union mysockaddr *addr, struct in_addr netmask, int dad)
{
struct irec *iface;
int fd, mtu = 0, loopback;
@@ -202,8 +202,11 @@ static int iface_allowed(struct irec **irecp, int if_index,
we call this routine multiple times. */
for (iface = *irecp; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, addr))
return 1;
{
iface->dad = dad;
return 1;
}
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1 ||
!indextoname(fd, if_index, ifr.ifr_name) ||
ioctl(fd, SIOCGIFFLAGS, &ifr) == -1)
@@ -283,6 +286,8 @@ static int iface_allowed(struct irec **irecp, int if_index,
iface->netmask = netmask;
iface->tftp_ok = tftp_ok;
iface->mtu = mtu;
iface->dad = dad;
iface->done = 0;
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
strcpy(iface->name, ifr.ifr_name);
iface->next = *irecp;
@@ -296,7 +301,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
#ifdef HAVE_IPV6
static int iface_allowed_v6(struct in6_addr *local,
int scope, int if_index, void *vparam)
int scope, int if_index, int dad, void *vparam)
{
union mysockaddr addr;
struct in_addr netmask; /* dummy */
@@ -312,7 +317,7 @@ static int iface_allowed_v6(struct in6_addr *local,
addr.in6.sin6_port = htons(daemon->port);
addr.in6.sin6_scope_id = scope;
return iface_allowed((struct irec **)vparam, if_index, &addr, netmask);
return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, dad);
}
#endif
@@ -330,7 +335,7 @@ static int iface_allowed_v4(struct in_addr local, int if_index,
addr.in.sin_addr = local;
addr.in.sin_port = htons(daemon->port);
return iface_allowed((struct irec **)vparam, if_index, &addr, netmask);
return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, 0);
}
int enumerate_interfaces(void)
@@ -355,13 +360,10 @@ int fix_fd(int fd)
return 1;
}
static int make_sock(union mysockaddr *addr, int type)
static int make_sock(union mysockaddr *addr, int type, int dienow)
{
int family = addr->sa.sa_family;
int fd, rc, opt = 1;
#ifdef HAVE_IPV6
static int dad_count = 0;
#endif
if ((fd = socket(family, type, 0)) == -1)
{
@@ -374,11 +376,16 @@ static int make_sock(union mysockaddr *addr, int type)
return -1;
err:
port = prettyprint_addr(addr, daemon->namebuff);
if (!option_bool(OPT_NOWILD))
sprintf(daemon->namebuff, "port %d", port);
die(_("failed to create listening socket for %s: %s"),
daemon->namebuff, EC_BADNET);
if (dienow)
{
port = prettyprint_addr(addr, daemon->namebuff);
if (!option_bool(OPT_NOWILD))
sprintf(daemon->namebuff, "port %d", port);
die(_("failed to create listening socket for %s: %s"),
daemon->namebuff, EC_BADNET);
}
return -1;
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
@@ -389,27 +396,7 @@ static int make_sock(union mysockaddr *addr, int type)
goto err;
#endif
while (1)
{
if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) != -1)
break;
#ifdef HAVE_IPV6
/* An interface may have an IPv6 address which is still undergoing DAD.
If so, the bind will fail until the DAD completes, so we try over 20 seconds
before failing. */
if (family == AF_INET6 &&
(errno == ENODEV || errno == EADDRNOTAVAIL) &&
dad_count++ < DAD_WAIT)
{
sleep(1);
continue;
}
#endif
break;
}
if (rc == -1)
if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
goto err;
if (type == SOCK_STREAM)
@@ -462,15 +449,15 @@ static int make_sock(union mysockaddr *addr, int type)
return fd;
}
static struct listener *create_listeners(union mysockaddr *addr, int do_tftp)
static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, int dienow)
{
struct listener *l = NULL;
int fd = -1, tcpfd = -1, tftpfd = -1;
if (daemon->port != 0)
{
fd = make_sock(addr, SOCK_DGRAM);
tcpfd = make_sock(addr, SOCK_STREAM);
fd = make_sock(addr, SOCK_DGRAM, dienow);
tcpfd = make_sock(addr, SOCK_STREAM, dienow);
}
#ifdef HAVE_TFTP
@@ -481,7 +468,7 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp)
/* port must be restored to DNS port for TCP code */
short save = addr->in.sin_port;
addr->in.sin_port = htons(TFTP_PORT);
tftpfd = make_sock(addr, SOCK_DGRAM);
tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
addr->in.sin_port = save;
}
# ifdef HAVE_IPV6
@@ -489,7 +476,7 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp)
{
short save = addr->in6.sin6_port;
addr->in6.sin6_port = htons(TFTP_PORT);
tftpfd = make_sock(addr, SOCK_DGRAM);
tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
addr->in6.sin6_port = save;
}
# endif
@@ -509,7 +496,7 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp)
return l;
}
struct listener *create_wildcard_listeners(void)
void create_wildcard_listeners(void)
{
union mysockaddr addr;
struct listener *l;
@@ -523,7 +510,7 @@ struct listener *create_wildcard_listeners(void)
addr.in.sin_addr.s_addr = INADDR_ANY;
addr.in.sin_port = htons(daemon->port);
l = create_listeners(&addr, tftp_enabled);
l = create_listeners(&addr, tftp_enabled, 1);
#ifdef HAVE_IPV6
memset(&addr, 0, sizeof(addr));
@@ -535,31 +522,41 @@ struct listener *create_wildcard_listeners(void)
addr.in6.sin6_port = htons(daemon->port);
if (l)
l->next = create_listeners(&addr, tftp_enabled);
l->next = create_listeners(&addr, tftp_enabled, 1);
else
l = create_listeners(&addr, tftp_enabled);
l = create_listeners(&addr, tftp_enabled, 1);
#endif
return l;
daemon->listeners = l;
}
struct listener *create_bound_listeners(void)
void create_bound_listeners(int dienow)
{
struct listener *new, *listeners = NULL;
struct listener *new;
struct irec *iface;
for (iface = daemon->interfaces; iface; iface = iface->next)
if ((new = create_listeners(&iface->addr, iface->tftp_ok)))
if (!iface->done && !iface->dad &&
(new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
{
new->iface = iface;
new->next = listeners;
listeners = new;
new->next = daemon->listeners;
daemon->listeners = new;
iface->done = 1;
}
return listeners;
}
int is_dad_listeners(void)
{
struct irec *iface;
if (option_bool(OPT_NOWILD))
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->dad && !iface->done)
return 1;
return 0;
}
/* return a UDP socket bound to a random port, have to cope with straying into
occupied port nos and reserved ones. */
int random_sock(int family)