Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7cebd20fe7 | ||
|
|
26d0dbaf24 | ||
|
|
309331f52c |
51
CHANGELOG
51
CHANGELOG
@@ -1785,3 +1785,54 @@ version 2.28
|
||||
ignored, since this may be unreliable. This means that a DHCP
|
||||
client must use the standard port to do full configuration.
|
||||
|
||||
version 2.29
|
||||
Fixed compilation on OpenBSD (thanks to Tom Hensel for the
|
||||
report).
|
||||
|
||||
Fixed false "no interface" errors when --bind-interfaces is
|
||||
set along with --interface=lo or --listen-address. Thanks
|
||||
to Paul Wise for the report.
|
||||
|
||||
Updated patch for SuSE rpm. Thanks to Steven Springl.
|
||||
|
||||
It turns out that there are some Linux kernel
|
||||
configurations which make using the capability system
|
||||
impossible. If this situation occurs then continue, running
|
||||
as root, and log a warning. Thanks to Scott Wehrenberg
|
||||
for help tracking this down.
|
||||
|
||||
version 2.30
|
||||
Fixed crash when a DHCP client requested a broadcast
|
||||
reply. This problem was introduced in version 2.28.
|
||||
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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
9
FAQ
9
FAQ
@@ -369,6 +369,7 @@ A: Yes, dynmaically allocated IP addresses are checked by sending an
|
||||
other DHCP requests during this time. To avoid dropping requests,
|
||||
the address probe may be skipped when dnsmasq is under heavy load.
|
||||
|
||||
|
||||
Q: I'm using dnsmasq on a machine with the Firestarter firewall, and
|
||||
DHCP doesn't work. What's the problem?
|
||||
|
||||
@@ -376,7 +377,13 @@ A: This a variant on the iptables problem. Explicit details on how to
|
||||
proceed can be found at
|
||||
http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2005q3/000431.html
|
||||
|
||||
|
||||
|
||||
Q: Dnsmasq logs "running as root because setting capabilities failed"
|
||||
when it starts up. Why did that happen and what can do to fix it?
|
||||
|
||||
A: Change your kernel configuration: either deselect CONFIG_SECURITY
|
||||
_or_ select CONFIG_SECURITY_CAPABILITIES.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
.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)
|
||||
$(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
|
||||
xgettext -d dnsmasq --foreign-user --keyword=_ -o dnsmasq.pot -i $(OBJS:.o=.c)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/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 $*
|
||||
fi
|
||||
|
||||
|
||||
16
dbus/dnsmasq.conf
Normal file
16
dbus/dnsmasq.conf
Normal file
@@ -0,0 +1,16 @@
|
||||
<!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>
|
||||
|
||||
133
dnsmasq-rh.spec
133
dnsmasq-rh.spec
@@ -1,133 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# General mumbojumbo
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
Name: dnsmasq
|
||||
Version: 2.28
|
||||
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 @@
|
||||
###############################################################################
|
||||
|
||||
Name: dnsmasq
|
||||
Version: 2.28
|
||||
Version: 2.31
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Productivity/Networking/DNS/Servers
|
||||
|
||||
@@ -285,6 +285,12 @@ bogus-priv
|
||||
# http://www.isc.org/index.pl?/sw/dhcp/authoritative.php
|
||||
#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.
|
||||
#cache-size=150
|
||||
|
||||
|
||||
3
doc.html
3
doc.html
@@ -22,7 +22,8 @@ Supported platforms include Linux (with glibc and uclibc), *BSD and
|
||||
Mac OS X.
|
||||
Dnsmasq is included in at least the following Linux distributions:
|
||||
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
|
||||
Linksys wireless routers and the m0n0wall project.
|
||||
<P>
|
||||
|
||||
@@ -102,14 +102,11 @@ or
|
||||
options are given dnsmasq listens on all available interfaces except any
|
||||
given in
|
||||
.B \--except-interface
|
||||
options. If IP alias interfaces (eg "eth1:0") are used with
|
||||
options. IP alias interfaces (eg "eth1:0") cannot be used with
|
||||
.B --interface
|
||||
or
|
||||
.B --except-interface
|
||||
options, then the
|
||||
.B --bind-interfaces
|
||||
option will be automatically set. This is required for deeply boring
|
||||
sockets-API reasons.
|
||||
options, use --listen-address instead.
|
||||
.TP
|
||||
.B \-I, --except-interface=<interface name>
|
||||
Do not listen on the specified interface. Note that the order of
|
||||
@@ -148,9 +145,7 @@ working even when interfaces come and go and change address. This
|
||||
option forces dnsmasq to really bind only the interfaces it is
|
||||
listening on. About the only time when this is useful is when
|
||||
running another nameserver (or another instance of dnsmasq) on the
|
||||
same machine or when using IP
|
||||
alias. Specifying interfaces with IP alias automatically turns this
|
||||
option on. Setting this option also enables multiple instances of
|
||||
same machine. Setting this option also enables multiple instances of
|
||||
dnsmasq which provide DHCP service to run in the same machine.
|
||||
.TP
|
||||
.B \-y, --localise-queries
|
||||
@@ -538,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
|
||||
lease file and parsed for leases which are then added to the DNS
|
||||
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
|
||||
.B \-s, --domain=<domain>
|
||||
Specifies the domain for the DHCP server. This has two effects;
|
||||
|
||||
407
po/pt_BR.po
407
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@
|
||||
#define CHUSER "nobody"
|
||||
-#define CHGRP "dip"
|
||||
+#define CHGRP "dialout"
|
||||
#define IP6INTERFACES "/proc/net/if_inet6"
|
||||
#define UPTIME "/proc/uptime"
|
||||
#define DHCP_SERVER_PORT 67
|
||||
#define DHCP_CLIENT_PORT 68
|
||||
|
||||
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
#!/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
|
||||
|
||||
22
src/bpf.c
22
src/bpf.c
@@ -48,7 +48,12 @@ void init_bpf(struct daemon *daemon)
|
||||
{
|
||||
sprintf(ifreq.iov_base, "/dev/bpf%d", i++);
|
||||
if ((daemon->dhcp_raw_fd = open(ifreq.iov_base, O_RDWR, 0)) != -1)
|
||||
return;
|
||||
{
|
||||
int flags = fcntl(daemon->dhcp_raw_fd, F_GETFD);
|
||||
if (flags != -1)
|
||||
fcntl(daemon->dhcp_raw_fd, F_SETFD, flags | FD_CLOEXEC);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (errno != EBUSY)
|
||||
die(_("cannot create DHCP BPF socket: %s"), NULL);
|
||||
@@ -141,7 +146,7 @@ void send_via_bpf(struct daemon *daemon, struct dhcp_packet *mess, size_t len,
|
||||
int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
|
||||
{
|
||||
char *ptr;
|
||||
struct ifreq *ifr, ifaux;
|
||||
struct ifreq *ifr;
|
||||
struct ifconf ifc;
|
||||
int fd, errsav, ret = 0;
|
||||
int lastlen = 0;
|
||||
@@ -186,14 +191,10 @@ int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), i
|
||||
|
||||
ifr = ifreq.iov_base;
|
||||
memcpy(ifr, ptr, len);
|
||||
|
||||
strncpy(ifaux.ifr_name, ifr->ifr_name, IF_NAMESIZE);
|
||||
|
||||
if (ifr->ifr_addr.sa_family == AF_INET && ipv4_callback)
|
||||
{
|
||||
struct in_addr addr, netmask, broadcast;
|
||||
if (ioctl(fd, SIOCGIFINDEX, &ifaux) == -1)
|
||||
continue;
|
||||
broadcast.s_addr = 0;
|
||||
addr = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
|
||||
if (ioctl(fd, SIOCGIFNETMASK, ifr) == -1)
|
||||
@@ -201,7 +202,10 @@ int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), i
|
||||
netmask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
|
||||
if (ioctl(fd, SIOCGIFBRDADDR, ifr) != -1)
|
||||
broadcast = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
|
||||
if (!((*ipv4_callback)(daemon, addr, (int)ifaux.ifr_index, netmask, broadcast, parm)))
|
||||
if (!((*ipv4_callback)(daemon, addr,
|
||||
(int)if_nametoindex(ifr->ifr_name),
|
||||
netmask, broadcast,
|
||||
parm)))
|
||||
goto err;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
@@ -214,11 +218,9 @@ int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), i
|
||||
addr->s6_addr[2] = 0;
|
||||
addr->s6_addr[3] = 0;
|
||||
}
|
||||
if (ioctl(fd, SIOCGIFINDEX, &ifaux) == -1)
|
||||
continue;
|
||||
if (!((*ipv6_callback)(daemon, addr,
|
||||
(int)((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_scope_id,
|
||||
(int)ifaux.ifr_index,
|
||||
(int)if_nametoindex(ifr->ifr_name),
|
||||
parm)))
|
||||
goto err;
|
||||
}
|
||||
|
||||
22
src/config.h
22
src/config.h
@@ -10,7 +10,7 @@
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#define VERSION "2.28"
|
||||
#define VERSION "2.31"
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests */
|
||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||
@@ -79,7 +79,8 @@
|
||||
|
||||
/* Get linux C library versions. */
|
||||
#if defined(__linux__) && !defined(__UCLIBC__) && !defined(__uClinux__)
|
||||
# include <libio.h>
|
||||
/*# include <libio.h> */
|
||||
# include <features.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -165,10 +166,10 @@ NOTES:
|
||||
|
||||
*/
|
||||
|
||||
/* platform independent options. */
|
||||
#undef HAVE_BROKEN_RTC
|
||||
#undef HAVE_ISC_READER
|
||||
#undef HAVE_DBUS
|
||||
/* platform independent options- uncomment to enable */
|
||||
/* #define HAVE_BROKEN_RTC */
|
||||
/* #define HAVE_ISC_READER */
|
||||
/* #define HAVE_DBUS */
|
||||
|
||||
#if defined(HAVE_BROKEN_RTC) && defined(HAVE_ISC_READER)
|
||||
# error HAVE_ISC_READER is not compatible with HAVE_BROKEN_RTC
|
||||
@@ -203,11 +204,13 @@ NOTES:
|
||||
#define HAVE_DEV_URANDOM
|
||||
#define HAVE_DEV_RANDOM
|
||||
#undef HAVE_SOCKADDR_SA_LEN
|
||||
#if !defined(__UCLIBC_HAS_MMU__)
|
||||
#if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__)
|
||||
# define NO_FORK
|
||||
#endif
|
||||
#if !defined(__UCLIBC_HAS_IPV6__)
|
||||
# define NO_IPV6
|
||||
#if defined(__UCLIBC_HAS_IPV6__)
|
||||
# ifndef IPV6_V6ONLY
|
||||
# define IPV6_V6ONLY 26
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* This is for glibc 2.x */
|
||||
@@ -282,4 +285,3 @@ typedef unsigned long in_addr_t;
|
||||
# define ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -240,7 +240,7 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
check_servers(daemon);
|
||||
}
|
||||
else if (strcmp(method, "ClearCache") == 0)
|
||||
clear_cache_and_reload(daemon);
|
||||
clear_cache_and_reload(daemon, dnsmasq_time());
|
||||
else
|
||||
return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
|
||||
|
||||
@@ -260,7 +260,7 @@ char *dbus_init(struct daemon *daemon)
|
||||
dbus_error_init (&dbus_error);
|
||||
if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error)))
|
||||
return NULL;
|
||||
|
||||
|
||||
dbus_connection_set_exit_on_disconnect(connection, FALSE);
|
||||
dbus_connection_set_watch_functions(connection, add_watch, remove_watch,
|
||||
NULL, (void *)daemon, NULL);
|
||||
|
||||
24
src/dhcp.c
24
src/dhcp.c
@@ -25,14 +25,13 @@ void dhcp_init(struct daemon *daemon)
|
||||
{
|
||||
int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
struct sockaddr_in saddr;
|
||||
int flags, oneopt = 1;
|
||||
int oneopt = 1;
|
||||
struct dhcp_config *configs, *cp;
|
||||
|
||||
if (fd == -1)
|
||||
die (_("cannot create DHCP socket : %s"), NULL);
|
||||
|
||||
if ((flags = fcntl(fd, F_GETFL, 0)) == -1 ||
|
||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
|
||||
if (!fix_fd(fd) ||
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 ||
|
||||
#elif defined(IP_RECVIF)
|
||||
@@ -203,8 +202,9 @@ void dhcp_packet(struct daemon *daemon, time_t now)
|
||||
return;
|
||||
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);
|
||||
lease_update_file(daemon);
|
||||
lease_update_file(daemon, now);
|
||||
lease_update_dns(daemon);
|
||||
lease_collect(daemon);
|
||||
|
||||
if (iov.iov_len == 0)
|
||||
return;
|
||||
@@ -241,6 +241,7 @@ void dhcp_packet(struct daemon *daemon, time_t now)
|
||||
{
|
||||
/* broadcast to 255.255.255.255 */
|
||||
struct in_pktinfo *pkt;
|
||||
msg.msg_control = control_u.control;
|
||||
msg.msg_controllen = sizeof(control_u);
|
||||
cmptr = CMSG_FIRSTHDR(&msg);
|
||||
dest.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
@@ -257,9 +258,18 @@ void dhcp_packet(struct daemon *daemon, time_t now)
|
||||
/* unicast to unconfigured client */
|
||||
dest.sin_addr = mess->yiaddr;
|
||||
dest.sin_port = htons(DHCP_CLIENT_PORT);
|
||||
if (mess->hlen != 0 && mess->htype != 0)
|
||||
arp_inject(daemon->netlinkfd, mess->yiaddr, iface_index,
|
||||
mess->chaddr, mess->hlen);
|
||||
if (mess->hlen != 0 && mess->hlen <= 14 && mess->htype != 0)
|
||||
{
|
||||
/* 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
|
||||
|
||||
315
src/dnsmasq.c
315
src/dnsmasq.c
@@ -48,12 +48,13 @@ int main (int argc, char **argv)
|
||||
{
|
||||
struct daemon *daemon;
|
||||
int bind_fallback = 0;
|
||||
int bad_capabilities = 0;
|
||||
time_t now, last = 0;
|
||||
struct sigaction sigact;
|
||||
struct iname *if_tmp;
|
||||
int flags, piperead, pipefd[2];
|
||||
int piperead, pipefd[2];
|
||||
unsigned char sig;
|
||||
|
||||
|
||||
#ifndef NO_GETTEXT
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain("dnsmasq", LOCALEDIR);
|
||||
@@ -95,18 +96,19 @@ int main (int argc, char **argv)
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
netlink_init(daemon);
|
||||
#endif
|
||||
|
||||
daemon->interfaces = NULL;
|
||||
if (!enumerate_interfaces(daemon))
|
||||
die(_("failed to find list of interfaces: %s"), NULL);
|
||||
|
||||
if (!(daemon->options & OPT_NOWILD) &&
|
||||
!(daemon->listeners = create_wildcard_listeners(daemon->port)))
|
||||
#elif !(defined(IP_RECVDSTADDR) && \
|
||||
defined(IP_RECVIF) && \
|
||||
defined(IP_SENDSRCADDR))
|
||||
if (!(daemon->options & OPT_NOWILD))
|
||||
{
|
||||
bind_fallback = 1;
|
||||
daemon->options |= OPT_NOWILD;
|
||||
}
|
||||
#endif
|
||||
|
||||
daemon->interfaces = NULL;
|
||||
if (!enumerate_interfaces(daemon))
|
||||
die(_("failed to find list of interfaces: %s"), NULL);
|
||||
|
||||
if (daemon->options & OPT_NOWILD)
|
||||
{
|
||||
@@ -123,6 +125,8 @@ int main (int argc, char **argv)
|
||||
die(_("no interface with address %s"), daemon->namebuff);
|
||||
}
|
||||
}
|
||||
else if (!(daemon->listeners = create_wildcard_listeners(daemon->port)))
|
||||
die(_("failed to create listening socket: %s"), NULL);
|
||||
|
||||
forward_init(1);
|
||||
cache_init(daemon->cachesize, daemon->options & OPT_LOG);
|
||||
@@ -184,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 */
|
||||
if (pipe(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)
|
||||
if (pipe(pipefd) == -1 || !fix_fd(pipefd[0]) || !fix_fd(pipefd[1]))
|
||||
die(_("cannot create pipe: %s"), NULL);
|
||||
|
||||
piperead = pipefd[0];
|
||||
@@ -203,6 +203,7 @@ int main (int argc, char **argv)
|
||||
struct passwd *ent_pw = daemon->username ? getpwnam(daemon->username) : NULL;
|
||||
fd_set test_set;
|
||||
int maxfd, i;
|
||||
int nullfd = open("/dev/null", O_RDWR);
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
cap_user_header_t hdr = NULL;
|
||||
@@ -210,7 +211,7 @@ int main (int argc, char **argv)
|
||||
|
||||
/* On linux, we keep CAP_NETADMIN (for ARP-injection) and
|
||||
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));
|
||||
data = safe_malloc(sizeof(*data));
|
||||
@@ -222,7 +223,10 @@ int main (int argc, char **argv)
|
||||
|
||||
/* Tell kernel to not clear capabilities when dropping root */
|
||||
if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1) == -1)
|
||||
die(_("Cannot set capabilities: %s"), NULL);
|
||||
{
|
||||
bad_capabilities = errno;
|
||||
ent_pw = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -239,12 +243,12 @@ int main (int argc, char **argv)
|
||||
if (!(daemon->options & OPT_NO_FORK))
|
||||
{
|
||||
if (fork() != 0 )
|
||||
exit(0);
|
||||
_exit(0);
|
||||
|
||||
setsid();
|
||||
|
||||
if (fork() != 0)
|
||||
exit(0);
|
||||
_exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -282,25 +286,33 @@ int main (int argc, char **argv)
|
||||
if (i <= maxfd && FD_ISSET(i, &test_set))
|
||||
continue;
|
||||
|
||||
close(i);
|
||||
/* open stdout etc to /dev/null */
|
||||
if (i == STDOUT_FILENO || i == STDERR_FILENO || i == STDIN_FILENO)
|
||||
dup2(nullfd, i);
|
||||
else
|
||||
close(i);
|
||||
}
|
||||
|
||||
/* Change uid and gid for security */
|
||||
if (ent_pw)
|
||||
if (daemon->groupname || ent_pw)
|
||||
{
|
||||
gid_t dummy;
|
||||
struct group *gp;
|
||||
|
||||
/* remove all supplimentary groups */
|
||||
setgroups(0, &dummy);
|
||||
/* change group for /etc/ppp/resolv.conf
|
||||
otherwise get the group for "nobody" */
|
||||
|
||||
/* 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);
|
||||
(ent_pw && (gp = getgrgid(ent_pw->pw_gid))))
|
||||
{
|
||||
/* remove all supplimentary groups */
|
||||
setgroups(0, &dummy);
|
||||
setgid(gp->gr_gid);
|
||||
}
|
||||
}
|
||||
|
||||
if (ent_pw && ent_pw->pw_uid != 0)
|
||||
{
|
||||
/* finally drop root */
|
||||
setuid(ent_pw->pw_uid);
|
||||
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
data->effective = data->permitted =
|
||||
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
|
||||
@@ -362,12 +374,23 @@ int main (int argc, char **argv)
|
||||
}
|
||||
|
||||
if (!(daemon->options & OPT_DEBUG) && (getuid() == 0 || geteuid() == 0))
|
||||
syslog(LOG_WARNING, _("running as root"));
|
||||
{
|
||||
if (bad_capabilities)
|
||||
{
|
||||
errno = bad_capabilities;
|
||||
syslog(LOG_WARNING, _("warning: setting capabilities failed: %m"));
|
||||
}
|
||||
syslog(LOG_WARNING, _("running as root"));
|
||||
}
|
||||
|
||||
check_servers(daemon);
|
||||
|
||||
pid = getpid();
|
||||
|
||||
pid = getpid();
|
||||
|
||||
/* Start lease-change script */
|
||||
if (daemon->dhcp)
|
||||
lease_collect(daemon);
|
||||
|
||||
while (1)
|
||||
{
|
||||
int maxfd;
|
||||
@@ -472,11 +495,13 @@ int main (int argc, char **argv)
|
||||
|
||||
if (FD_ISSET(piperead, &rset))
|
||||
{
|
||||
pid_t p;
|
||||
|
||||
if (read(piperead, &sig, 1) == 1)
|
||||
switch (sig)
|
||||
{
|
||||
case SIGHUP:
|
||||
clear_cache_and_reload(daemon);
|
||||
clear_cache_and_reload(daemon, now);
|
||||
if (daemon->resolv_files && (daemon->options & OPT_NO_POLL))
|
||||
{
|
||||
reload_servers(daemon->resolv_files->name, daemon);
|
||||
@@ -490,24 +515,62 @@ int main (int argc, char **argv)
|
||||
|
||||
case SIGALRM:
|
||||
if (daemon->dhcp)
|
||||
lease_update_file(daemon);
|
||||
{
|
||||
lease_prune(NULL, now);
|
||||
lease_update_file(daemon, now);
|
||||
lease_collect(daemon);
|
||||
}
|
||||
break;
|
||||
|
||||
case SIGTERM:
|
||||
syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
|
||||
if (daemon->dhcp)
|
||||
fclose(daemon->lease_stream);
|
||||
exit(0);
|
||||
{
|
||||
int i;
|
||||
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->script_pid != 0)
|
||||
kill(daemon->script_pid, SIGQUIT);
|
||||
/* close this carefully */
|
||||
fclose(daemon->lease_stream);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
case SIGCHLD:
|
||||
/* See Stevens 5.10 */
|
||||
while (waitpid(-1, NULL, WNOHANG) > 0)
|
||||
daemon->num_kids--;
|
||||
/* 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--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
if (FD_ISSET(daemon->netlinkfd, &rset))
|
||||
netlink_multicast(daemon);
|
||||
@@ -515,7 +578,7 @@ int main (int argc, char **argv)
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
/* if we didn't create a DBus connection, retry now. */
|
||||
if ((daemon->options & OPT_DBUS) && !daemon->dbus)
|
||||
if ((daemon->options & OPT_DBUS) && !daemon->dbus)
|
||||
{
|
||||
char *err;
|
||||
if ((err = dbus_init(daemon)))
|
||||
@@ -553,12 +616,12 @@ static void sig_handler(int sig)
|
||||
{
|
||||
/* alarm is used to kill children after a fixed time. */
|
||||
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);
|
||||
if (daemon->dhcp)
|
||||
@@ -567,7 +630,7 @@ void clear_cache_and_reload(struct daemon *daemon)
|
||||
dhcp_read_ethers(daemon);
|
||||
dhcp_update_configs(daemon->dhcp_conf);
|
||||
lease_update_from_configs(daemon);
|
||||
lease_update_file(daemon);
|
||||
lease_update_file(daemon, now);
|
||||
lease_update_dns(daemon);
|
||||
}
|
||||
}
|
||||
@@ -614,95 +677,115 @@ static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t 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)
|
||||
if (confd == -1)
|
||||
continue;
|
||||
|
||||
if (daemon->options & OPT_NOWILD)
|
||||
iface = listener->iface;
|
||||
else
|
||||
{
|
||||
struct irec *iface = NULL;
|
||||
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. */
|
||||
|
||||
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 ((daemon->num_kids >= MAX_PROCS) || !iface)
|
||||
close(confd);
|
||||
/* 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 ((daemon->num_kids >= MAX_PROCS) || !iface)
|
||||
{
|
||||
shutdown(confd, SHUT_RDWR);
|
||||
close(confd);
|
||||
}
|
||||
#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++;
|
||||
close(confd);
|
||||
}
|
||||
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)
|
||||
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);
|
||||
|
||||
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);
|
||||
#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)
|
||||
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);
|
||||
|
||||
if (!(daemon->options & OPT_DEBUG))
|
||||
exit(0);
|
||||
|
||||
close(confd);
|
||||
if (buff)
|
||||
free(buff);
|
||||
for (s = daemon->servers; s; s = s->next)
|
||||
if (s->tcpfd != -1)
|
||||
close(s->tcpfd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int make_icmp_sock(void)
|
||||
{
|
||||
int fd, flags;
|
||||
int fd;
|
||||
int zeroopt = 0;
|
||||
|
||||
if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
|
||||
{
|
||||
if ((flags = fcntl(fd, F_GETFL, 0)) == -1 ||
|
||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
|
||||
if (!fix_fd(fd) ||
|
||||
setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
|
||||
{
|
||||
close(fd);
|
||||
|
||||
@@ -288,7 +288,9 @@ struct dhcp_lease {
|
||||
int clid_len; /* length of client identifier */
|
||||
unsigned char *clid; /* clientid */
|
||||
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 */
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
unsigned int length;
|
||||
@@ -411,6 +413,7 @@ struct daemon {
|
||||
char *username, *groupname;
|
||||
char *domain_suffix;
|
||||
char *runfile;
|
||||
char *lease_change_command;
|
||||
struct iname *if_names, *if_addrs, *if_except, *dhcp_except;
|
||||
struct bogus_addr *bogus_addr;
|
||||
struct server *servers;
|
||||
@@ -440,6 +443,7 @@ struct daemon {
|
||||
struct server *last_server;
|
||||
struct server *srv_save; /* Used for resend on DoD */
|
||||
size_t packet_len; /* " " */
|
||||
pid_t script_pid, tcp_pids[MAX_PROCS];
|
||||
int num_kids;
|
||||
|
||||
/* DHCP state */
|
||||
@@ -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,
|
||||
unsigned int mask);
|
||||
int expand_buf(struct iovec *iov, size_t size);
|
||||
char *print_mac(struct daemon *daemon, unsigned char *mac, int len);
|
||||
|
||||
/* option.c */
|
||||
struct daemon *read_opts (int argc, char **argv, char *compile_opts);
|
||||
|
||||
@@ -541,6 +547,7 @@ struct listener *create_wildcard_listeners(int port);
|
||||
struct listener *create_bound_listeners(struct daemon *daemon);
|
||||
int iface_check(struct daemon *daemon, int family,
|
||||
struct all_addr *addr, char *name);
|
||||
int fix_fd(int fd);
|
||||
|
||||
/* dhcp.c */
|
||||
void dhcp_init(struct daemon *daemon);
|
||||
@@ -564,12 +571,11 @@ char *strip_hostname(struct daemon *daemon, char *hostname);
|
||||
char *host_from_dns(struct daemon *daemon, struct in_addr addr);
|
||||
|
||||
/* 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_init(struct daemon *daemon, time_t now);
|
||||
struct dhcp_lease *lease_allocate(unsigned char *hwaddr, unsigned char *clid,
|
||||
int hw_len, int hw_type, int clid_len, struct in_addr addr);
|
||||
int lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
|
||||
struct dhcp_lease *lease_allocate(struct in_addr addr);
|
||||
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
|
||||
unsigned char *clid, int hw_len, int hw_type, int clid_len);
|
||||
void lease_set_hostname(struct dhcp_lease *lease, char *name,
|
||||
char *suffix, int auth);
|
||||
@@ -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);
|
||||
void lease_prune(struct dhcp_lease *target, time_t now);
|
||||
void lease_update_from_configs(struct daemon *daemon);
|
||||
void lease_collect(struct daemon *daemon);
|
||||
|
||||
/* 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);
|
||||
@@ -586,7 +593,7 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
/* dnsmasq.c */
|
||||
int make_icmp_sock(void);
|
||||
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 */
|
||||
#ifdef HAVE_ISC_READER
|
||||
@@ -599,8 +606,6 @@ void netlink_init(struct daemon *daemon);
|
||||
int iface_enumerate(struct daemon *daemon, void *parm,
|
||||
int (*ipv4_callback)(), int (*ipv6_callback)());
|
||||
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
|
||||
|
||||
/* bpf.c */
|
||||
|
||||
278
src/lease.c
278
src/lease.c
@@ -12,64 +12,54 @@
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
static struct dhcp_lease *leases;
|
||||
static struct dhcp_lease *leases, *old_leases;
|
||||
static int dns_dirty, file_dirty, leases_left;
|
||||
|
||||
void lease_init(struct daemon *daemon, time_t now)
|
||||
{
|
||||
unsigned int a0, a1, a2, a3;
|
||||
unsigned long ei;
|
||||
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
||||
struct in_addr addr;
|
||||
struct dhcp_lease *lease;
|
||||
int clid_len = 0, hw_len, hw_type;
|
||||
int flags, clid_len, hw_len, hw_type;
|
||||
|
||||
dns_dirty = 1;
|
||||
file_dirty = 0;
|
||||
leases = NULL;
|
||||
leases = old_leases = NULL;
|
||||
leases_left = daemon->dhcp_max;
|
||||
|
||||
/* NOTE: need a+ mode to create file if it doesn't exist */
|
||||
if (!(daemon->lease_stream = fopen(daemon->lease_file, "a+")))
|
||||
die(_("cannot open or create leases file: %s"), NULL);
|
||||
|
||||
|
||||
flags = fcntl(fileno(daemon->lease_stream), F_GETFD);
|
||||
if (flags != -1)
|
||||
fcntl(fileno(daemon->lease_stream), F_SETFD, flags | FD_CLOEXEC);
|
||||
|
||||
/* a+ mode lease pointer at end. */
|
||||
rewind(daemon->lease_stream);
|
||||
|
||||
/* client-id max length is 255 which is 255*2 digits + 254 colons
|
||||
borrow DNS packet buffer which is always larger than 1000 bytes */
|
||||
while (fscanf(daemon->lease_stream, "%lu %255s %d.%d.%d.%d %255s %764s",
|
||||
&ei, daemon->dhcp_buff2, &a0, &a1, &a2, &a3,
|
||||
daemon->dhcp_buff, daemon->packet) == 8)
|
||||
while (fscanf(daemon->lease_stream, "%lu %255s %16s %255s %764s",
|
||||
&ei, daemon->dhcp_buff2, daemon->namebuff,
|
||||
daemon->dhcp_buff, daemon->packet) == 5)
|
||||
{
|
||||
#ifndef HAVE_BROKEN_RTC
|
||||
/* strictly time_t is opaque, but this hack should work on all sane systems,
|
||||
even when sizeof(time_t) == 8 */
|
||||
time_t expires = (time_t)ei;
|
||||
|
||||
if (ei != 0 && difftime(now, expires) > 0)
|
||||
{
|
||||
file_dirty = 1;
|
||||
continue; /* expired */
|
||||
}
|
||||
#endif
|
||||
|
||||
hw_len = parse_hex(daemon->dhcp_buff2, hwaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
|
||||
/* For backwards compatibility, no explict MAC address type means ether. */
|
||||
if (hw_type == 0 && hw_len != 0)
|
||||
hw_type = ARPHRD_ETHER;
|
||||
|
||||
addr.s_addr = htonl((a0<<24) + (a1<<16) + (a2<<8) + a3);
|
||||
addr.s_addr = inet_addr(daemon->namebuff);
|
||||
|
||||
/* decode hex in place */
|
||||
if (strcmp(daemon->packet, "*") == 0)
|
||||
clid_len = 0;
|
||||
else
|
||||
clid_len = 0;
|
||||
if (strcmp(daemon->packet, "*") != 0)
|
||||
clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
|
||||
|
||||
if (!(lease = lease_allocate(hwaddr, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len, addr)))
|
||||
if (!(lease = lease_allocate(addr)))
|
||||
die (_("too many stored leases"), NULL);
|
||||
|
||||
/* not actually new */
|
||||
lease->new = 0;
|
||||
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
if (ei != 0)
|
||||
lease->expires = (time_t)ei + now;
|
||||
@@ -77,12 +67,21 @@ void lease_init(struct daemon *daemon, time_t now)
|
||||
lease->expires = (time_t)0;
|
||||
lease->length = ei;
|
||||
#else
|
||||
lease->expires = expires;
|
||||
/* strictly time_t is opaque, but this hack should work on all sane systems,
|
||||
even when sizeof(time_t) == 8 */
|
||||
lease->expires = (time_t)ei;
|
||||
#endif
|
||||
|
||||
lease_set_hwaddr(lease, hwaddr, (unsigned char *)daemon->packet, hw_len, hw_type, clid_len);
|
||||
|
||||
if (strcmp(daemon->dhcp_buff, "*") != 0)
|
||||
lease_set_hostname(lease, daemon->dhcp_buff, daemon->domain_suffix, 0);
|
||||
}
|
||||
|
||||
/* Some leases may have expired */
|
||||
file_dirty = 0;
|
||||
lease_prune(NULL, now);
|
||||
dns_dirty = 1;
|
||||
}
|
||||
|
||||
void lease_update_from_configs(struct daemon *daemon)
|
||||
@@ -103,67 +102,83 @@ void lease_update_from_configs(struct daemon *daemon)
|
||||
lease_set_hostname(lease, name, daemon->domain_suffix, 1); /* updates auth flag only */
|
||||
}
|
||||
|
||||
void lease_update_file(struct daemon *daemon)
|
||||
static void ourprintf(struct daemon *daemon, int *errp, char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
if (!(*errp) && vfprintf(daemon->lease_stream, format, ap) < 0)
|
||||
*errp = errno;
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void lease_update_file(struct daemon *daemon, time_t now)
|
||||
{
|
||||
struct dhcp_lease *lease;
|
||||
int i;
|
||||
|
||||
time_t next_event;
|
||||
int i, err = 0;
|
||||
|
||||
if (file_dirty != 0)
|
||||
{
|
||||
errno = 0;
|
||||
rewind(daemon->lease_stream);
|
||||
if (errno != 0 || ftruncate(fileno(daemon->lease_stream), 0) != 0)
|
||||
{
|
||||
write_err:
|
||||
syslog(LOG_ERR, _("failed to write %s: %m (retry in %ds)"), daemon->lease_file, LEASE_RETRY);
|
||||
alarm(LEASE_RETRY);
|
||||
return;
|
||||
}
|
||||
err = errno;
|
||||
|
||||
for (lease = leases; lease; lease = lease->next)
|
||||
{
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
if (fprintf(daemon->lease_stream, "%u ", lease->length) < 0)
|
||||
goto write_err;
|
||||
ourprintf(daemon, &err, "%u ", lease->length);
|
||||
#else
|
||||
if (fprintf(daemon->lease_stream, "%lu ", (unsigned long)lease->expires) < 0)
|
||||
goto write_err;
|
||||
ourprintf(daemon, &err, "%lu ", (unsigned long)lease->expires);
|
||||
#endif
|
||||
if ((lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0) &&
|
||||
fprintf(daemon->lease_stream, "%.2x-", lease->hwaddr_type) < 0)
|
||||
goto write_err;
|
||||
if (lease->hwaddr_type != ARPHRD_ETHER || lease->hwaddr_len == 0)
|
||||
ourprintf(daemon, &err, "%.2x-", lease->hwaddr_type);
|
||||
for (i = 0; i < lease->hwaddr_len; i++)
|
||||
{
|
||||
if (fprintf(daemon->lease_stream, "%.2x", lease->hwaddr[i]) < 0)
|
||||
goto write_err;
|
||||
if (i != lease->hwaddr_len - 1 &&
|
||||
fprintf(daemon->lease_stream, ":") < 0)
|
||||
goto write_err;
|
||||
ourprintf(daemon, &err, "%.2x", lease->hwaddr[i]);
|
||||
if (i != lease->hwaddr_len - 1)
|
||||
ourprintf(daemon, &err, ":");
|
||||
}
|
||||
if (fprintf(daemon->lease_stream, " %s %s ", inet_ntoa(lease->addr),
|
||||
lease->hostname && strlen(lease->hostname) != 0 ? lease->hostname : "*") < 0)
|
||||
goto write_err;
|
||||
ourprintf(daemon, &err, " %s %s ", inet_ntoa(lease->addr),
|
||||
lease->hostname && strlen(lease->hostname) != 0 ? lease->hostname : "*");
|
||||
|
||||
if (lease->clid && lease->clid_len != 0)
|
||||
{
|
||||
for (i = 0; i < lease->clid_len - 1; i++)
|
||||
if (fprintf(daemon->lease_stream, "%.2x:", lease->clid[i]) < 0)
|
||||
goto write_err;
|
||||
if (fprintf(daemon->lease_stream, "%.2x\n", lease->clid[i]) < 0)
|
||||
goto write_err;
|
||||
ourprintf(daemon, &err, "%.2x:", lease->clid[i]);
|
||||
ourprintf(daemon, &err, "%.2x\n", lease->clid[i]);
|
||||
}
|
||||
else
|
||||
if (fprintf(daemon->lease_stream, "*\n") < 0)
|
||||
goto write_err;
|
||||
|
||||
ourprintf(daemon, &err, "*\n");
|
||||
}
|
||||
|
||||
if (fflush(daemon->lease_stream) != 0)
|
||||
goto write_err;
|
||||
if (fsync(fileno(daemon->lease_stream)) < 0)
|
||||
goto write_err;
|
||||
file_dirty = 0;
|
||||
|
||||
if (fflush(daemon->lease_stream) != 0 ||
|
||||
fsync(fileno(daemon->lease_stream)) < 0)
|
||||
err = errno;
|
||||
|
||||
if (!err)
|
||||
file_dirty = 0;
|
||||
}
|
||||
|
||||
/* Set alarm for when the first lease expires + slop. */
|
||||
for (next_event = 0, lease = leases; lease; lease = lease->next)
|
||||
if (lease->expires != 0 &&
|
||||
(next_event == 0 || difftime(next_event, lease->expires + 10) > 0.0))
|
||||
next_event = lease->expires + 10;
|
||||
|
||||
if (err)
|
||||
{
|
||||
if (next_event == 0 || difftime(next_event, LEASE_RETRY + now) > 0.0)
|
||||
next_event = LEASE_RETRY + now;
|
||||
|
||||
syslog(LOG_ERR, _("failed to write %s: %s (retry in %us)"),
|
||||
daemon->lease_file, strerror(err),
|
||||
(unsigned int)difftime(next_event, now));
|
||||
}
|
||||
|
||||
if (next_event != 0)
|
||||
alarm((unsigned)difftime(next_event, now));
|
||||
}
|
||||
|
||||
void lease_update_dns(struct daemon *daemon)
|
||||
@@ -194,18 +209,16 @@ void lease_prune(struct dhcp_lease *target, time_t now)
|
||||
if ((lease->expires != 0 && difftime(now, lease->expires) > 0) || lease == target)
|
||||
{
|
||||
file_dirty = 1;
|
||||
|
||||
*up = lease->next; /* unlink */
|
||||
if (lease->hostname)
|
||||
{
|
||||
free(lease->hostname);
|
||||
dns_dirty = 1;
|
||||
}
|
||||
if (lease->fqdn)
|
||||
free(lease->fqdn);
|
||||
if (lease->clid)
|
||||
free(lease->clid);
|
||||
free(lease);
|
||||
dns_dirty = 1;
|
||||
|
||||
*up = lease->next; /* unlink */
|
||||
|
||||
/* Put on old_leases list 'till we
|
||||
can run the script */
|
||||
lease->next = old_leases;
|
||||
old_leases = lease;
|
||||
|
||||
leases_left++;
|
||||
}
|
||||
else
|
||||
@@ -248,30 +261,20 @@ struct dhcp_lease *lease_find_by_addr(struct in_addr addr)
|
||||
}
|
||||
|
||||
|
||||
struct dhcp_lease *lease_allocate(unsigned char *hwaddr, unsigned char *clid,
|
||||
int hw_len, int hw_type, int clid_len, struct in_addr addr)
|
||||
struct dhcp_lease *lease_allocate(struct in_addr addr)
|
||||
{
|
||||
struct dhcp_lease *lease;
|
||||
if (!leases_left || !(lease = malloc(sizeof(struct dhcp_lease))))
|
||||
return NULL;
|
||||
|
||||
lease->clid = NULL;
|
||||
lease->hostname = lease->fqdn = NULL;
|
||||
memset(lease, 0, sizeof(struct dhcp_lease));
|
||||
lease->new = 1;
|
||||
lease->addr = addr;
|
||||
memset(lease->hwaddr, 0, DHCP_CHADDR_MAX);
|
||||
lease->hwaddr_len = 0;
|
||||
lease->hwaddr_type = 0;
|
||||
lease->hwaddr_len = 225; /* illegal value */
|
||||
lease->expires = 1;
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
lease->length = 0xffffffff; /* illegal value */
|
||||
#endif
|
||||
|
||||
if (!lease_set_hwaddr(lease, hwaddr, clid, hw_len, hw_type, clid_len))
|
||||
{
|
||||
free(lease);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lease->next = leases;
|
||||
leases = lease;
|
||||
|
||||
@@ -309,22 +312,18 @@ void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now)
|
||||
#endif
|
||||
}
|
||||
|
||||
int lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
|
||||
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
|
||||
unsigned char *clid, int hw_len, int hw_type, int clid_len)
|
||||
{
|
||||
/* must have some sort of unique-id */
|
||||
if (hw_len == 0 && (clid_len == 0 || !clid))
|
||||
return 0;
|
||||
|
||||
if (hw_len != lease->hwaddr_len ||
|
||||
hw_type != lease->hwaddr_type ||
|
||||
hw_len == 0 ||
|
||||
memcmp(lease->hwaddr, hwaddr, hw_len) != 0)
|
||||
(hw_len != 0 && memcmp(lease->hwaddr, hwaddr, hw_len) != 0))
|
||||
{
|
||||
file_dirty = 1;
|
||||
memcpy(lease->hwaddr, hwaddr, hw_len);
|
||||
lease->hwaddr_len = hw_len;
|
||||
lease->hwaddr_type = hw_type;
|
||||
lease->old = 1; /* run script on change */
|
||||
}
|
||||
|
||||
/* only update clid when one is available, stops packets
|
||||
@@ -341,7 +340,7 @@ int lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
|
||||
if (lease->clid)
|
||||
free(lease->clid);
|
||||
if (!(lease->clid = malloc(clid_len)))
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
else if (memcmp(lease->clid, clid, clid_len) != 0)
|
||||
file_dirty = 1;
|
||||
@@ -349,8 +348,6 @@ int lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
|
||||
lease->clid_len = clid_len;
|
||||
memcpy(lease->clid, clid, clid_len);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix, int auth)
|
||||
@@ -363,7 +360,7 @@ void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix, int
|
||||
lease->auth_name = auth;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!name && !lease->hostname)
|
||||
return;
|
||||
|
||||
@@ -379,6 +376,7 @@ void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix, int
|
||||
{
|
||||
if (lease_tmp->auth_name && !auth)
|
||||
return;
|
||||
lease_tmp->old = 1; /* call script on change */
|
||||
new_name = lease_tmp->hostname;
|
||||
lease_tmp->hostname = NULL;
|
||||
if (lease_tmp->fqdn)
|
||||
@@ -410,8 +408,82 @@ void lease_set_hostname(struct dhcp_lease *lease, char *name, char *suffix, int
|
||||
lease->auth_name = auth;
|
||||
|
||||
file_dirty = 1;
|
||||
dns_dirty = 1;
|
||||
dns_dirty = 1;
|
||||
lease->old = 1; /* run script on change */
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_FORK
|
||||
static pid_t run_script(struct daemon *daemon, char *action, struct dhcp_lease *lease)
|
||||
{
|
||||
if (daemon->lease_change_command)
|
||||
{
|
||||
char *mac = print_mac(daemon, lease->hwaddr, lease->hwaddr_len);
|
||||
char *addr = inet_ntoa(lease->addr);
|
||||
char *com = strrchr(daemon->lease_change_command, '/');
|
||||
pid_t pid = fork();
|
||||
|
||||
if (pid == -1)
|
||||
return 0; /* fork error */
|
||||
else if (pid != 0)
|
||||
return pid;
|
||||
|
||||
execl(daemon->lease_change_command,
|
||||
com ? com+1 : daemon->lease_change_command,
|
||||
action, mac, addr, lease->hostname, (char*)NULL);
|
||||
|
||||
/* log socket should still be open, right? */
|
||||
syslog(LOG_ERR, _("failed to execute %s: %m"),
|
||||
daemon->lease_change_command);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* deleted leases get transferred to the old_leases list.
|
||||
remove them here, after calling the lease change
|
||||
script. Also run the lease change script on new leases */
|
||||
void lease_collect(struct daemon *daemon)
|
||||
{
|
||||
struct dhcp_lease *lease;
|
||||
|
||||
while (old_leases)
|
||||
{
|
||||
if (daemon->script_pid != 0)
|
||||
return; /* busy */
|
||||
|
||||
lease = old_leases;
|
||||
old_leases = lease->next;
|
||||
|
||||
#ifndef NO_FORK
|
||||
daemon->script_pid = run_script(daemon, "del", lease);
|
||||
#endif
|
||||
|
||||
if (lease->hostname)
|
||||
free(lease->hostname);
|
||||
if (lease->fqdn)
|
||||
free(lease->fqdn);
|
||||
if (lease->clid)
|
||||
free(lease->clid);
|
||||
free(lease);
|
||||
}
|
||||
|
||||
for (lease = leases; lease; lease = lease->next)
|
||||
if (lease->new || lease->old)
|
||||
{
|
||||
if (daemon->script_pid != 0)
|
||||
return; /* busy */
|
||||
|
||||
#ifndef NO_FORK
|
||||
daemon->script_pid = run_script(daemon, lease->new ? "add" : "old", lease);
|
||||
#endif
|
||||
|
||||
lease->new = lease->old = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -36,10 +36,26 @@ void netlink_init(struct daemon *daemon)
|
||||
addr.nl_groups = RTMGRP_IPV4_ROUTE;
|
||||
#endif
|
||||
|
||||
if ((daemon->netlinkfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1 ||
|
||||
bind(daemon->netlinkfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
|
||||
die(_("cannot create RTnetlink socket: %s"), NULL);
|
||||
/* May not be able to have permission to set multicast groups don't die in that case */
|
||||
if ((daemon->netlinkfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) != -1)
|
||||
{
|
||||
if (bind(daemon->netlinkfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
|
||||
{
|
||||
addr.nl_groups = 0;
|
||||
if (errno != EPERM || bind(daemon->netlinkfd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
|
||||
daemon->netlinkfd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (daemon->netlinkfd == -1)
|
||||
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_base = safe_malloc(iov.iov_len);
|
||||
}
|
||||
@@ -104,7 +120,7 @@ int iface_enumerate(struct daemon *daemon, void *parm, int (*ipv4_callback)(), i
|
||||
again:
|
||||
req.nlh.nlmsg_len = sizeof(req);
|
||||
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_seq = ++seq;
|
||||
req.g.rtgen_family = family;
|
||||
@@ -205,7 +221,7 @@ static void nl_err(struct nlmsghdr *h)
|
||||
{
|
||||
struct nlmsgerr *err = NLMSG_DATA(h);
|
||||
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.
|
||||
@@ -224,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());
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
120
src/network.c
120
src/network.c
@@ -15,43 +15,39 @@
|
||||
int iface_check(struct daemon *daemon, int family, struct all_addr *addr, char *name)
|
||||
{
|
||||
struct iname *tmp;
|
||||
int ret = 1;
|
||||
|
||||
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||
return 0;
|
||||
/* Note: have to check all and not bail out early, so that we set the
|
||||
"used" flags. */
|
||||
|
||||
if (daemon->if_names || daemon->if_addrs)
|
||||
{
|
||||
ret = 0;
|
||||
|
||||
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
|
||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||
{
|
||||
tmp->used = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = tmp->used = 1;
|
||||
|
||||
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
||||
if (tmp->addr.sa.sa_family == family)
|
||||
{
|
||||
if (family == AF_INET &&
|
||||
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
|
||||
{
|
||||
tmp->used = 1;
|
||||
return 1;
|
||||
}
|
||||
ret = tmp->used = 1;
|
||||
#ifdef HAVE_IPV6
|
||||
else if (family == AF_INET6 &&
|
||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
|
||||
&addr->addr.addr6))
|
||||
{
|
||||
tmp->used = 1;
|
||||
return 1;
|
||||
}
|
||||
ret = tmp->used = 1;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && (strcmp(tmp->name, name) == 0))
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iface_allowed(struct daemon *daemon, struct irec **irecp, int if_index,
|
||||
@@ -184,13 +180,25 @@ int enumerate_interfaces(struct daemon *daemon)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(HAVE_IPV6) && \
|
||||
(defined(HAVE_LINUX_NETWORK) || \
|
||||
(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR)))
|
||||
/* 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)
|
||||
static int create_ipv6_listener(struct listener **link, int port)
|
||||
{
|
||||
union mysockaddr addr;
|
||||
int tcpfd, fd, flags, save;
|
||||
int tcpfd, fd;
|
||||
struct listener *l;
|
||||
int opt = 1;
|
||||
|
||||
@@ -210,21 +218,14 @@ static int create_ipv6_listener(struct listener **link, int port)
|
||||
errno == EINVAL);
|
||||
|
||||
if ((tcpfd = socket(AF_INET6, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
save = errno;
|
||||
close(fd);
|
||||
errno = save;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
if (setsockopt(fd, 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(tcpfd, IPV6_LEVEL, IPV6_V6ONLY, &opt, sizeof(opt)) == -1 ||
|
||||
(flags = fcntl(fd, F_GETFL, 0)) == -1 ||
|
||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
|
||||
(flags = fcntl(tcpfd, F_GETFL, 0)) == -1 ||
|
||||
fcntl(tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
|
||||
!fix_fd(fd) ||
|
||||
!fix_fd(tcpfd) ||
|
||||
#ifdef IPV6_RECVPKTINFO
|
||||
setsockopt(fd, IPV6_LEVEL, IPV6_RECVPKTINFO, &opt, sizeof(opt)) == -1 ||
|
||||
#else
|
||||
@@ -233,14 +234,8 @@ static int create_ipv6_listener(struct listener **link, int port)
|
||||
bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
|
||||
listen(tcpfd, 5) == -1 ||
|
||||
bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
|
||||
{
|
||||
save = errno;
|
||||
close(fd);
|
||||
close(tcpfd);
|
||||
errno = save;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
l = safe_malloc(sizeof(struct listener));
|
||||
l->fd = fd;
|
||||
l->tcpfd = tcpfd;
|
||||
@@ -254,14 +249,9 @@ static int create_ipv6_listener(struct listener **link, int port)
|
||||
|
||||
struct listener *create_wildcard_listeners(int port)
|
||||
{
|
||||
#if !(defined(HAVE_LINUX_NETWORK) || (defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR)))
|
||||
port = 0; /* eliminate warning */
|
||||
return NULL;
|
||||
#else
|
||||
union mysockaddr addr;
|
||||
int opt = 1;
|
||||
struct listener *l, *l6 = NULL;
|
||||
int flags;
|
||||
int tcpfd, fd;
|
||||
|
||||
addr.in.sin_family = AF_INET;
|
||||
@@ -271,26 +261,19 @@ struct listener *create_wildcard_listeners(int port)
|
||||
addr.in.sin_len = sizeof(struct sockaddr_in);
|
||||
#endif
|
||||
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ||
|
||||
(tcpfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
return NULL;
|
||||
|
||||
if ((tcpfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
close (fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (setsockopt(tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
|
||||
bind(tcpfd, (struct sockaddr *)&addr, sa_len(&addr)) == -1 ||
|
||||
listen(tcpfd, 5) == -1 ||
|
||||
(flags = fcntl(tcpfd, F_GETFL, 0)) == -1 ||
|
||||
fcntl(tcpfd, F_SETFL, flags | O_NONBLOCK) == -1 ||
|
||||
!fix_fd(tcpfd) ||
|
||||
#ifdef HAVE_IPV6
|
||||
!create_ipv6_listener(&l6, port) ||
|
||||
#endif
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
|
||||
(flags = fcntl(fd, F_GETFL, 0)) == -1 ||
|
||||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1 ||
|
||||
!fix_fd(fd) ||
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
setsockopt(fd, SOL_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1 ||
|
||||
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
|
||||
@@ -298,12 +281,8 @@ struct listener *create_wildcard_listeners(int port)
|
||||
setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1 ||
|
||||
#endif
|
||||
bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == -1)
|
||||
{
|
||||
close(fd);
|
||||
close(tcpfd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
l = safe_malloc(sizeof(struct listener));
|
||||
l->family = AF_INET;
|
||||
l->fd = fd;
|
||||
@@ -311,8 +290,6 @@ struct listener *create_wildcard_listeners(int port)
|
||||
l->next = l6;
|
||||
|
||||
return l;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
struct listener *create_bound_listeners(struct daemon *daemon)
|
||||
@@ -320,7 +297,7 @@ struct listener *create_bound_listeners(struct daemon *daemon)
|
||||
|
||||
struct listener *listeners = NULL;
|
||||
struct irec *iface;
|
||||
int flags, opt = 1;
|
||||
int opt = 1;
|
||||
|
||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||
{
|
||||
@@ -332,11 +309,8 @@ struct listener *create_bound_listeners(struct daemon *daemon)
|
||||
(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->tcpfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
|
||||
/* See Stevens 16.6 */
|
||||
(flags = fcntl(new->tcpfd, F_GETFL, 0)) == -1 ||
|
||||
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)
|
||||
!fix_fd(new->tcpfd) ||
|
||||
!fix_fd(new->fd))
|
||||
die(_("failed to create listening socket: %s"), NULL);
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
@@ -380,7 +354,6 @@ struct listener *create_bound_listeners(struct daemon *daemon)
|
||||
struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds)
|
||||
{
|
||||
struct serverfd *sfd;
|
||||
int flags;
|
||||
|
||||
/* may have a suitable one already */
|
||||
for (sfd = *sfds; sfd; sfd = sfd->next )
|
||||
@@ -399,8 +372,7 @@ struct serverfd *allocate_sfd(union mysockaddr *addr, struct serverfd **sfds)
|
||||
}
|
||||
|
||||
if (bind(sfd->fd, (struct sockaddr *)addr, sa_len(addr)) == -1 ||
|
||||
(flags = fcntl(sfd->fd, F_GETFL, 0)) == -1 ||
|
||||
fcntl(sfd->fd, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
!fix_fd(sfd->fd))
|
||||
{
|
||||
int errsave = errno; /* save error from bind. */
|
||||
close(sfd->fd);
|
||||
|
||||
17
src/option.c
17
src/option.c
@@ -19,7 +19,7 @@ struct myoption {
|
||||
int val;
|
||||
};
|
||||
|
||||
#define OPTSTRING "531yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:"
|
||||
#define OPTSTRING "531yZDNLERKzowefnbvhdkqr:m:p:c:l:s:i:t:u:g:a:x:S:C:A:T:H:Q:I:B:F:G:O:M:X:V:U:j:P:J:W:Y:2:4:6:"
|
||||
|
||||
static const struct myoption opts[] = {
|
||||
{"version", 0, 0, 'v'},
|
||||
@@ -82,6 +82,7 @@ static const struct myoption opts[] = {
|
||||
{"bootp-dynamic", 0, 0, '3'},
|
||||
{"dhcp-mac", 1, 0, '4'},
|
||||
{"no-ping", 0, 0, '5'},
|
||||
{"dhcp-script", 1, 0, '6'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
@@ -180,6 +181,7 @@ static const struct {
|
||||
{ "-3, --bootp-dynamic", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
|
||||
{ "-4, --dhcp-mac=<id>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
|
||||
{ "-5, --no-ping", gettext_noop("Disable ICMP echo address checking in the DHCP server."), NULL },
|
||||
{ "-6, --dhcp-script=path", gettext_noop("Script to run on DHCP lease creation and destruction."), NULL },
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@@ -609,6 +611,15 @@ struct daemon *read_opts (int argc, char **argv, char *compile_opts)
|
||||
case 'l':
|
||||
daemon->lease_file = safe_string_alloc(arg);
|
||||
break;
|
||||
|
||||
case '6':
|
||||
#ifdef NO_FORK
|
||||
problem = _("cannot run scripts under uClinux");
|
||||
option = '?';
|
||||
#else
|
||||
daemon->lease_change_command = safe_string_alloc(arg);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'H':
|
||||
{
|
||||
@@ -648,8 +659,6 @@ struct daemon *read_opts (int argc, char **argv, char *compile_opts)
|
||||
"interface=" to disable all interfaces except loop. */
|
||||
new->name = safe_string_alloc(arg);
|
||||
new->isloop = new->used = 0;
|
||||
if (safe_strchr(new->name, ':'))
|
||||
daemon->options |= OPT_NOWILD;
|
||||
arg = comma;
|
||||
} while (arg);
|
||||
break;
|
||||
@@ -665,8 +674,6 @@ struct daemon *read_opts (int argc, char **argv, char *compile_opts)
|
||||
{
|
||||
new->next = daemon->if_except;
|
||||
daemon->if_except = new;
|
||||
if (safe_strchr(new->name, ':'))
|
||||
daemon->options |= OPT_NOWILD;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -32,7 +32,7 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
|
||||
unsigned int label_type = l & 0xc0;
|
||||
if (label_type == 0xc0) /* pointer */
|
||||
{
|
||||
if (p - (unsigned char *)header + 1u >= plen)
|
||||
if ((size_t)(p - (unsigned char *)header + 1) >= plen)
|
||||
return 0;
|
||||
|
||||
/* get offset */
|
||||
@@ -70,7 +70,7 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
|
||||
/* output is \[x<hex>/siz]. which is digs+9 chars */
|
||||
if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME)
|
||||
return 0;
|
||||
if (p - (unsigned char *)header + ((count-1)>>3) + 1u >= plen)
|
||||
if ((size_t)(p - (unsigned char *)header + ((count-1)>>3) + 1) >= plen)
|
||||
return 0;
|
||||
|
||||
*cp++ = '\\';
|
||||
@@ -94,7 +94,7 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
|
||||
{ /* label_type = 0 -> label. */
|
||||
if (cp - (unsigned char *)name + l + 1 >= MAXDNAME)
|
||||
return 0;
|
||||
if (p - (unsigned char *)header + 1u >= plen)
|
||||
if ((size_t)(p - (unsigned char *)header + 1) >= plen)
|
||||
return 0;
|
||||
for(j=0; j<l; j++, p++)
|
||||
if (isExtract)
|
||||
@@ -134,7 +134,11 @@ static int extract_name(HEADER *header, size_t plen, unsigned char **pp,
|
||||
}
|
||||
|
||||
if (isExtract)
|
||||
*--cp = 0; /* terminate: lose final period */
|
||||
{
|
||||
if (cp != (unsigned char *)name)
|
||||
cp--;
|
||||
*cp = 0; /* terminate: lose final period */
|
||||
}
|
||||
else if (*cp != 0)
|
||||
retvalue = 2;
|
||||
|
||||
|
||||
@@ -72,7 +72,6 @@ static void bootp_option_put(struct dhcp_packet *mess,
|
||||
struct dhcp_boot *boot_opts, struct dhcp_netid *netids);
|
||||
static struct in_addr option_addr(unsigned char *opt);
|
||||
static unsigned int option_uint(unsigned char *opt, int size);
|
||||
static char *print_mac(struct daemon *daemon, unsigned char *mac, int len);
|
||||
static void log_packet(struct daemon *daemon, char *type, struct in_addr *addr,
|
||||
struct dhcp_packet *mess, char *interface, char *string);
|
||||
static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
|
||||
@@ -329,7 +328,9 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
mess->yiaddr = lease->addr;
|
||||
}
|
||||
|
||||
if (!message && !lease && (!(lease = lease_allocate(mess->chaddr, NULL, mess->hlen, mess->htype, 0, mess->yiaddr))))
|
||||
if (!message &&
|
||||
!lease &&
|
||||
(!(lease = lease_allocate(mess->yiaddr))))
|
||||
message = _("no leases left");
|
||||
|
||||
if (!message && !(context = narrow_context(context, mess->yiaddr)))
|
||||
@@ -730,7 +731,11 @@ size_t dhcp_reply(struct daemon *daemon, struct dhcp_context *context, char *ifa
|
||||
else if ((ltmp = lease_find_by_addr(mess->yiaddr)) && ltmp != lease)
|
||||
message = _("address in use");
|
||||
|
||||
else if (!lease && !(lease = lease_allocate(mess->chaddr, clid, mess->hlen, mess->htype, clid_len, mess->yiaddr)))
|
||||
else if (!clid && mess->hlen == 0)
|
||||
message = _("no unique-id");
|
||||
|
||||
else if (!lease &&
|
||||
!(lease = lease_allocate(mess->yiaddr)))
|
||||
message = _("no leases left");
|
||||
}
|
||||
|
||||
@@ -855,25 +860,10 @@ static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *
|
||||
return time;
|
||||
}
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
|
||||
static void log_packet(struct daemon *daemon, char *type, struct in_addr *addr,
|
||||
struct dhcp_packet *mess, char *interface, char *string)
|
||||
{
|
||||
syslog(LOG_INFO, "%s%s(%s) %s%s%s%s",
|
||||
syslog(LOG_INFO, "%s%s(%s) %s%s%s %s",
|
||||
type ? "DHCP" : "BOOTP",
|
||||
type ? type : "",
|
||||
interface,
|
||||
|
||||
14
src/util.c
14
src/util.c
@@ -396,3 +396,17 @@ int expand_buf(struct iovec *iov, size_t size)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user