Commit 7cebd20f authored by Simon Kelley's avatar Simon Kelley

import of dnsmasq-2.31.tar.gz

parent 26d0dbaf
...@@ -1803,9 +1803,35 @@ version 2.29 ...@@ -1803,9 +1803,35 @@ version 2.29
version 2.30 version 2.30
Fixed crash when a DHCP client requested a broadcast Fixed crash when a DHCP client requested a broadcast
reply. This problem was introduced in version 2.29. reply. This problem was introduced in version 2.28.
Thanks to Sandra Dekkers for the bug report. Thanks to Sandra Dekkers for the bug report.
version 2.31
Added --dhcp-script option. There have been calls for this
for a long time from many good people. Fabio Muzzi gets
the prize for finally convincing me.
Added example dbus config file and moved dbus stuff into
its own directory.
Removed horribly outdated Redhat RPM build files. These
are obsolete now that dnsmasq in in Fedora extras. Thanks
to Patrick "Jima" Laughton, the Fedora package
maintainer.
Added workaround for Linux kernel bug. This manifests
itself as failure of DHCP on kernels with "support for
classical IP over ATM" configured. That includes most
Debian kernel packages. Many thanks to A. Costa and
Benjamin Kudria for their huge efforts in chasing this
down.
Force-kill child processes when dnsmasq is sent a sigterm,
otherwise an unclosed TCP connection could keep dnsmasq
hanging round for a few minutes.
Tweaked config.h logic for uclibc build. It will now pick
up MMU and IPV6 status correctly on every system I tested.
......
...@@ -6,10 +6,10 @@ OBJS = cache.o rfc1035.o util.o option.o forward.o isc.o network.o \ ...@@ -6,10 +6,10 @@ OBJS = cache.o rfc1035.o util.o option.o forward.o isc.o network.o \
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o
.c.o: .c.o:
$(CC) $(CFLAGS) $(I18N) `../bld/pkg-wrapper $(PKG_CONFIG) --cflags dbus-1` $(RPM_OPT_FLAGS) -Wall -W -c $< $(CC) $(CFLAGS) $(COPTS) $(I18N) `echo $(COPTS) | ../bld/pkg-wrapper $(PKG_CONFIG) --cflags dbus-1` $(RPM_OPT_FLAGS) -Wall -W -c $<
dnsmasq : $(OBJS) dnsmasq : $(OBJS)
$(CC) -o $@ $(OBJS) `../bld/pkg-wrapper $(PKG_CONFIG) --libs dbus-1` $(LIBS) $(CC) -o $@ $(OBJS) `echo $(COPTS) | ../bld/pkg-wrapper $(PKG_CONFIG) --libs dbus-1` $(LIBS)
dnsmasq.pot : $(OBJS:.o=.c) dnsmasq.h config.h dnsmasq.pot : $(OBJS:.o=.c) dnsmasq.h config.h
xgettext -d dnsmasq --foreign-user --keyword=_ -o dnsmasq.pot -i $(OBJS:.o=.c) xgettext -d dnsmasq --foreign-user --keyword=_ -o dnsmasq.pot -i $(OBJS:.o=.c)
......
#!/bin/sh #!/bin/sh
if grep -q "^\#.*define.*HAVE_DBUS" config.h ; then if grep -q "^\#.*define.*HAVE_DBUS" config.h || grep -q HAVE_DBUS ; then
exec $* exec $*
fi fi
......
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="root">
<allow own="uk.org.thekelleys.dnsmasq"/>
<allow send_destination="uk.org.thekelleys.dnsmasq"/>
<allow send_interface="uk.org.thekelleys.dnsmasq"/>
</policy>
<policy context="default">
<deny own="uk.org.thekelleys.dnsmasq"/>
<deny send_destination="uk.org.thekelleys.dnsmasq"/>
<deny send_interface="uk.org.thekelleys.dnsmasq"/>
</policy>
</busconfig>
###############################################################################
#
# General mumbojumbo
#
###############################################################################
Name: dnsmasq
Version: 2.30
Release: 1
License: GPL
Group: System Environment/Daemons
Vendor: Simon Kelley
Packager: Simon Kelley
Distribution: Red Hat Linux
URL: http://www.thekelleys.org.uk/dnsmasq
Source0: %{name}-%{version}.tar.gz
Requires: chkconfig
BuildRoot: /var/tmp/%{name}-%{version}
Summary: A lightweight caching nameserver
%description
Dnsmasq is lightweight, easy to configure DNS forwarder and DHCP server. It
is designed to provide DNS and, optionally, DHCP, to a small network. It can
serve the names of local machines which are not in the global DNS. The DHCP
server integrates with the DNS server and allows machines with DHCP-allocated
addresses to appear in the DNS with names configured either in each host or
in a central configuration file. Dnsmasq supports static and dynamic DHCP
leases and BOOTP for network booting of diskless machines.
###############################################################################
#
# Build
#
###############################################################################
%prep
%setup -q
%build
make all-i18n PREFIX=/usr
###############################################################################
#
# Install
#
###############################################################################
%install
rm -rf $RPM_BUILD_ROOT
mkdir -p -m 755 $RPM_BUILD_ROOT/usr/sbin
mkdir -p -m 755 $RPM_BUILD_ROOT/etc/rc.d/init.d
mkdir -p -m 755 $RPM_BUILD_ROOT/usr/share/man/man8
cp rpm/dnsmasq.rh $RPM_BUILD_ROOT/etc/rc.d/init.d/dnsmasq
make install-i18n DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr
strip $RPM_BUILD_ROOT/usr/sbin/dnsmasq
cp src/dnsmasq $RPM_BUILD_ROOT/usr/sbin
cp dnsmasq.conf.example $RPM_BUILD_ROOT/etc/dnsmasq.conf
###############################################################################
#
# Clean up
#
###############################################################################
%clean
rm -rf $RPM_BUILD_ROOT
###############################################################################
#
# Post-install scriptlet
#
###############################################################################
%post
/sbin/chkconfig --add dnsmasq
###############################################################################
#
# Pre-uninstall scriptlet
#
# If there's a time when your package needs to have one last look around before
# the user erases it, the place to do it is in the %preun script. Anything that
# a package needs to do immediately prior to RPM taking any action to erase the
# package, can be done here.
#
###############################################################################
%preun
if [ $1 = 0 ]; then # execute this only if we are NOT doing an upgrade
service dnsmasq stop >/dev/null 2>&1
/sbin/chkconfig --del dnsmasq
fi
###############################################################################
#
# Post-uninstall scriptlet
#
# The %postun script executes after the package has been removed. It is the
# last chance for a package to clean up after itself.
#
###############################################################################
%postun
if [ "$1" -ge "1" ]; then
service dnsmasq restart >/dev/null 2>&1
fi
###############################################################################
#
# File list
#
###############################################################################
%files
%defattr(-,root,root)
%doc CHANGELOG COPYING FAQ doc.html setup.html UPGRADING_to_2.0
%config /etc/rc.d/init.d/dnsmasq
%config /etc/dnsmasq.conf
%attr(0755,root,root) /etc/rc.d/init.d/dnsmasq
%attr(0664,root,root) /etc/dnsmasq.conf
%attr(0755,root,root) /usr/sbin/dnsmasq
#%attr(0644,root,root) /usr/share/man/*/man8/dnsmasq*
%attr(0644,root,root) /usr/share/man/man8/dnsmasq*
%attr(0644,root,root) /usr/share/locale/*/LC_MESSAGES/*
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
############################################################################### ###############################################################################
Name: dnsmasq Name: dnsmasq
Version: 2.30 Version: 2.31
Release: 1 Release: 1
Copyright: GPL Copyright: GPL
Group: Productivity/Networking/DNS/Servers Group: Productivity/Networking/DNS/Servers
......
...@@ -285,6 +285,12 @@ bogus-priv ...@@ -285,6 +285,12 @@ bogus-priv
# http://www.isc.org/index.pl?/sw/dhcp/authoritative.php # http://www.isc.org/index.pl?/sw/dhcp/authoritative.php
#dhcp-authoritative #dhcp-authoritative
# Run an executable when a DHCP lease is created or destroyed.
# The arguments sent to the script are "add" or "del",
# then the MAC address, the IP address and finally the hostname
# if there is one.
#dhcp-script=/bin/echo
# Set the cachesize here. # Set the cachesize here.
#cache-size=150 #cache-size=150
......
...@@ -22,7 +22,8 @@ Supported platforms include Linux (with glibc and uclibc), *BSD and ...@@ -22,7 +22,8 @@ Supported platforms include Linux (with glibc and uclibc), *BSD and
Mac OS X. Mac OS X.
Dnsmasq is included in at least the following Linux distributions: Dnsmasq is included in at least the following Linux distributions:
Gentoo, Debian, Slackware, Suse, Gentoo, Debian, Slackware, Suse,
Smoothwall, IP-Cop, floppyfw, Firebox, LEAF, Freesco, fli4l, CoyoteLinux and Smoothwall, IP-Cop, floppyfw, Firebox, LEAF, Freesco, fli4l,
CoyoteLinux, Endian Firewall and
Clarkconnect. It is also available as a FreeBSD port and is used in Clarkconnect. It is also available as a FreeBSD port and is used in
Linksys wireless routers and the m0n0wall project. Linksys wireless routers and the m0n0wall project.
<P> <P>
......
...@@ -533,7 +533,34 @@ is given but no dhcp-range option is given then dnsmasq version 1 ...@@ -533,7 +533,34 @@ is given but no dhcp-range option is given then dnsmasq version 1
behaviour is activated. The file given is assumed to be an ISC dhcpd behaviour is activated. The file given is assumed to be an ISC dhcpd
lease file and parsed for leases which are then added to the DNS lease file and parsed for leases which are then added to the DNS
system if they have a hostname. This functionality may have been system if they have a hostname. This functionality may have been
excluded from dnsmasq at compile time, in which case an error will occur. excluded from dnsmasq at compile time, in which case an error will
occur. In any case note that ISC leasefile integration is a deprecated
feature. It should not be used in new installations, and will be
removed in a future release.
.TP
.B \-6 --dhcp-script=<path>
Whenever a new DHCP lease is created, or an old one destroyed, the
binary specified by this option is run. The arguments to the binary
are "add", "old" or "del", the MAC
address of the host (or "<null>"), the IP address, and the hostname,
if known. "add" means a lease has been created, "del" means it has
been destroyed, "old" is a notification of an existing lease when
dnsmasq starts or a change to MAC address or hostname of an existing lease.
The process is run as any unprivileged user which dnsmasq
runs as, so it may be necessary to inhibit dropping of the root user,
using the
.B -u
directive, if the script needs root privs.
The environment is inherited from the invoker of dnsmasq,
and all file decriptors are
closed except stdin, stdout and stderr which are open to /dev/null
(except in debug mode).
The script is not invoked concurrently: if subsequent lease
changes occur, the script is not invoked again until any existing
invokation exits. At dnsmasq startup, the script will be invoked for
all existing leases as they are read from the lease file. Expired
leases will be called with "del" and others with "old". <path>
must be an absolute pathname, no PATH search occurs.
.TP .TP
.B \-s, --domain=<domain> .B \-s, --domain=<domain>
Specifies the domain for the DHCP server. This has two effects; Specifies the domain for the DHCP server. This has two effects;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#!/bin/sh
#
# Startup script for the DNS caching server
#
# chkconfig: 2345 99 01
# description: This script starts your DNS caching server
# processname: dnsmasq
# pidfile: /var/run/dnsmasq.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
dnsmasq=/usr/sbin/dnsmasq
[ -f $dnsmasq ] || exit 0
# change this line if you want dnsmasq to serve an MX record for
# the host it is running on.
MAILHOSTNAME=""
# change this line if you want dns to get its upstream servers from
# somewhere other that /etc/resolv.conf
RESOLV_CONF=""
# change this if you want dnsmasq to cache any "hostname" or "client-hostname" from
# a dhcpd's lease file
DHCP_LEASE="/var/lib/dhcp/dhcpd.leases"
DOMAIN_SUFFIX=`dnsdomainname`
OPTIONS=""
if [ ! -z "${MAILHOSTNAME}" ]; then
OPTIONS="$OPTIONS -m $MAILHOSTNAME"
fi
if [ ! -z "${RESOLV_CONF}" ]; then
OPTIONS="$OPTIONS -r $RESOLV_CONF"
fi
if [ ! -z "${DHCP_LEASE}" ]; then
OPTIONS="$OPTIONS -l $DHCP_LEASE"
fi
if [ ! -z "${DOMAIN_SUFFIX}" ]; then
OPTIONS="$OPTIONS -s $DOMAIN_SUFFIX"
fi
RETVAL=0
# See how we were called.
case "$1" in
start)
echo -n "Starting dnsmasq: "
daemon $dnsmasq $OPTIONS
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/dnsmasq
;;
stop)
if test "x`pidof dnsmasq`" != x; then
echo -n "Shutting down dnsmasq: "
killproc dnsmasq
fi
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/dnsmasq /var/run/dnsmasq.pid
;;
status)
status dnsmasq
RETVAL=$?
;;
restart|reload)
$0 stop
$0 start
RETVAL=$?
;;
condrestart)
if test "x`/sbin/pidof dnsmasq`" != x; then
$0 stop
$0 start
RETVAL=$?
fi
;;
*)
echo "Usage: $0 {start|stop|restart|reload|condrestart|status}"
exit 1
esac
exit $RETVAL
...@@ -48,8 +48,13 @@ void init_bpf(struct daemon *daemon) ...@@ -48,8 +48,13 @@ void init_bpf(struct daemon *daemon)
{ {
sprintf(ifreq.iov_base, "/dev/bpf%d", i++); sprintf(ifreq.iov_base, "/dev/bpf%d", i++);
if ((daemon->dhcp_raw_fd = open(ifreq.iov_base, O_RDWR, 0)) != -1) if ((daemon->dhcp_raw_fd = open(ifreq.iov_base, O_RDWR, 0)) != -1)
{
int flags = fcntl(daemon->dhcp_raw_fd, F_GETFD);
if (flags != -1)
fcntl(daemon->dhcp_raw_fd, F_SETFD, flags | FD_CLOEXEC);
return; return;
} }
}
if (errno != EBUSY) if (errno != EBUSY)
die(_("cannot create DHCP BPF socket: %s"), NULL); die(_("cannot create DHCP BPF socket: %s"), NULL);
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
GNU General Public License for more details. GNU General Public License for more details.
*/ */
#define VERSION "2.30" #define VERSION "2.31"
#define FTABSIZ 150 /* max number of outstanding requests */ #define FTABSIZ 150 /* max number of outstanding requests */
#define MAX_PROCS 20 /* max no children for TCP requests */ #define MAX_PROCS 20 /* max no children for TCP requests */
...@@ -79,7 +79,8 @@ ...@@ -79,7 +79,8 @@
/* Get linux C library versions. */ /* Get linux C library versions. */
#if defined(__linux__) && !defined(__UCLIBC__) && !defined(__uClinux__) #if defined(__linux__) && !defined(__UCLIBC__) && !defined(__uClinux__)
# include <libio.h> /*# include <libio.h> */
# include <features.h>
#endif #endif
...@@ -203,11 +204,13 @@ NOTES: ...@@ -203,11 +204,13 @@ NOTES:
#define HAVE_DEV_URANDOM #define HAVE_DEV_URANDOM
#define HAVE_DEV_RANDOM #define HAVE_DEV_RANDOM
#undef HAVE_SOCKADDR_SA_LEN #undef HAVE_SOCKADDR_SA_LEN
#if !defined(__UCLIBC_HAS_MMU__) #if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__)
# define NO_FORK # define NO_FORK
#endif #endif
#if !defined(__UCLIBC_HAS_IPV6__) #if defined(__UCLIBC_HAS_IPV6__)
# define NO_IPV6 # ifndef IPV6_V6ONLY
# define IPV6_V6ONLY 26
# endif
#endif #endif
/* This is for glibc 2.x */ /* This is for glibc 2.x */
...@@ -282,4 +285,3 @@ typedef unsigned long in_addr_t; ...@@ -282,4 +285,3 @@ typedef unsigned long in_addr_t;
# define ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */ # define ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
#endif #endif
...@@ -240,7 +240,7 @@ DBusHandlerResult message_handler(DBusConnection *connection, ...@@ -240,7 +240,7 @@ DBusHandlerResult message_handler(DBusConnection *connection,
check_servers(daemon); check_servers(daemon);
} }
else if (strcmp(method, "ClearCache") == 0) else if (strcmp(method, "ClearCache") == 0)
clear_cache_and_reload(daemon); clear_cache_and_reload(daemon, dnsmasq_time());
else else
return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
......
...@@ -25,14 +25,13 @@ void dhcp_init(struct daemon *daemon) ...@@ -25,14 +25,13 @@ void dhcp_init(struct daemon *daemon)
{ {
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in saddr; struct sockaddr_in saddr;
int flags, oneopt = 1; int oneopt = 1;
struct dhcp_config *configs, *cp; struct dhcp_config *configs, *cp;
if (fd == -1) if (fd == -1)
die (_("cannot create DHCP socket : %s"), NULL); die (_("cannot create DHCP socket : %s"), NULL);
if ((flags = fcntl(fd, F_GETFL, 0)) == -1 || if (!fix_fd(fd) ||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
#if defined(HAVE_LINUX_NETWORK) #if defined(HAVE_LINUX_NETWORK)
setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 || setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 ||
#elif defined(IP_RECVIF) #elif defined(IP_RECVIF)
...@@ -203,8 +202,9 @@ void dhcp_packet(struct daemon *daemon, time_t now) ...@@ -203,8 +202,9 @@ void dhcp_packet(struct daemon *daemon, time_t now)
return; return;
lease_prune(NULL, now); /* lose any expired leases */ lease_prune(NULL, now); /* lose any expired leases */
iov.iov_len = dhcp_reply(daemon, parm.current, ifr.ifr_name, (size_t)sz, now, unicast_dest); iov.iov_len = dhcp_reply(daemon, parm.current, ifr.ifr_name, (size_t)sz, now, unicast_dest);
lease_update_file(daemon); lease_update_file(daemon, now);
lease_update_dns(daemon); lease_update_dns(daemon);
lease_collect(daemon);
if (iov.iov_len == 0) if (iov.iov_len == 0)
return; return;
...@@ -258,9 +258,18 @@ void dhcp_packet(struct daemon *daemon, time_t now) ...@@ -258,9 +258,18 @@ void dhcp_packet(struct daemon *daemon, time_t now)
/* unicast to unconfigured client */ /* unicast to unconfigured client */
dest.sin_addr = mess->yiaddr; dest.sin_addr = mess->yiaddr;
dest.sin_port = htons(DHCP_CLIENT_PORT); dest.sin_port = htons(DHCP_CLIENT_PORT);
if (mess->hlen != 0 && mess->htype != 0) if (mess->hlen != 0 && mess->hlen <= 14 && mess->htype != 0)
arp_inject(daemon->netlinkfd, mess->yiaddr, iface_index, {
mess->chaddr, mess->hlen); /* inject mac address direct into ARP cache.
struct sockaddr limits size to 14 bytes. */
struct arpreq req;
*((struct sockaddr_in *)&req.arp_pa) = dest;
req.arp_ha.sa_family = mess->htype;
memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
strncpy(req.arp_dev, ifr.ifr_name, 16);
req.arp_flags = ATF_COM;
ioctl(daemon->dhcpfd, SIOCSARP, &req);
}
} }
#else #else
else else
......
...@@ -52,7 +52,7 @@ int main (int argc, char **argv) ...@@ -52,7 +52,7 @@ int main (int argc, char **argv)
time_t now, last = 0; time_t now, last = 0;
struct sigaction sigact; struct sigaction sigact;
struct iname *if_tmp; struct iname *if_tmp;
int flags, piperead, pipefd[2]; int piperead, pipefd[2];
unsigned char sig; unsigned char sig;
#ifndef NO_GETTEXT #ifndef NO_GETTEXT
...@@ -188,11 +188,7 @@ int main (int argc, char **argv) ...@@ -188,11 +188,7 @@ int main (int argc, char **argv)
} }
/* Use a pipe to carry signals back to the event loop in a race-free manner */ /* Use a pipe to carry signals back to the event loop in a race-free manner */
if (pipe(pipefd) == -1 || if (pipe(pipefd) == -1 || !fix_fd(pipefd[0]) || !fix_fd(pipefd[1]))
(flags = fcntl(pipefd[0], F_GETFL)) == -1 ||
fcntl(pipefd[0], F_SETFL, flags | O_NONBLOCK) == -1 ||
(flags = fcntl(pipefd[1], F_GETFL)) == -1 ||
fcntl(pipefd[1], F_SETFL, flags | O_NONBLOCK) == -1)
die(_("cannot create pipe: %s"), NULL); die(_("cannot create pipe: %s"), NULL);
piperead = pipefd[0]; piperead = pipefd[0];
...@@ -207,6 +203,7 @@ int main (int argc, char **argv) ...@@ -207,6 +203,7 @@ int main (int argc, char **argv)
struct passwd *ent_pw = daemon->username ? getpwnam(daemon->username) : NULL; struct passwd *ent_pw = daemon->username ? getpwnam(daemon->username) : NULL;
fd_set test_set; fd_set test_set;
int maxfd, i; int maxfd, i;
int nullfd = open("/dev/null", O_RDWR);
#ifdef HAVE_LINUX_NETWORK #ifdef HAVE_LINUX_NETWORK
cap_user_header_t hdr = NULL; cap_user_header_t hdr = NULL;
...@@ -214,7 +211,7 @@ int main (int argc, char **argv) ...@@ -214,7 +211,7 @@ int main (int argc, char **argv)
/* On linux, we keep CAP_NETADMIN (for ARP-injection) and /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
CAP_NET_RAW (for icmp) if we're doing dhcp */ CAP_NET_RAW (for icmp) if we're doing dhcp */
if (ent_pw) if (ent_pw && ent_pw->pw_uid != 0)
{ {
hdr = safe_malloc(sizeof(*hdr)); hdr = safe_malloc(sizeof(*hdr));
data = safe_malloc(sizeof(*data)); data = safe_malloc(sizeof(*data));
...@@ -246,12 +243,12 @@ int main (int argc, char **argv) ...@@ -246,12 +243,12 @@ int main (int argc, char **argv)
if (!(daemon->options & OPT_NO_FORK)) if (!(daemon->options & OPT_NO_FORK))
{ {
if (fork() != 0 ) if (fork() != 0 )
exit(0); _exit(0);
setsid(); setsid();
if (fork() != 0) if (fork() != 0)
exit(0); _exit(0);
} }
#endif #endif
...@@ -289,22 +286,30 @@ int main (int argc, char **argv) ...@@ -289,22 +286,30 @@ int main (int argc, char **argv)
if (i <= maxfd && FD_ISSET(i, &test_set)) if (i <= maxfd && FD_ISSET(i, &test_set))
continue; continue;
/* open stdout etc to /dev/null */
if (i == STDOUT_FILENO || i == STDERR_FILENO || i == STDIN_FILENO)
dup2(nullfd, i);
else
close(i); close(i);
} }
/* Change uid and gid for security */ if (daemon->groupname || ent_pw)
if (ent_pw)
{ {
gid_t dummy; gid_t dummy;
struct group *gp; struct group *gp;
/* change group for /etc/ppp/resolv.conf otherwise get the group for "nobody" */
if ((daemon->groupname && (gp = getgrnam(daemon->groupname))) ||
(ent_pw && (gp = getgrgid(ent_pw->pw_gid))))
{
/* remove all supplimentary groups */ /* remove all supplimentary groups */
setgroups(0, &dummy); setgroups(0, &dummy);
/* change group for /etc/ppp/resolv.conf
otherwise get the group for "nobody" */
if ((daemon->groupname && (gp = getgrnam(daemon->groupname))) ||
(gp = getgrgid(ent_pw->pw_gid)))
setgid(gp->gr_gid); setgid(gp->gr_gid);
}
}
if (ent_pw && ent_pw->pw_uid != 0)
{
/* finally drop root */ /* finally drop root */
setuid(ent_pw->pw_uid); setuid(ent_pw->pw_uid);
...@@ -382,6 +387,10 @@ int main (int argc, char **argv) ...@@ -382,6 +387,10 @@ int main (int argc, char **argv)
pid = getpid(); pid = getpid();
/* Start lease-change script */
if (daemon->dhcp)
lease_collect(daemon);
while (1) while (1)
{ {
int maxfd; int maxfd;
...@@ -486,11 +495,13 @@ int main (int argc, char **argv) ...@@ -486,11 +495,13 @@ int main (int argc, char **argv)
if (FD_ISSET(piperead, &rset)) if (FD_ISSET(piperead, &rset))
{ {
pid_t p;
if (read(piperead, &sig, 1) == 1) if (read(piperead, &sig, 1) == 1)
switch (sig) switch (sig)
{ {
case SIGHUP: case SIGHUP:
clear_cache_and_reload(daemon); clear_cache_and_reload(daemon, now);
if (daemon->resolv_files && (daemon->options & OPT_NO_POLL)) if (daemon->resolv_files && (daemon->options & OPT_NO_POLL))
{ {
reload_servers(daemon->resolv_files->name, daemon); reload_servers(daemon->resolv_files->name, daemon);
...@@ -504,21 +515,59 @@ int main (int argc, char **argv) ...@@ -504,21 +515,59 @@ int main (int argc, char **argv)
case SIGALRM: case SIGALRM:
if (daemon->dhcp) if (daemon->dhcp)
lease_update_file(daemon); {
lease_prune(NULL, now);
lease_update_file(daemon, now);
lease_collect(daemon);
}
break; break;
case SIGTERM: case SIGTERM:
{
int i;
syslog(LOG_INFO, _("exiting on receipt of SIGTERM")); syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
/* Knock all our children on the head. */
for (i = 0; i < MAX_PROCS; i++)
if (daemon->tcp_pids[i] != 0)
kill(daemon->tcp_pids[i], SIGQUIT);
if (daemon->dhcp) if (daemon->dhcp)
{
if (daemon->script_pid != 0)
kill(daemon->script_pid, SIGQUIT);
/* close this carefully */
fclose(daemon->lease_stream); fclose(daemon->lease_stream);
}
exit(0); exit(0);
}
case SIGCHLD: case SIGCHLD:
/* See Stevens 5.10 */ /* See Stevens 5.10 */
while (waitpid(-1, NULL, WNOHANG) > 0) /* Note that if a script process forks and then exits
without waiting for its child, we will reap that child.
It is not therefore safe to assume that any dieing children
whose pid != script_pid are TCP server threads. */
while ((p = waitpid(-1, NULL, WNOHANG)) > 0)
{
if (p == daemon->script_pid)
{
daemon->script_pid = 0;
lease_collect(daemon);
}
else
{
int i;
for (i = 0 ; i < MAX_PROCS; i++)
if (daemon->tcp_pids[i] == p)
{
daemon->tcp_pids[i] = 0;
daemon->num_kids--; daemon->num_kids--;
break; break;
}
}
}
break;
} }
} }
...@@ -567,12 +616,12 @@ static void sig_handler(int sig) ...@@ -567,12 +616,12 @@ static void sig_handler(int sig)
{ {
/* alarm is used to kill children after a fixed time. */ /* alarm is used to kill children after a fixed time. */
if (sig == SIGALRM) if (sig == SIGALRM)
exit(0); _exit(0);
} }
} }
void clear_cache_and_reload(struct daemon *daemon) void clear_cache_and_reload(struct daemon *daemon, time_t now)
{ {
cache_reload(daemon->options, daemon->namebuff, daemon->domain_suffix, daemon->addn_hosts); cache_reload(daemon->options, daemon->namebuff, daemon->domain_suffix, daemon->addn_hosts);
if (daemon->dhcp) if (daemon->dhcp)
...@@ -581,7 +630,7 @@ void clear_cache_and_reload(struct daemon *daemon) ...@@ -581,7 +630,7 @@ void clear_cache_and_reload(struct daemon *daemon)
dhcp_read_ethers(daemon); dhcp_read_ethers(daemon);
dhcp_update_configs(daemon->dhcp_conf); dhcp_update_configs(daemon->dhcp_conf);
lease_update_from_configs(daemon); lease_update_from_configs(daemon);
lease_update_file(daemon); lease_update_file(daemon, now);
lease_update_dns(daemon); lease_update_dns(daemon);
} }
} }
...@@ -628,12 +677,13 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now) ...@@ -628,12 +677,13 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now)
if (FD_ISSET(listener->tcpfd, set)) if (FD_ISSET(listener->tcpfd, set))
{ {
int confd; int confd;
struct irec *iface = NULL;
pid_t p;
while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR); while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
if (confd != -1) if (confd == -1)
{ continue;
struct irec *iface = NULL;
if (daemon->options & OPT_NOWILD) if (daemon->options & OPT_NOWILD)
iface = listener->iface; iface = listener->iface;
...@@ -656,11 +706,24 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now) ...@@ -656,11 +706,24 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now)
} }
if ((daemon->num_kids >= MAX_PROCS) || !iface) if ((daemon->num_kids >= MAX_PROCS) || !iface)
{
shutdown(confd, SHUT_RDWR);
close(confd); close(confd);
}
#ifndef NO_FORK #ifndef NO_FORK
else if (!(daemon->options & OPT_DEBUG) && 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;
}
daemon->num_kids++; daemon->num_kids++;
}
close(confd); close(confd);
} }
#endif #endif
...@@ -693,30 +756,36 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now) ...@@ -693,30 +756,36 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now)
buff = tcp_request(daemon, confd, now, dst_addr_4, iface->netmask); buff = tcp_request(daemon, confd, now, dst_addr_4, iface->netmask);
if (!(daemon->options & OPT_DEBUG)) shutdown(confd, SHUT_RDWR);
exit(0);
close(confd); close(confd);
if (buff) if (buff)
free(buff); free(buff);
for (s = daemon->servers; s; s = s->next) for (s = daemon->servers; s; s = s->next)
if (s->tcpfd != -1) if (s->tcpfd != -1)
{
shutdown(s->tcpfd, SHUT_RDWR);
close(s->tcpfd); close(s->tcpfd);
} }
#ifndef NO_FORK
if (!(daemon->options & OPT_DEBUG))
_exit(0);
#endif
} }
} }
} }
} }
int make_icmp_sock(void) int make_icmp_sock(void)
{ {
int fd, flags; int fd;
int zeroopt = 0; int zeroopt = 0;
if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1) if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
{ {
if ((flags = fcntl(fd, F_GETFL, 0)) == -1 || if (!fix_fd(fd) ||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1) setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
{ {
close(fd); close(fd);
......
...@@ -288,7 +288,9 @@ struct dhcp_lease { ...@@ -288,7 +288,9 @@ struct dhcp_lease {
int clid_len; /* length of client identifier */ int clid_len; /* length of client identifier */
unsigned char *clid; /* clientid */ unsigned char *clid; /* clientid */
char *hostname, *fqdn; /* name from client-hostname option or config */ char *hostname, *fqdn; /* name from client-hostname option or config */
int auth_name; /* hostname came from config, not from client */ char auth_name; /* hostname came from config, not from client */
char new; /* newly created */
char old; /* read from leasefile */
time_t expires; /* lease expiry */ time_t expires; /* lease expiry */
#ifdef HAVE_BROKEN_RTC #ifdef HAVE_BROKEN_RTC
unsigned int length; unsigned int length;
...@@ -411,6 +413,7 @@ struct daemon { ...@@ -411,6 +413,7 @@ struct daemon {
char *username, *groupname; char *username, *groupname;
char *domain_suffix; char *domain_suffix;
char *runfile; char *runfile;
char *lease_change_command;
struct iname *if_names, *if_addrs, *if_except, *dhcp_except; struct iname *if_names, *if_addrs, *if_except, *dhcp_except;
struct bogus_addr *bogus_addr; struct bogus_addr *bogus_addr;
struct server *servers; struct server *servers;
...@@ -440,6 +443,7 @@ struct daemon { ...@@ -440,6 +443,7 @@ struct daemon {
struct server *last_server; struct server *last_server;
struct server *srv_save; /* Used for resend on DoD */ struct server *srv_save; /* Used for resend on DoD */
size_t packet_len; /* " " */ size_t packet_len; /* " " */
pid_t script_pid, tcp_pids[MAX_PROCS];
int num_kids; int num_kids;
/* DHCP state */ /* DHCP state */
...@@ -522,6 +526,8 @@ int parse_hex(char *in, unsigned char *out, int maxlen, ...@@ -522,6 +526,8 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
int memcmp_masked(unsigned char *a, unsigned char *b, int len, int memcmp_masked(unsigned char *a, unsigned char *b, int len,
unsigned int mask); unsigned int mask);
int expand_buf(struct iovec *iov, size_t size); int expand_buf(struct iovec *iov, size_t size);
char *print_mac(struct daemon *daemon, unsigned char *mac, int len);
/* option.c */ /* option.c */
struct daemon *read_opts (int argc, char **argv, char *compile_opts); struct daemon *read_opts (int argc, char **argv, char *compile_opts);
...@@ -541,6 +547,7 @@ struct listener *create_wildcard_listeners(int port); ...@@ -541,6 +547,7 @@ struct listener *create_wildcard_listeners(int port);
struct listener *create_bound_listeners(struct daemon *daemon); struct listener *create_bound_listeners(struct daemon *daemon);
int iface_check(struct daemon *daemon, int family, int iface_check(struct daemon *daemon, int family,
struct all_addr *addr, char *name); struct all_addr *addr, char *name);
int fix_fd(int fd);
/* dhcp.c */ /* dhcp.c */
void dhcp_init(struct daemon *daemon); void dhcp_init(struct daemon *daemon);
...@@ -564,12 +571,11 @@ char *strip_hostname(struct daemon *daemon, char *hostname); ...@@ -564,12 +571,11 @@ char *strip_hostname(struct daemon *daemon, char *hostname);
char *host_from_dns(struct daemon *daemon, struct in_addr addr); char *host_from_dns(struct daemon *daemon, struct in_addr addr);
/* lease.c */ /* lease.c */
void lease_update_file(struct daemon *daemon); void lease_update_file(struct daemon *daemon, time_t now);
void lease_update_dns(struct daemon *daemon); void lease_update_dns(struct daemon *daemon);
void lease_init(struct daemon *daemon, time_t now); void lease_init(struct daemon *daemon, time_t now);
struct dhcp_lease *lease_allocate(unsigned char *hwaddr, unsigned char *clid, struct dhcp_lease *lease_allocate(struct in_addr addr);
int hw_len, int hw_type, int clid_len, struct in_addr addr); void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
int lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
unsigned char *clid, int hw_len, int hw_type, int clid_len); unsigned char *clid, int hw_len, int hw_type, int clid_len);
void lease_set_hostname(struct dhcp_lease *lease, char *name, void lease_set_hostname(struct dhcp_lease *lease, char *name,
char *suffix, int auth); char *suffix, int auth);
...@@ -579,6 +585,7 @@ struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int h ...@@ -579,6 +585,7 @@ struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int h
struct dhcp_lease *lease_find_by_addr(struct in_addr addr); struct dhcp_lease *lease_find_by_addr(struct in_addr addr);
void lease_prune(struct dhcp_lease *target, time_t now); void lease_prune(struct dhcp_lease *target, time_t now);
void lease_update_from_configs(struct daemon *daemon); void lease_update_from_configs(struct daemon *daemon);
void lease_collect(struct daemon *daemon);
/* rfc2131.c */ /* rfc2131.c */
size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_name, size_t sz, time_t now, int unicast_dest); size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *iface_name, size_t sz, time_t now, int unicast_dest);
...@@ -586,7 +593,7 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa ...@@ -586,7 +593,7 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
/* dnsmasq.c */ /* dnsmasq.c */
int make_icmp_sock(void); int make_icmp_sock(void);
int icmp_ping(struct daemon *daemon, struct in_addr addr); int icmp_ping(struct daemon *daemon, struct in_addr addr);
void clear_cache_and_reload(struct daemon *daemon); void clear_cache_and_reload(struct daemon *daemon, time_t now);
/* isc.c */ /* isc.c */
#ifdef HAVE_ISC_READER #ifdef HAVE_ISC_READER
...@@ -599,8 +606,6 @@ void netlink_init(struct daemon *daemon); ...@@ -599,8 +606,6 @@ void netlink_init(struct daemon *daemon);
int iface_enumerate(struct daemon *daemon, void *parm, int iface_enumerate(struct daemon *daemon, void *parm,
int (*ipv4_callback)(), int (*ipv6_callback)()); int (*ipv4_callback)(), int (*ipv6_callback)());
void netlink_multicast(struct daemon *daemon); void netlink_multicast(struct daemon *daemon);
void arp_inject(int fd, struct in_addr addr,
int iface, unsigned char *mac, unsigned int mac_len);
#endif #endif
/* bpf.c */ /* bpf.c */
......
This diff is collapsed.
...@@ -48,7 +48,13 @@ void netlink_init(struct daemon *daemon) ...@@ -48,7 +48,13 @@ void netlink_init(struct daemon *daemon)
} }
if (daemon->netlinkfd == -1) if (daemon->netlinkfd == -1)
die(_("cannot create RTnetlink socket: %s"), NULL); die(_("cannot create netlink socket: %s"), NULL);
else
{
int flags = fcntl(daemon->netlinkfd, F_GETFD);
if (flags != -1)
fcntl(daemon->netlinkfd, F_SETFD, flags | FD_CLOEXEC);
}
iov.iov_len = 200; iov.iov_len = 200;
iov.iov_base = safe_malloc(iov.iov_len); iov.iov_base = safe_malloc(iov.iov_len);
...@@ -114,7 +120,7 @@ int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), i ...@@ -114,7 +120,7 @@ int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), i
again: again:
req.nlh.nlmsg_len = sizeof(req); req.nlh.nlmsg_len = sizeof(req);
req.nlh.nlmsg_type = RTM_GETADDR; req.nlh.nlmsg_type = RTM_GETADDR;
req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST | NLM_F_ACK;
req.nlh.nlmsg_pid = 0; req.nlh.nlmsg_pid = 0;
req.nlh.nlmsg_seq = ++seq; req.nlh.nlmsg_seq = ++seq;
req.g.rtgen_family = family; req.g.rtgen_family = family;
...@@ -215,7 +221,7 @@ static void nl_err(struct nlmsghdr *h) ...@@ -215,7 +221,7 @@ static void nl_err(struct nlmsghdr *h)
{ {
struct nlmsgerr *err = NLMSG_DATA(h); struct nlmsgerr *err = NLMSG_DATA(h);
if (err->error != 0) if (err->error != 0)
syslog(LOG_ERR, _("RTnetlink returns error: %s"), strerror(-(err->error))); syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
} }
/* We arrange to receive netlink multicast messages whenever the network route is added. /* We arrange to receive netlink multicast messages whenever the network route is added.
...@@ -234,45 +240,6 @@ static void nl_routechange(struct daemon *daemon, struct nlmsghdr *h) ...@@ -234,45 +240,6 @@ static void nl_routechange(struct daemon *daemon, struct nlmsghdr *h)
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send()); &daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
} }
} }
void arp_inject(int fd, struct in_addr ip_addr, int iface,
unsigned char *mac, unsigned int mac_len)
{
struct sockaddr_nl addr;
struct {
struct nlmsghdr nlh;
struct ndmsg m;
struct rtattr addr_attr;
struct in_addr addr;
struct rtattr ll_attr;
char mac[DHCP_CHADDR_MAX];
} req;
memset(&req, 0, sizeof(req));
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
req.nlh.nlmsg_len = sizeof(req);
req.nlh.nlmsg_type = RTM_NEWNEIGH;
req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE;
req.m.ndm_family = AF_INET;
req.m.ndm_ifindex = iface;
req.m.ndm_state = NUD_REACHABLE;
req.addr_attr.rta_type = NDA_DST;
req.addr_attr.rta_len = RTA_LENGTH(sizeof(struct in_addr));
req.addr = ip_addr;
req.ll_attr.rta_type = NDA_LLADDR;
req.ll_attr.rta_len = RTA_LENGTH(mac_len);
memcpy(req.mac, mac, mac_len);
while(sendto(fd, (void *)&req, sizeof(req), 0, (struct sockaddr *)&addr, sizeof(addr)) == -1 &&
retry_send());
}
#endif #endif
...@@ -180,11 +180,25 @@ int enumerate_interfaces(struct daemon *daemon) ...@@ -180,11 +180,25 @@ int enumerate_interfaces(struct daemon *daemon)
#endif #endif
} }
/* set NONBLOCK and CLOEXEC bits on fd: See Stevens 16.6 */
int fix_fd(int fd)
{
int flags;
if ((flags = fcntl(fd, F_GETFL)) == -1 ||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
(flags = fcntl(fd, F_GETFD)) == -1 ||
fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
return 0;
return 1;
}
#if defined(HAVE_IPV6) #if defined(HAVE_IPV6)
static int create_ipv6_listener(struct listener **link, int port) static int create_ipv6_listener(struct listener **link, int port)
{ {
union mysockaddr addr; union mysockaddr addr;
int tcpfd, fd, flags; int tcpfd, fd;
struct listener *l; struct listener *l;
int opt = 1; int opt = 1;
...@@ -210,10 +224,8 @@ static int create_ipv6_listener(struct listener **link, int port) ...@@ -210,10 +224,8 @@ static int create_ipv6_listener(struct listener **link, int port)
setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
setsockopt(fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 || setsockopt(fd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
setsockopt(tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 || setsockopt(tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
(flags = fcntl(fd, F_GETFL, 0)) == -1 || !fix_fd(fd) ||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 || !fix_fd(tcpfd) ||
(flags = fcntl(tcpfd, F_GETFL, 0)) == -1 ||
fcntl(tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
#ifdef IPV6_RECVPKTINFO #ifdef IPV6_RECVPKTINFO
setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1 || setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1 ||
#else #else
...@@ -240,7 +252,6 @@ struct listener *create_wildcard_listeners(int port) ...@@ -240,7 +252,6 @@ struct listener *create_wildcard_listeners(int port)
union mysockaddr addr; union mysockaddr addr;
int opt = 1; int opt = 1;
struct listener *l, *l6 = NULL; struct listener *l, *l6 = NULL;
int flags;
int tcpfd, fd; int tcpfd, fd;
addr.in.sin_family = AF_INET; addr.in.sin_family = AF_INET;
...@@ -257,14 +268,12 @@ struct listener *create_wildcard_listeners(int port) ...@@ -257,14 +268,12 @@ struct listener *create_wildcard_listeners(int port)
if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 || bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
listen(tcpfd, 5) == -1 || listen(tcpfd, 5) == -1 ||
(flags = fcntl(tcpfd, F_GETFL, 0)) == -1 || !fix_fd(tcpfd) ||
fcntl(tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
!create_ipv6_listener(&l6, port) || !create_ipv6_listener(&l6, port) ||
#endif #endif
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
(flags = fcntl(fd, F_GETFL, 0)) == -1 || !fix_fd(fd) ||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
#if defined(HAVE_LINUX_NETWORK) #if defined(HAVE_LINUX_NETWORK)
setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 || setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
...@@ -288,7 +297,7 @@ struct listener *create_bound_listeners(struct daemon *daemon) ...@@ -288,7 +297,7 @@ struct listener *create_bound_listeners(struct daemon *daemon)
struct listener *listeners = NULL; struct listener *listeners = NULL;
struct irec *iface; struct irec *iface;
int flags, opt = 1; int opt = 1;
for (iface = daemon->interfaces; iface; iface = iface->next) for (iface = daemon->interfaces; iface; iface = iface->next)
{ {
...@@ -300,11 +309,8 @@ struct listener *create_bound_listeners(struct daemon *daemon) ...@@ -300,11 +309,8 @@ struct listener *create_bound_listeners(struct daemon *daemon)
(new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 || (new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || setsockopt(new->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
/* See Stevens 16.6 */ !fix_fd(new->tcpfd) ||
(flags = fcntl(new->tcpfd, F_GETFL, 0)) == -1 || !fix_fd(new->fd))
fcntl(new->tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
(flags = fcntl(new->fd, F_GETFL, 0)) == -1 ||
fcntl(new->fd, F_SETFL, flags | O_NONBLOCK) == -1)
die(_("failed to create listening socket: %s"), NULL); die(_("failed to create listening socket: %s"), NULL);
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
...@@ -348,7 +354,6 @@ struct listener *create_bound_listeners(struct daemon *daemon) ...@@ -348,7 +354,6 @@ struct listener *create_bound_listeners(struct daemon *daemon)
struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds) struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds)
{ {
struct serverfd *sfd; struct serverfd *sfd;
int flags;
/* may have a suitable one already */ /* may have a suitable one already */
for (sfd = *sfds; sfd; sfd = sfd->next ) for (sfd = *sfds; sfd; sfd = sfd->next )
...@@ -367,8 +372,7 @@ struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds) ...@@ -367,8 +372,7 @@ struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds)
} }
if (bind(sfd->fd, (struct sockaddr *)addr, sa_len(addr)) == -1 || if (bind(sfd->fd, (struct sockaddr *)addr, sa_len(addr)) == -1 ||
(flags = fcntl(sfd->fd, F_GETFL, 0)) == -1 || !fix_fd(sfd->fd))
fcntl(sfd->fd, F_SETFL, flags | O_NONBLOCK) == -1)
{ {
int errsave = errno; /* save error from bind. */ int errsave = errno; /* save error from bind. */
close(sfd->fd); close(sfd->fd);
......
This diff is collapsed.
This diff is collapsed.
...@@ -396,3 +396,17 @@ int expand_buf(struct iovec *iov, size_t size) ...@@ -396,3 +396,17 @@ int expand_buf(struct iovec *iov, size_t size)
return 1; return 1;
} }
char *print_mac(struct daemon *daemon, unsigned char *mac, int len)
{
char *p = daemon->namebuff;
int i;
if (len == 0)
sprintf(p, "<null>");
else
for (i = 0; i < len; i++)
p += sprintf(p, "%.2x%s", mac[i], (i == len - 1) ? "" : ":");
return daemon->namebuff;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment