Compare commits

...
9 Commits
9 changed files with 134 additions and 25 deletions

No files matched your search

+14 -1
View File
@@ -32,6 +32,19 @@ version 2.64
infinte loop at startup. Regression in 2.63. Thanks to
Haim Gelfenbeyn for spotting this.
Set SO_REUSEADDRESS and SO_V6ONLY options on the DHCPv6
socket, this allows multiple instances of dnsmasq on a
single machine, in the same way as for DHCPv4. Thanks to
Gene Czarcinski and Vladislav Grishenko for work on this.
Fix DHCPv6 to do access control correctly when it's
configured with --listen-address. Thanks to
Gene Czarcinski for sorting this out.
Add a "wildcard" dhcp-range which works for any IPv6
subnet, --dhcp-range=::,static Useful for Stateless
DHCPv6. Thanks to Vladislav Grishenko for the patch.
version 2.63
Do duplicate dhcp-host address check in --test mode.
@@ -394,7 +407,7 @@ version 2.58
Fix regression in TFTP server on *BSD platforms introduced
in version 2.56, due to confusion with sockaddr
length. Many thanks to Loïc Pefferkorn for finding this.
length. Many thanks to Loic Pefferkorn for finding this.
Support scope-ids in IPv6 addresses of nameservers from
/etc/resolv.conf and in --server options. Eg
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/python
import dbus
bus = dbus.SystemBus()
p = bus.get_object("uk.org.thekelleys.dnsmasq", "/uk/org/thekelleys/dnsmasq")
l = dbus.Interface(p, dbus_interface="uk.org.thekelleys.dnsmasq")
# The new more flexible SetServersEx method
array = dbus.Array()
array.append(["1.2.3.5"])
array.append(["1.2.3.4#664", "foobar.com"])
array.append(["1003:1234:abcd::1%eth0", "eng.mycorp.com", "lab.mycorp.com"])
print l.SetServersEx(array)
# Must create a new object for dnsmasq as the introspection gives the wrong
# signature for SetServers (av) while the code only expects a bunch of arguments
# instead of an array of variants
p = bus.get_object("uk.org.thekelleys.dnsmasq", "/uk/org/thekelleys/dnsmasq", introspect=False)
l = dbus.Interface(p, dbus_interface="uk.org.thekelleys.dnsmasq")
# The previous method; all addresses in machine byte order
print l.SetServers(dbus.UInt32(16909060), # 1.2.3.5
dbus.UInt32(16909061), # 1.2.3.4
"foobar.com",
dbus.Byte(0x10), # 1003:1234:abcd::1
dbus.Byte(0x03),
dbus.Byte(0x12),
dbus.Byte(0x34),
dbus.Byte(0xab),
dbus.Byte(0xcd),
dbus.Byte(0x00),
dbus.Byte(0x00),
dbus.Byte(0x00),
dbus.Byte(0x00),
dbus.Byte(0x00),
dbus.Byte(0x00),
dbus.Byte(0x00),
dbus.Byte(0x00),
dbus.Byte(0x00),
dbus.Byte(0x01),
"eng.mycorp.com",
"lab.mycorp.com")
+2 -2
View File
@@ -480,7 +480,7 @@
#tftp-no-blocksize
# Set the boot file name only when the "red" tag is set.
#dhcp-boot=net:red,pxelinux.red-net
#dhcp-boot=tag:red,pxelinux.red-net
# An example of dhcp-boot with an external TFTP server: the name and IP
# address of the server are given after the filename.
@@ -621,6 +621,6 @@
# Log lots of extra information about DHCP transactions.
#log-dhcp
# Include a another lot of configuration options.
# Include another lot of configuration options.
#conf-file=/etc/dnsmasq.more.conf
#conf-dir=/etc/dnsmasq.d
+1 -1
View File
@@ -364,7 +364,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message)
}
/* parse the IP address */
addr_err = parse_server(str_addr, &addr, &source_addr, &interface, NULL);
addr_err = parse_server(str_addr, &addr, &source_addr, (char *) &interface, NULL);
free(str_addr);
if (addr_err)
+58 -16
View File
@@ -21,7 +21,7 @@
struct iface_param {
struct dhcp_context *current;
struct in6_addr fallback;
int ind;
int ind, addr_match;
};
static int complete_context6(struct in6_addr *local, int prefix,
@@ -36,15 +36,31 @@ void dhcp6_init(void)
#if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
int class = IPTOS_CLASS_CS6;
#endif
int oneopt = 1;
if ((fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1 ||
#if defined(IPV6_TCLASS) && defined(IPTOS_CLASS_CS6)
setsockopt(fd, IPPROTO_IPV6, IPV6_TCLASS, &class, sizeof(class)) == -1 ||
#endif
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &oneopt, sizeof(oneopt)) == -1 ||
!fix_fd(fd) ||
!set_ipv6pktinfo(fd))
die (_("cannot create DHCPv6 socket: %s"), NULL, EC_BADNET);
/* When bind-interfaces is set, there might be more than one dnmsasq
instance binding port 547. That's OK if they serve different networks.
Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. */
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
{
#ifdef SO_REUSEPORT
int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt));
#else
int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
#endif
if (rc == -1)
die(_("failed to set SO_REUSE{ADDR|PORT} on DHCPv6 socket: %s"), NULL, EC_BADNET);
}
memset(&saddr, 0, sizeof(saddr));
#ifdef HAVE_SOCKADDR_SA_LEN
saddr.sin6_len = sizeof(struct sockaddr_in6);
@@ -71,7 +87,6 @@ void dhcp6_packet(time_t now)
char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
} control_u;
struct sockaddr_in6 from;
struct all_addr dest;
ssize_t sz;
struct ifreq ifr;
struct iname *tmp;
@@ -98,33 +113,52 @@ void dhcp6_packet(time_t now)
p.c = CMSG_DATA(cmptr);
if_index = p.p->ipi6_ifindex;
dest.addr.addr6 = p.p->ipi6_addr;
}
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
return;
if (!iface_check(AF_INET6, (struct all_addr *)&dest, ifr.ifr_name))
return;
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
return;
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
return;
/* unlinked contexts are marked by context->current == context */
for (context = daemon->dhcp6; context; context = context->next)
{
context->current = context;
memset(&context->local6, 0, IN6ADDRSZ);
}
parm.current = NULL;
parm.ind = if_index;
parm.addr_match = 0;
memset(&parm.fallback, 0, IN6ADDRSZ);
for (context = daemon->dhcp6; context; context = context->next)
if (IN6_IS_ADDR_UNSPECIFIED(&context->start6) && context->prefix == 0)
{
/* wildcard context for DHCP-stateless only */
parm.current = context;
context->current = NULL;
}
else
{
/* unlinked contexts are marked by context->current == context */
context->current = context;
memset(&context->local6, 0, IN6ADDRSZ);
}
if (!iface_enumerate(AF_INET6, &parm, complete_context6))
return;
if (daemon->if_names || daemon->if_addrs)
{
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0))
break;
if (!tmp && !parm.addr_match)
return;
}
lease_prune(NULL, now); /* lose any expired leases */
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
@@ -151,15 +185,23 @@ static int complete_context6(struct in6_addr *local, int prefix,
{
struct dhcp_context *context;
struct iface_param *param = vparam;
struct iname *tmp;
(void)scope; /* warning */
(void)dad;
if (if_index == param->ind &&
!IN6_IS_ADDR_LOOPBACK(local) &&
!IN6_IS_ADDR_LINKLOCAL(local) &&
!IN6_IS_ADDR_MULTICAST(local))
{
/* if we have --listen-address config, see if the
arrival interface has a matching address. */
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
if (tmp->addr.sa.sa_family == AF_INET6 &&
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local))
param->addr_match = 1;
/* Determine a globally address on the arrival interface, even
if we have no matching dhcp-context, because we're only
allocating on remote subnets via relays. This
+1 -1
View File
@@ -891,7 +891,7 @@ void safe_pipe(int *fd, int read_noblock);
void *whine_malloc(size_t size);
int sa_len(union mysockaddr *addr);
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
int hostname_isequal(char *a, char *b);
int hostname_isequal(const char *a, const char *b);
time_t dnsmasq_time(void);
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
#ifdef HAVE_IPV6
+5 -1
View File
@@ -2115,7 +2115,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
{
new->prefix = 64; /* default */
new->end6 = new->start6;
/* dhcp-range=:: enables DHCP stateless on any interface */
if (IN6_IS_ADDR_UNSPECIFIED(&new->start6))
new->prefix = 0;
for (leasepos = 1; leasepos < k; leasepos++)
{
if (strcmp(a[leasepos], "static") == 0)
+9 -2
View File
@@ -194,8 +194,8 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
iface_id.next = tags;
tags = &iface_id;
/* set tag "DHCPv6" */
v6_id.net = "DHCPv6";
/* set tag "dhcpv6" */
v6_id.net = "dhcpv6";
v6_id.next = tags;
tags = &v6_id;
@@ -1010,6 +1010,13 @@ static int dhcp6_no_relay(int msg_type, struct in6_addr *link_address, struct dh
case DHCP6IREQ:
{
/* We can't discriminate contexts based on address, as we don't know it.
If there is only one possible context, we can use its tags */
if (context && !context->current)
{
context->netid.next = NULL;
context_tags = &context->netid;
}
log6_packet("DHCPINFORMATION-REQUEST", clid, clid_len, NULL, xid, iface_name, ignore ? "ignored" : hostname);
if (ignore)
return 0;
+1 -1
View File
@@ -280,7 +280,7 @@ int sa_len(union mysockaddr *addr)
}
/* don't use strcasecmp and friends here - they may be messed up by LOCALE */
int hostname_isequal(char *a, char *b)
int hostname_isequal(const char *a, const char *b)
{
unsigned int c1, c2;