import of dnsmasq-2.36.tar.gz

This commit is contained in:
Simon Kelley
2007-01-21 20:01:28 +00:00
parent 4011c4e05e
commit 832af0bafb
31 changed files with 5064 additions and 2851 deletions

View File

@@ -109,6 +109,11 @@ int main (int argc, char **argv)
}
#endif
#ifndef HAVE_TFTP
if (daemon->options & OPT_TFTP)
die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL);
#endif
daemon->interfaces = NULL;
if (!enumerate_interfaces(daemon))
die(_("failed to find list of interfaces: %s"), NULL);
@@ -128,7 +133,7 @@ int main (int argc, char **argv)
die(_("no interface with address %s"), daemon->namebuff);
}
}
else if (!(daemon->listeners = create_wildcard_listeners(daemon->port)))
else if (!(daemon->listeners = create_wildcard_listeners(daemon->port, daemon->options & OPT_TFTP)))
die(_("failed to create listening socket: %s"), NULL);
cache_init(daemon->cachesize, daemon->options & OPT_LOG);
@@ -270,7 +275,7 @@ int main (int argc, char **argv)
}
/* if we are to run scripts, we need to fork a helper before dropping root. */
daemon->helperfd = create_helper(daemon);
daemon->helperfd = create_helper(daemon);
if (!(daemon->options & OPT_DEBUG))
{
@@ -381,6 +386,45 @@ int main (int argc, char **argv)
}
}
#ifdef HAVE_TFTP
if (daemon->options & OPT_TFTP)
{
long max_fd = sysconf(_SC_OPEN_MAX);
#ifdef FD_SETSIZE
if (FD_SETSIZE < max_fd)
max_fd = FD_SETSIZE;
#endif
syslog(LOG_INFO, "TFTP %s%s %s",
daemon->tftp_prefix ? _("root is ") : _("enabled"),
daemon->tftp_prefix ? daemon->tftp_prefix: "",
daemon->options & OPT_TFTP_SECURE ? _("secure mode") : "");
/* This is a guess, it assumes that for small limits,
disjoint files might be servered, but for large limits,
a single file will be sent to may clients (the file only needs
one fd). */
max_fd -= 30; /* use other than TFTP */
if (max_fd < 0)
max_fd = 5;
else if (max_fd < 100)
max_fd = max_fd/2;
else
max_fd = max_fd - 20;
if (daemon->tftp_max > max_fd)
{
daemon->tftp_max = max_fd;
syslog(LOG_WARNING,
_("restricting maximum simultaneous TFTP transfers to %d"),
daemon->tftp_max);
}
}
#endif
if (!(daemon->options & OPT_DEBUG) && (getuid() == 0 || geteuid() == 0))
{
if (bad_capabilities)
@@ -414,15 +458,16 @@ int main (int argc, char **argv)
tp = &t;
}
#ifdef HAVE_DBUS
/* Whilst polling for the dbus, wake every quarter second */
if ((daemon->options & OPT_DBUS) && !daemon->dbus)
/* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
if (daemon->tftp_trans ||
((daemon->options & OPT_DBUS) && !daemon->dbus))
{
t.tv_sec = 0;
t.tv_usec = 250000;
tp = &t;
}
#ifdef HAVE_DBUS
set_dbus_listeners(daemon, &maxfd, &rset, &wset, &eset);
#endif
@@ -614,7 +659,11 @@ int main (int argc, char **argv)
#endif
check_dns_listeners(daemon, &rset, now);
#ifdef HAVE_TFTP
check_tftp_listeners(daemon, &rset, now);
#endif
if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
dhcp_packet(daemon, now);
@@ -668,7 +717,18 @@ static int set_dns_listeners(struct daemon *daemon, time_t now, fd_set *set, int
struct serverfd *serverfdp;
struct listener *listener;
int wait, i;
#ifdef HAVE_TFTP
int tftp = 0;
struct tftp_transfer *transfer;
for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
{
tftp++;
FD_SET(transfer->sockfd, set);
bump_maxfd(transfer->sockfd, maxfdp);
}
#endif
/* will we be able to get memory? */
get_new_frec(daemon, now, &wait);
@@ -696,8 +756,17 @@ static int set_dns_listeners(struct daemon *daemon, time_t now, fd_set *set, int
bump_maxfd(listener->tcpfd, maxfdp);
break;
}
}
#ifdef HAVE_TFTP
if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
{
FD_SET(listener->tftpfd, set);
bump_maxfd(listener->tftpfd, maxfdp);
}
#endif
}
return wait;
}
@@ -705,116 +774,121 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now)
{
struct serverfd *serverfdp;
struct listener *listener;
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
if (FD_ISSET(serverfdp->fd, set))
reply_query(serverfdp, daemon, now);
for (listener = daemon->listeners; listener; listener = listener->next)
{
if (FD_ISSET(listener->fd, set))
receive_query(listener, daemon, now);
if (FD_ISSET(listener->tcpfd, set))
{
int confd;
struct irec *iface = NULL;
pid_t p;
while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
if (confd == -1)
continue;
if (daemon->options & OPT_NOWILD)
iface = listener->iface;
else
{
union mysockaddr tcp_addr;
socklen_t tcp_len = sizeof(union mysockaddr);
/* Check for allowed interfaces when binding the wildcard address:
we do this by looking for an interface with the same address as
the local address of the TCP connection, then looking to see if that's
an allowed interface. As a side effect, we get the netmask of the
interface too, for localisation. */
/* interface may be new since startup */
if (enumerate_interfaces(daemon) &&
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) != -1)
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr))
break;
}
if (!iface)
{
shutdown(confd, SHUT_RDWR);
close(confd);
}
#ifndef NO_FORK
else if (!(daemon->options & OPT_DEBUG) && (p = fork()) != 0)
{
if (p != -1)
{
int i;
for (i = 0; i < MAX_PROCS; i++)
if (daemon->tcp_pids[i] == 0)
{
daemon->tcp_pids[i] = p;
break;
}
}
close(confd);
}
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
if (FD_ISSET(serverfdp->fd, set))
reply_query(serverfdp, daemon, now);
for (listener = daemon->listeners; listener; listener = listener->next)
{
if (FD_ISSET(listener->fd, set))
receive_query(listener, daemon, now);
#ifdef HAVE_TFTP
if (listener->tftpfd != -1 && FD_ISSET(listener->tftpfd, set))
tftp_request(listener, daemon, now);
#endif
else
{
unsigned char *buff;
struct server *s;
int flags;
struct in_addr dst_addr_4;
dst_addr_4.s_addr = 0;
if (FD_ISSET(listener->tcpfd, set))
{
int confd;
struct irec *iface = NULL;
pid_t p;
while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
if (confd == -1)
continue;
if (daemon->options & OPT_NOWILD)
iface = listener->iface;
else
{
union mysockaddr tcp_addr;
socklen_t tcp_len = sizeof(union mysockaddr);
/* Check for allowed interfaces when binding the wildcard address:
we do this by looking for an interface with the same address as
the local address of the TCP connection, then looking to see if that's
an allowed interface. As a side effect, we get the netmask of the
interface too, for localisation. */
/* interface may be new since startup */
if (enumerate_interfaces(daemon) &&
getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) != -1)
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr))
break;
}
if (!iface)
{
shutdown(confd, SHUT_RDWR);
close(confd);
}
#ifndef NO_FORK
else if (!(daemon->options & OPT_DEBUG) && (p = fork()) != 0)
{
if (p != -1)
{
int i;
for (i = 0; i < MAX_PROCS; i++)
if (daemon->tcp_pids[i] == 0)
{
daemon->tcp_pids[i] = p;
break;
}
}
close(confd);
}
#endif
else
{
unsigned char *buff;
struct server *s;
int flags;
struct in_addr dst_addr_4;
dst_addr_4.s_addr = 0;
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to
terminate the process. */
if (!(daemon->options & OPT_DEBUG))
alarm(CHILD_LIFETIME);
/* start with no upstream connections. */
for (s = daemon->servers; s; s = s->next)
if (!(daemon->options & OPT_DEBUG))
alarm(CHILD_LIFETIME);
/* start with no upstream connections. */
for (s = daemon->servers; s; s = s->next)
s->tcpfd = -1;
/* The connected socket inherits non-blocking
attribute from the listening socket.
Reset that here. */
if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
if (listener->family == AF_INET)
dst_addr_4 = iface->addr.in.sin_addr;
buff = tcp_request(daemon, confd, now, dst_addr_4, iface->netmask);
/* The connected socket inherits non-blocking
attribute from the listening socket.
Reset that here. */
if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
if (listener->family == AF_INET)
dst_addr_4 = iface->addr.in.sin_addr;
buff = tcp_request(daemon, confd, now, dst_addr_4, iface->netmask);
shutdown(confd, SHUT_RDWR);
close(confd);
if (buff)
free(buff);
for (s = daemon->servers; s; s = s->next)
if (s->tcpfd != -1)
{
shutdown(s->tcpfd, SHUT_RDWR);
close(s->tcpfd);
}
shutdown(confd, SHUT_RDWR);
close(confd);
if (buff)
free(buff);
for (s = daemon->servers; s; s = s->next)
if (s->tcpfd != -1)
{
shutdown(s->tcpfd, SHUT_RDWR);
close(s->tcpfd);
}
#ifndef NO_FORK
if (!(daemon->options & OPT_DEBUG))
_exit(0);
if (!(daemon->options & OPT_DEBUG))
_exit(0);
#endif
}
}
}
}
}
}
}
@@ -841,7 +915,7 @@ int icmp_ping(struct daemon *daemon, struct in_addr addr)
/* Try and get an ICMP echo from a machine. */
/* Note that whilst in the three second wait, we check for
(and service) events on the DNS sockets, (so doing that
(and service) events on the DNS and TFTP sockets, (so doing that
better not use any resources our caller has in use...)
but we remain deaf to signals or further DHCP packets. */
@@ -900,13 +974,17 @@ int icmp_ping(struct daemon *daemon, struct in_addr addr)
FD_ZERO(&rset);
FD_SET(fd, &rset);
set_dns_listeners(daemon, now, &rset, &maxfd);
if (select(maxfd+1, &rset, NULL, NULL, &tv) < 0)
FD_ZERO(&rset);
now = dnsmasq_time();
check_dns_listeners(daemon, &rset, now);
#ifdef HAVE_TFTP
check_tftp_listeners(daemon, &rset, now);
#endif
if (FD_ISSET(fd, &rset) &&
recvfrom(fd, &packet, sizeof(packet), 0,
(struct sockaddr *)&faddr, &len) == sizeof(packet) &&