Compare commits
17 Commits
v2.71test2
...
v2.72test3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6799a46605 | ||
|
|
c4638f9e66 | ||
|
|
4b34f5d22f | ||
|
|
a0358e5ddb | ||
|
|
a03f8d4c37 | ||
|
|
c4a0937683 | ||
|
|
2f4c4b6076 | ||
|
|
a008a843cf | ||
|
|
d92c53e700 | ||
|
|
a754e1d7b2 | ||
|
|
8e9ffba66e | ||
|
|
15a97ad6fb | ||
|
|
91f4a5e4b5 | ||
|
|
0fa7e62947 | ||
|
|
62f992f06c | ||
|
|
a23949d44d | ||
|
|
7ea3d3fdca |
14
CHANGELOG
14
CHANGELOG
@@ -1,3 +1,17 @@
|
||||
version 2.72
|
||||
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
|
||||
|
||||
Add support for "ipsets" in *BSD, using pf. Thanks to
|
||||
Sven Falempim for the patch.
|
||||
|
||||
Fix race condition which could lock up dnsmasq when an
|
||||
interface goes down and up rapidly. Thanks to Conrad
|
||||
Kostecki for helping to chase this down.
|
||||
|
||||
Add DBus methods SetFilterWin2KOption and SetBogusPrivOption
|
||||
Thanks to the Smoothwall project for the patch.
|
||||
|
||||
|
||||
version 2.71
|
||||
Subtle change to error handling to help DNSSEC validation
|
||||
when servers fail to provide NODATA answers for
|
||||
|
||||
2
Makefile
2
Makefile
@@ -69,7 +69,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
||||
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
|
||||
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
|
||||
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
|
||||
domain.o dnssec.o blockdata.o
|
||||
domain.o dnssec.o blockdata.o tables.c
|
||||
|
||||
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
||||
dns-protocol.h radv-protocol.h ip6addr.h
|
||||
|
||||
@@ -9,7 +9,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
|
||||
rfc2131.c tftp.c util.c conntrack.c \
|
||||
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
||||
radv.c slaac.c auth.c ipset.c domain.c \
|
||||
dnssec.c dnssec-openssl.c blockdata.c
|
||||
dnssec.c dnssec-openssl.c blockdata.c tables.c
|
||||
|
||||
LOCAL_MODULE := dnsmasq
|
||||
|
||||
|
||||
@@ -40,6 +40,14 @@ ClearCache
|
||||
Returns nothing. Clears the domain name cache and re-reads
|
||||
/etc/hosts. The same as sending dnsmasq a HUP signal.
|
||||
|
||||
SetFilterWin2KOption
|
||||
--------------------
|
||||
Takes boolean, sets or resets the --filterwin2k option.
|
||||
|
||||
SetBogusPrivOption
|
||||
------------------
|
||||
Takes boolean, sets or resets the --bogus-priv option.
|
||||
|
||||
SetServers
|
||||
----------
|
||||
Returns nothing. Takes a set of arguments representing the new
|
||||
|
||||
26
debian/changelog
vendored
26
debian/changelog
vendored
@@ -1,3 +1,29 @@
|
||||
dnsmasq (2.72-1) unstable; urgency=low
|
||||
|
||||
* New upstream.
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 20 May 2014 21:01:11 +0000
|
||||
|
||||
dnsmasq (2.71-1) unstable; urgency=low
|
||||
|
||||
* New upstream.
|
||||
* Fix 100% CPU-usage bug when dnsmasq started with cachesize
|
||||
set to zero. (LP: #1314697)
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 16 May 2014 20:17:10 +0000
|
||||
|
||||
dnsmasq (2.70-3) unstable; urgency=medium
|
||||
|
||||
* Write a pid-file, even when being started using systemd, since
|
||||
other components may wish to signal dnsmasq.
|
||||
* Enable dnsmasq systemd unit on install. Otherwise dnsmasq does not run on
|
||||
fresh installations (without administrator handholding) and even worse it
|
||||
is disabled on systems switching from sysv to systemd. Modify
|
||||
postinst/postrm exactly as dh_systemd would, add dependency on
|
||||
init-system-helpers. Closes: #724602
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 11 May 2014 17:45:21 +0000
|
||||
|
||||
dnsmasq (2.70-2) unstable; urgency=low
|
||||
|
||||
* Ensure daemon not stared if dnsmasq package has been removed,
|
||||
|
||||
6
debian/control
vendored
6
debian/control
vendored
@@ -2,13 +2,15 @@ Source: dnsmasq
|
||||
Section: net
|
||||
Priority: optional
|
||||
Build-depends: gettext, libnetfilter-conntrack-dev [linux-any],
|
||||
libidn11-dev, libdbus-1-dev (>=0.61), libgmp-dev, nettle-dev (>=2.4-3)
|
||||
libidn11-dev, libdbus-1-dev (>=0.61), libgmp-dev,
|
||||
nettle-dev (>=2.4-3)
|
||||
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Standards-Version: 3.9.3
|
||||
|
||||
Package: dnsmasq
|
||||
Architecture: all
|
||||
Depends: netbase, dnsmasq-base(>= ${binary:Version})
|
||||
Depends: netbase, dnsmasq-base(>= ${binary:Version}),
|
||||
init-system-helpers (>= 1.18~)
|
||||
Suggests: resolvconf
|
||||
Conflicts: resolvconf (<<1.15)
|
||||
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||
|
||||
10
debian/init
vendored
10
debian/init
vendored
@@ -277,9 +277,15 @@ case "$1" in
|
||||
stop_resolvconf
|
||||
;;
|
||||
systemd-exec)
|
||||
# --pid-file without argument disables writing a PIDfile, we don't need one with sytemd.
|
||||
# /var/run may be volatile, so we need to ensure that
|
||||
# /var/run/dnsmasq exists here as well as in postinst
|
||||
if [ ! -d /var/run/dnsmasq ]; then
|
||||
mkdir /var/run/dnsmasq || return 2
|
||||
chown dnsmasq:nogroup /var/run/dnsmasq || return 2
|
||||
fi
|
||||
# Enable DBus by default because we use DBus activation with systemd.
|
||||
exec $DAEMON --keep-in-foreground --pid-file --enable-dbus \
|
||||
exec $DAEMON --keep-in-foreground --enable-dbus \
|
||||
-x /var/run/dnsmasq/$NAME.pid \
|
||||
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
|
||||
${MAILTARGET:+ -t $MAILTARGET} \
|
||||
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \
|
||||
|
||||
16
debian/postinst
vendored
16
debian/postinst
vendored
@@ -1,6 +1,22 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Code copied from dh_systemd_enable ----------------------
|
||||
# This will only remove masks created by d-s-h on package removal.
|
||||
deb-systemd-helper unmask dnsmasq.service >/dev/null || true
|
||||
|
||||
# was-enabled defaults to true, so new installations run enable.
|
||||
if deb-systemd-helper --quiet was-enabled dnsmasq.service; then
|
||||
# Enables the unit on first installation, creates new
|
||||
# symlinks on upgrades if the unit file has changed.
|
||||
deb-systemd-helper enable dnsmasq.service >/dev/null || true
|
||||
else
|
||||
# Update the statefile to add new symlinks (if any), which need to be
|
||||
# cleaned up on purge. Also remove old symlinks.
|
||||
deb-systemd-helper update-state dnsmasq.service >/dev/null || true
|
||||
fi
|
||||
# End code copied from dh_systemd_enable ------------------
|
||||
|
||||
if [ -x /etc/init.d/dnsmasq ]; then
|
||||
update-rc.d dnsmasq defaults 15 85 >/dev/null
|
||||
|
||||
|
||||
16
debian/postrm
vendored
16
debian/postrm
vendored
@@ -4,3 +4,19 @@ set -e
|
||||
if [ purge = "$1" ]; then
|
||||
update-rc.d dnsmasq remove >/dev/null
|
||||
fi
|
||||
|
||||
# Code copied from dh_systemd_enable ----------------------
|
||||
if [ "$1" = "remove" ]; then
|
||||
if [ -x "/usr/bin/deb-systemd-helper" ]; then
|
||||
deb-systemd-helper mask dnsmasq.service >/dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$1" = "purge" ]; then
|
||||
if [ -x "/usr/bin/deb-systemd-helper" ]; then
|
||||
deb-systemd-helper purge dnsmasq.service >/dev/null
|
||||
deb-systemd-helper unmask dnsmasq.service >/dev/null
|
||||
fi
|
||||
fi
|
||||
# End code copied from dh_systemd_enable ------------------
|
||||
|
||||
|
||||
12
debian/rules
vendored
12
debian/rules
vendored
@@ -11,18 +11,16 @@
|
||||
|
||||
package=dnsmasq-base
|
||||
|
||||
CFLAGS = $(shell export DEB_BUILD_OPTIONS=$(DEB_BUILD_OPTIONS); dpkg-buildflags --get CFLAGS)
|
||||
CFLAGS += $(shell dpkg-buildflags --get CPPFLAGS)
|
||||
dpkg_buildflags := DEB_BUILD_MAINT_OPTIONS="hardening=+all" dpkg-buildflags
|
||||
|
||||
CFLAGS = $(shell $(dpkg_buildflags) --get CFLAGS)
|
||||
CFLAGS += $(shell $(dpkg_buildflags) --get CPPFLAGS)
|
||||
CFLAGS += -Wall -W
|
||||
|
||||
LDFLAGS = $(shell dpkg-buildflags --get LDFLAGS)
|
||||
LDFLAGS = $(shell $(dpkg_buildflags) --get LDFLAGS)
|
||||
|
||||
DEB_COPTS = $(COPTS)
|
||||
|
||||
# The nettle library in Debian is too old to include
|
||||
# ECC support.
|
||||
DEB_COPTS += -DNO_NETTLE_ECC
|
||||
|
||||
TARGET = install-i18n
|
||||
|
||||
DEB_BUILD_ARCH_OS := $(shell dpkg-architecture -qDEB_BUILD_ARCH_OS)
|
||||
|
||||
5
debian/systemd.service
vendored
5
debian/systemd.service
vendored
@@ -13,9 +13,8 @@ ExecStartPre=/usr/sbin/dnsmasq --test
|
||||
# itself, when called with the "systemd-exec" function.
|
||||
#
|
||||
# It also adds the command-line flags
|
||||
# --keep-in-foreground --pid-file --enable-dbus
|
||||
# to disable writing a pid-file (not needed with systemd) and
|
||||
# enable DBus by default because we use DBus activation.
|
||||
# --keep-in-foreground --enable-dbus
|
||||
# to enable DBus by default because we use DBus activation.
|
||||
#
|
||||
ExecStart=/etc/init.d/dnsmasq systemd-exec
|
||||
|
||||
|
||||
@@ -794,7 +794,7 @@ and
|
||||
for details.)
|
||||
|
||||
For IPv6, the mode may be some combination of
|
||||
.B ra-only, slaac, ra-names, ra-stateless.
|
||||
.B ra-only, slaac, ra-names, ra-stateless, ra-advrouter.
|
||||
|
||||
.B ra-only
|
||||
tells dnsmasq to offer Router Advertisement only on this subnet,
|
||||
@@ -829,6 +829,11 @@ can be combined with
|
||||
and
|
||||
.B slaac.
|
||||
|
||||
.B ra-advrouter
|
||||
enables a mode where router address(es) rather than prefix(es) are included in the advertisements.
|
||||
This is described in RFC-3775 section 7.2 and is used in mobile IPv6. In this mode the interval option
|
||||
is also included, as described in RFC-3775 section 7.3.
|
||||
|
||||
.TP
|
||||
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
||||
Specify per host parameters for the DHCP server. This allows a machine
|
||||
|
||||
@@ -376,7 +376,7 @@ void route_init(void)
|
||||
die(_("cannot create PF_ROUTE socket: %s"), NULL, EC_BADNET);
|
||||
}
|
||||
|
||||
void route_sock(time_t now)
|
||||
void route_sock(void)
|
||||
{
|
||||
struct if_msghdr *msg;
|
||||
int rc = recv(daemon->routefd, daemon->packet, daemon->packet_buff_sz, 0);
|
||||
@@ -401,7 +401,7 @@ void route_sock(time_t now)
|
||||
else if (msg->ifm_type == RTM_NEWADDR)
|
||||
{
|
||||
del_family = 0;
|
||||
newaddress(now);
|
||||
send_newaddr();
|
||||
}
|
||||
else if (msg->ifm_type == RTM_DELADDR)
|
||||
{
|
||||
@@ -439,7 +439,7 @@ void route_sock(time_t now)
|
||||
of += sizeof(long) - (diff & (sizeof(long) - 1));
|
||||
}
|
||||
|
||||
newaddress(now);
|
||||
send_newaddr();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -330,7 +330,7 @@ HAVE_SOCKADDR_SA_LEN
|
||||
#undef HAVE_AUTH
|
||||
#endif
|
||||
|
||||
#if defined(NO_IPSET) || !defined(HAVE_LINUX_NETWORK)
|
||||
#if defined(NO_IPSET)
|
||||
#undef HAVE_IPSET
|
||||
#endif
|
||||
|
||||
|
||||
38
src/dbus.c
38
src/dbus.c
@@ -44,6 +44,12 @@ const char* introspection_xml_template =
|
||||
" <method name=\"SetServersEx\">\n"
|
||||
" <arg name=\"servers\" direction=\"in\" type=\"aas\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetFilterWin2KOption\">\n"
|
||||
" <arg name=\"filterwin2k\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetBogusPrivOption\">\n"
|
||||
" <arg name=\"boguspriv\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <signal name=\"DhcpLeaseAdded\">\n"
|
||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||
@@ -372,6 +378,30 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
||||
return error;
|
||||
}
|
||||
|
||||
static DBusMessage *dbus_set_bool(DBusMessage *message, int flag, char *name)
|
||||
{
|
||||
DBusMessageIter iter;
|
||||
dbus_bool_t enabled;
|
||||
|
||||
if (!dbus_message_iter_init(message, &iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "Expected boolean argument");
|
||||
|
||||
dbus_message_iter_get_basic(&iter, &enabled);
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
my_syslog(LOG_INFO, "Enabling --%s option from D-Bus", name);
|
||||
set_option_bool(flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
my_syslog(LOG_INFO, "Disabling --$s option from D-Bus", name);
|
||||
reset_option_bool(flag);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *user_data)
|
||||
@@ -415,6 +445,14 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
reply = dbus_read_servers_ex(message, 1);
|
||||
new_servers = 1;
|
||||
}
|
||||
else if (strcmp(method, "SetFilterWin2KOption") == 0)
|
||||
{
|
||||
reply = dbus_set_bool(message, OPT_FILTER, "filterwin2k");
|
||||
}
|
||||
else if (strcmp(method, "SetBogusPrivOption") == 0)
|
||||
{
|
||||
reply = dbus_set_bool(message, OPT_BOGUSPRIV, "bogus-priv");
|
||||
}
|
||||
else if (strcmp(method, "ClearCache") == 0)
|
||||
clear_cache = 1;
|
||||
else
|
||||
|
||||
@@ -404,7 +404,8 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
|
||||
/* interface name already copied in */
|
||||
arp_req.arp_flags = ATF_COM;
|
||||
ioctl(daemon->dhcpfd, SIOCSARP, &arp_req);
|
||||
if (ioctl(daemon->dhcpfd, SIOCSARP, &arp_req) == -1)
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("ARP-cache injection failed: %s"), strerror(errno));
|
||||
}
|
||||
#elif defined(HAVE_SOLARIS_NETWORK)
|
||||
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
|
||||
|
||||
@@ -727,8 +727,7 @@ void dhcp_construct_contexts(time_t now)
|
||||
|
||||
if (context->flags & CONTEXT_GC && !(context->flags & CONTEXT_OLD))
|
||||
{
|
||||
if ((context->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)) ||
|
||||
option_bool(OPT_RA))
|
||||
if ((context->flags & CONTEXT_RA) || option_bool(OPT_RA))
|
||||
{
|
||||
/* previously constructed context has gone. advertise it's demise */
|
||||
context->flags |= CONTEXT_OLD;
|
||||
|
||||
@@ -917,10 +917,10 @@ int main (int argc, char **argv)
|
||||
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
if (FD_ISSET(daemon->netlinkfd, &rset))
|
||||
netlink_multicast(now);
|
||||
netlink_multicast();
|
||||
#elif defined(HAVE_BSD_NETWORK)
|
||||
if (FD_ISSET(daemon->routefd, &rset))
|
||||
route_sock(now);
|
||||
route_sock();
|
||||
#endif
|
||||
|
||||
/* Check for changes to resolv files once per second max. */
|
||||
@@ -1037,6 +1037,11 @@ void send_alarm(time_t event, time_t now)
|
||||
}
|
||||
}
|
||||
|
||||
void send_newaddr(void)
|
||||
{
|
||||
send_event(pipewrite, EVENT_NEWADDR, 0, NULL);
|
||||
}
|
||||
|
||||
void send_event(int fd, int event, int data, char *msg)
|
||||
{
|
||||
struct event_desc ev;
|
||||
@@ -1230,6 +1235,10 @@ static void async_event(int pipe, time_t now)
|
||||
if (daemon->log_file != NULL)
|
||||
log_reopen(daemon->log_file);
|
||||
break;
|
||||
|
||||
case EVENT_NEWADDR:
|
||||
newaddress(now);
|
||||
break;
|
||||
|
||||
case EVENT_TERM:
|
||||
/* Knock all our children on the head. */
|
||||
|
||||
@@ -165,6 +165,7 @@ struct event_desc {
|
||||
#define EVENT_LUA_ERR 19
|
||||
#define EVENT_TFTP_ERR 20
|
||||
#define EVENT_INIT 21
|
||||
#define EVENT_NEWADDR 22
|
||||
|
||||
/* Exit codes. */
|
||||
#define EC_GOOD 0
|
||||
@@ -823,7 +824,7 @@ struct dhcp_context {
|
||||
#define CONTEXT_NETMASK (1u<<1)
|
||||
#define CONTEXT_BRDCAST (1u<<2)
|
||||
#define CONTEXT_PROXY (1u<<3)
|
||||
#define CONTEXT_RA_ONLY (1u<<4)
|
||||
#define CONTEXT_RA_ROUTER (1u<<4)
|
||||
#define CONTEXT_RA_DONE (1u<<5)
|
||||
#define CONTEXT_RA_NAME (1u<<6)
|
||||
#define CONTEXT_RA_STATELESS (1u<<7)
|
||||
@@ -838,7 +839,6 @@ struct dhcp_context {
|
||||
#define CONTEXT_OLD (1u<<16)
|
||||
#define CONTEXT_V6 (1u<<17)
|
||||
|
||||
|
||||
struct ping_result {
|
||||
struct in_addr addr;
|
||||
time_t time;
|
||||
@@ -1289,6 +1289,7 @@ unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
||||
int make_icmp_sock(void);
|
||||
int icmp_ping(struct in_addr addr);
|
||||
#endif
|
||||
void send_newaddr(void);
|
||||
void send_alarm(time_t event, time_t now);
|
||||
void send_event(int fd, int event, int data, char *msg);
|
||||
void clear_cache_and_reload(time_t now);
|
||||
@@ -1297,7 +1298,7 @@ void poll_resolv(int force, int do_reload, time_t now);
|
||||
/* netlink.c */
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
void netlink_init(void);
|
||||
void netlink_multicast(time_t now);
|
||||
void netlink_multicast(void);
|
||||
#endif
|
||||
|
||||
/* bpf.c */
|
||||
@@ -1306,7 +1307,7 @@ void init_bpf(void);
|
||||
void send_via_bpf(struct dhcp_packet *mess, size_t len,
|
||||
struct in_addr iface_addr, struct ifreq *ifr);
|
||||
void route_init(void);
|
||||
void route_sock(time_t now);
|
||||
void route_sock(void);
|
||||
#endif
|
||||
|
||||
/* bpf.c or netlink.c */
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_IPSET
|
||||
#if defined(HAVE_IPSET) && defined(HAVE_LINUX_NETWORK)
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
static struct iovec iov;
|
||||
static u32 netlink_pid;
|
||||
|
||||
static int nl_async(struct nlmsghdr *h);
|
||||
static void nl_async(struct nlmsghdr *h);
|
||||
|
||||
void netlink_init(void)
|
||||
{
|
||||
@@ -142,7 +142,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
struct nlmsghdr *h;
|
||||
ssize_t len;
|
||||
static unsigned int seq = 0;
|
||||
int callback_ok = 1, newaddr = 0;
|
||||
int callback_ok = 1;
|
||||
|
||||
struct {
|
||||
struct nlmsghdr nlh;
|
||||
@@ -191,21 +191,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
|
||||
{
|
||||
/* May be multicast arriving async */
|
||||
if (nl_async(h))
|
||||
{
|
||||
newaddr = 1;
|
||||
enumerate_interfaces(1); /* reset */
|
||||
}
|
||||
nl_async(h);
|
||||
}
|
||||
else if (h->nlmsg_type == NLMSG_DONE)
|
||||
{
|
||||
/* handle async new interface address arrivals, these have to be done
|
||||
after we complete as we're not re-entrant */
|
||||
if (newaddr)
|
||||
newaddress(dnsmasq_time());
|
||||
|
||||
return callback_ok;
|
||||
}
|
||||
return callback_ok;
|
||||
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
|
||||
{
|
||||
struct ifaddrmsg *ifa = NLMSG_DATA(h);
|
||||
@@ -330,11 +319,11 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
}
|
||||
}
|
||||
|
||||
void netlink_multicast(time_t now)
|
||||
void netlink_multicast(void)
|
||||
{
|
||||
ssize_t len;
|
||||
struct nlmsghdr *h;
|
||||
int flags, newaddr = 0;
|
||||
int flags;
|
||||
|
||||
/* don't risk blocking reading netlink messages here. */
|
||||
if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 ||
|
||||
@@ -343,24 +332,19 @@ void netlink_multicast(time_t now)
|
||||
|
||||
if ((len = netlink_recv()) != -1)
|
||||
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
||||
if (nl_async(h))
|
||||
newaddr = 1;
|
||||
nl_async(h);
|
||||
|
||||
/* restore non-blocking status */
|
||||
fcntl(daemon->netlinkfd, F_SETFL, flags);
|
||||
|
||||
if (newaddr)
|
||||
newaddress(now);
|
||||
}
|
||||
|
||||
static int nl_async(struct nlmsghdr *h)
|
||||
static void nl_async(struct nlmsghdr *h)
|
||||
{
|
||||
if (h->nlmsg_type == NLMSG_ERROR)
|
||||
{
|
||||
struct nlmsgerr *err = NLMSG_DATA(h);
|
||||
if (err->error != 0)
|
||||
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
|
||||
return 0;
|
||||
}
|
||||
else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
|
||||
{
|
||||
@@ -385,18 +369,15 @@ static int nl_async(struct nlmsghdr *h)
|
||||
else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
|
||||
fd = daemon->rfd_save->fd;
|
||||
else
|
||||
return 0;
|
||||
return;
|
||||
|
||||
while(sendto(fd, daemon->packet, daemon->packet_len, 0,
|
||||
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
||||
return 1; /* clever bind mode - rescan */
|
||||
|
||||
return 0;
|
||||
send_newaddr();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -551,7 +551,7 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
|
||||
int enumerate_interfaces(int reset)
|
||||
{
|
||||
static struct addrlist *spare = NULL;
|
||||
static int done = 0, active = 0;
|
||||
static int done = 0;
|
||||
struct iface_param param;
|
||||
int errsave, ret = 1;
|
||||
struct addrlist *addr, *tmp;
|
||||
@@ -570,14 +570,11 @@ int enumerate_interfaces(int reset)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (done || active)
|
||||
if (done)
|
||||
return 1;
|
||||
|
||||
done = 1;
|
||||
|
||||
/* protect against recusive calls from iface_enumerate(); */
|
||||
active = 1;
|
||||
|
||||
if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
return 0;
|
||||
|
||||
@@ -677,10 +674,8 @@ int enumerate_interfaces(int reset)
|
||||
}
|
||||
|
||||
errno = errsave;
|
||||
|
||||
spare = param.spare;
|
||||
active = 0;
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -2583,9 +2583,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
if (strcmp(a[leasepos], "static") == 0)
|
||||
new->flags |= CONTEXT_STATIC | CONTEXT_DHCP;
|
||||
else if (strcmp(a[leasepos], "ra-only") == 0 || strcmp(a[leasepos], "slaac") == 0 )
|
||||
new->flags |= CONTEXT_RA_ONLY | CONTEXT_RA;
|
||||
new->flags |= CONTEXT_RA;
|
||||
else if (strcmp(a[leasepos], "ra-names") == 0)
|
||||
new->flags |= CONTEXT_RA_NAME | CONTEXT_RA;
|
||||
else if (strcmp(a[leasepos], "ra-advrouter") == 0)
|
||||
new->flags |= CONTEXT_RA_ROUTER | CONTEXT_RA;
|
||||
else if (strcmp(a[leasepos], "ra-stateless") == 0)
|
||||
new->flags |= CONTEXT_RA_STATELESS | CONTEXT_DHCP | CONTEXT_RA;
|
||||
else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
|
||||
@@ -2615,7 +2617,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
|
||||
if (new->prefix != 64)
|
||||
{
|
||||
if ((new->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
|
||||
if (new->flags & CONTEXT_RA)
|
||||
ret_err(_("prefix length must be exactly 64 for RA subnets"));
|
||||
else if (new->flags & CONTEXT_TEMPLATE)
|
||||
ret_err(_("prefix length must be exactly 64 for subnet constructors"));
|
||||
|
||||
@@ -49,6 +49,7 @@ struct prefix_opt {
|
||||
#define ICMP6_OPT_SOURCE_MAC 1
|
||||
#define ICMP6_OPT_PREFIX 3
|
||||
#define ICMP6_OPT_MTU 5
|
||||
#define ICMP6_OPT_ADV_INTERVAL 7
|
||||
#define ICMP6_OPT_RDNSS 25
|
||||
#define ICMP6_OPT_DNSSL 31
|
||||
|
||||
|
||||
44
src/radv.c
44
src/radv.c
@@ -28,7 +28,7 @@
|
||||
|
||||
struct ra_param {
|
||||
time_t now;
|
||||
int ind, managed, other, found_context, first;
|
||||
int ind, managed, other, found_context, first, adv_router;
|
||||
char *if_name;
|
||||
struct dhcp_netid *tags;
|
||||
struct in6_addr link_local, link_global, ula;
|
||||
@@ -226,6 +226,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
||||
parm.managed = 0;
|
||||
parm.other = 0;
|
||||
parm.found_context = 0;
|
||||
parm.adv_router = 0;
|
||||
parm.if_name = iface_name;
|
||||
parm.first = 1;
|
||||
parm.now = now;
|
||||
@@ -286,8 +287,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
||||
setaddr6part(&local, addr6part(&local) & ~((context->prefix == 64) ? (u64)-1LL : (1LLU << (128 - context->prefix)) - 1LLU));
|
||||
|
||||
|
||||
if ((context->flags &
|
||||
(CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
|
||||
if (context->flags & CONTEXT_RA)
|
||||
{
|
||||
do_slaac = 1;
|
||||
if (context->flags & CONTEXT_DHCP)
|
||||
@@ -339,6 +339,17 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
||||
if (!old_prefix && !parm.found_context)
|
||||
return;
|
||||
|
||||
/* If we're sending router address instead of prefix in at least on prefix,
|
||||
include the advertisement interval option. */
|
||||
if (parm.adv_router)
|
||||
{
|
||||
put_opt6_char(ICMP6_OPT_ADV_INTERVAL);
|
||||
put_opt6_char(1);
|
||||
put_opt6_short(0);
|
||||
/* interval value is in milliseconds */
|
||||
put_opt6_long(1000 * calc_interval(find_iface_param(iface_name)));
|
||||
}
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
/* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU
|
||||
available from SIOCGIFMTU */
|
||||
@@ -500,6 +511,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
int do_slaac = 0;
|
||||
int deprecate = 0;
|
||||
int constructed = 0;
|
||||
int adv_router = 0;
|
||||
unsigned int time = 0xffffffff;
|
||||
struct dhcp_context *context;
|
||||
|
||||
@@ -511,8 +523,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
{
|
||||
context->saved_valid = valid;
|
||||
|
||||
if ((context->flags &
|
||||
(CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
|
||||
if (context->flags & CONTEXT_RA)
|
||||
{
|
||||
do_slaac = 1;
|
||||
if (context->flags & CONTEXT_DHCP)
|
||||
@@ -530,7 +541,17 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
param->managed = 1;
|
||||
param->other = 1;
|
||||
}
|
||||
|
||||
|
||||
/* Configured to advertise router address, not prefix. See RFC 3775 7.2
|
||||
In this case we do all addresses associated with a context,
|
||||
hence the real_prefix setting here. */
|
||||
if (context->flags & CONTEXT_RA_ROUTER)
|
||||
{
|
||||
adv_router = 1;
|
||||
param->adv_router = 1;
|
||||
real_prefix = context->prefix;
|
||||
}
|
||||
|
||||
/* find floor time, don't reduce below 3 * RA interval. */
|
||||
if (time > context->lease_time)
|
||||
{
|
||||
@@ -556,7 +577,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
/* subsequent prefixes on the same interface
|
||||
and subsequent instances of this prefix don't need timers.
|
||||
Be careful not to find the same prefix twice with different
|
||||
addresses. */
|
||||
addresses unless we're advertising the actual addresses. */
|
||||
if (!(context->flags & CONTEXT_RA_DONE))
|
||||
{
|
||||
if (!param->first)
|
||||
@@ -607,13 +628,18 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
if ((opt = expand(sizeof(struct prefix_opt))))
|
||||
{
|
||||
/* zero net part of address */
|
||||
setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU));
|
||||
if (!adv_router)
|
||||
setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU));
|
||||
|
||||
opt->type = ICMP6_OPT_PREFIX;
|
||||
opt->len = 4;
|
||||
opt->prefix_len = real_prefix;
|
||||
/* autonomous only if we're not doing dhcp, always set "on-link" */
|
||||
opt->flags = do_slaac ? 0xC0 : 0x80;
|
||||
opt->flags = 0x80;
|
||||
if (do_slaac)
|
||||
opt->flags |= 0x40;
|
||||
if (adv_router)
|
||||
opt->flags |= 0x20;
|
||||
opt->valid_lifetime = htonl(valid);
|
||||
opt->preferred_lifetime = htonl(preferred);
|
||||
opt->reserved = 0;
|
||||
|
||||
169
src/tables.c
Normal file
169
src/tables.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/* tables.c is Copyright (c) 2014 Sven Falempin All Rights Reserved.
|
||||
|
||||
Author's email: sfalempin@citypassenger.com
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/pfvar.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
static char *pf_device = "/dev/pf";
|
||||
static int dev = -1;
|
||||
|
||||
static char *pfr_strerror(int errnum)
|
||||
{
|
||||
switch (errnum)
|
||||
{
|
||||
case ESRCH:
|
||||
return "Table does not exist";
|
||||
case ENOENT:
|
||||
return "Anchor or Ruleset does not exist";
|
||||
default:
|
||||
return strerror(errnum);
|
||||
}
|
||||
}
|
||||
|
||||
static int pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (size < 0 || (size && tbl == NULL))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_buffer = tbl;
|
||||
io.pfrio_esize = sizeof(*tbl);
|
||||
io.pfrio_size = size;
|
||||
if (ioctl(dev, DIOCRADDTABLES, &io))
|
||||
return (-1);
|
||||
if (nadd != NULL)
|
||||
*nadd = io.pfrio_nadd;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int fill_addr(const struct all_addr *ipaddr, int flags, struct pfr_addr* addr) {
|
||||
if ( !addr || !ipaddr)
|
||||
{
|
||||
my_syslog(LOG_ERR, _("error: fill_addr missused"));
|
||||
return -1;
|
||||
}
|
||||
bzero(addr, sizeof(*addr));
|
||||
#ifdef HAVE_IPV6
|
||||
if (flags & F_IPV6)
|
||||
{
|
||||
addr->pfra_af = AF_INET6;
|
||||
addr->pfra_net = 0x80;
|
||||
memcpy(&(addr->pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
addr->pfra_af = AF_INET;
|
||||
addr->pfra_net = 0x20;
|
||||
addr->pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ipset_init(void)
|
||||
{
|
||||
dev = open( pf_device, O_RDWR);
|
||||
if (dev == -1)
|
||||
{
|
||||
err(1, "%s", pf_device);
|
||||
die (_("failed to access pf devices: %s"), NULL, EC_MISC);
|
||||
}
|
||||
}
|
||||
|
||||
int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
||||
int flags, int remove)
|
||||
{
|
||||
struct pfr_addr addr;
|
||||
struct pfioc_table io;
|
||||
struct pfr_table table;
|
||||
int n = 0, rc = 0;
|
||||
|
||||
if ( dev == -1 )
|
||||
{
|
||||
my_syslog(LOG_ERR, _("warning: no opened pf devices %s"), pf_device);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bzero(&table, sizeof(struct pfr_table));
|
||||
table.pfrt_flags |= PFR_TFLAG_PERSIST;
|
||||
if ( strlen(setname) >= PF_TABLE_NAME_SIZE )
|
||||
{
|
||||
my_syslog(LOG_ERR, _("error: cannot use table name %s"), setname);
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( strlcpy(table.pfrt_name, setname,
|
||||
sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name))
|
||||
{
|
||||
my_syslog(LOG_ERR, _("error: cannot strlcpy table name %s"), setname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rc = pfr_add_tables(&table, 1, &n, 0))
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("warning: pfr_add_tables: %s(%d)"),
|
||||
pfr_strerror(errno),rc);
|
||||
return -1;
|
||||
}
|
||||
table.pfrt_flags &= ~PFR_TFLAG_PERSIST;
|
||||
if (n)
|
||||
my_syslog(LOG_INFO, _("info: table created"));
|
||||
|
||||
fill_addr(ipaddr,flags,&addr);
|
||||
bzero(&io, sizeof(io));
|
||||
io.pfrio_flags = 0;
|
||||
io.pfrio_table = table;
|
||||
io.pfrio_buffer = &addr;
|
||||
io.pfrio_esize = sizeof(addr);
|
||||
io.pfrio_size = 1;
|
||||
if (ioctl(dev, ( remove ? DIOCRDELADDRS : DIOCRADDADDRS ), &io))
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("warning: DIOCR%sADDRS: %s"), ( remove ? "DEL" : "ADD" ), pfr_strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
my_syslog(LOG_INFO, _("%d addresses %s"),
|
||||
io.pfrio_nadd, ( remove ? "removed" : "added" ));
|
||||
|
||||
return io.pfrio_nadd;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user