Compare commits

...
10 Commits
24 changed files with 4697 additions and 3956 deletions

No files matched your search

+9
View File
@@ -125,6 +125,15 @@ version 2.73
in the correct subnet, even of not in dynamic address
allocation range. Thanks to Steve Hirsch for spotting
the problem.
Add AddDhcpLease and DeleteDhcpLease DBus methods. Thanks
to Nicolas Cavallari for the patch.
Allow configuration of router advertisements without the
"on-link" bit set. Thanks to Neil Jerram for the patch.
Extend --bridge-interface to DHCPv6 and router
advertisements. Thanks to Neil Jerram for the patch.
version 2.72
+1 -1
View File
@@ -117,7 +117,7 @@ install-i18n : all-i18n install-common
cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR) $(INSTALL)
merge :
@cd $(BUILDDIR) && $(MAKE) -f $(top)/Makefile dnsmasq.pot
@cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile dnsmasq.pot
for f in `cd $(PO); echo *.po`; do \
echo -n msgmerge $(PO)/$$f && $(MSGMERGE) --no-wrap -U $(PO)/$$f $(BUILDDIR)/dnsmasq.pot; \
done
+74
View File
@@ -169,6 +169,80 @@ Return an array of strings, each string is the IP address of an upstream
server which has been found to loop queries back to this dnsmasq instance, and
it therefore not being used.
AddDhcpLease
------------
Returns nothing. Adds or updates a DHCP or DHCPv6 lease to the internal lease
database, as if a client requested and obtained a lease.
If a lease for the IPv4 or IPv6 address already exist, it is overwritten.
Note that this function will trigger the DhcpLeaseAdded or DhcpLeaseUpdated
D-Bus signal and will run the configured DHCP lease script accordingly.
This function takes many arguments which are the lease parameters:
- A string with the textual representation of the IPv4 or IPv6 address of the
client.
Examples:
"192.168.1.115"
"1003:1234:abcd::1%eth0"
"2001:db8:abcd::1"
- A string representing the hardware address of the client, using the same
format as the one used in the lease database.
Examples:
"00:23:45:67:89:ab"
"06-00:20:e0:3b:13:af" (token ring)
- The hostname of the client, as an array of bytes (so there is no problem
with non-ASCII character encoding). May be empty.
Example (for "hostname.or.fqdn"):
[104, 111, 115, 116, 110, 97, 109, 101, 46, 111, 114, 46, 102, 113, 100, 110]
- The client identifier (IPv4) or DUID (IPv6) as an array of bytes. May be
empty.
Examples:
DHCPv6 DUID:
[0, 3, 0, 1, 0, 35, 69, 103, 137, 171]
DHCPv4 client identifier:
[255, 12, 34, 56, 78, 0, 1, 0, 1, 29, 9, 99, 190, 35, 69, 103, 137, 171]
- The duration of the lease, in seconds. If the lease is updated, then
the duration replaces the previous duration.
Example:
7200
- The IAID (Identity association identifier) of the DHCPv6 lease, as a network
byte-order unsigned integer. For DHCPv4 leases, this must be set to 0.
Example (for IPv6):
203569230
- A boolean which, if true, indicates that the DHCPv6 lease is for a temporary
address (IA_TA). If false, the DHCPv6 lease is for a non-temporary address
(IA_NA). For DHCPv4 leases, this must be set to false.
RemoveDhcpLease
---------------
Returns nothing. Removes a DHCP or DHCPv6 lease to the internal lease
database, as if a client sent a release message to abandon a lease.
This function takes only one parameter: the text representation of the
IPv4 or IPv6 address of the lease to remove.
Note that this function will trigger the DhcpLeaseRemoved signal and the
configured DHCP lease script will be run with the "del" action.
2. SIGNALS
+11 -6
View File
@@ -833,7 +833,7 @@ and
for details.)
For IPv6, the mode may be some combination of
.B ra-only, slaac, ra-names, ra-stateless, ra-advrouter.
.B ra-only, slaac, ra-names, ra-stateless, ra-advrouter, off-link.
.B ra-only
tells dnsmasq to offer Router Advertisement only on this subnet,
@@ -873,6 +873,9 @@ enables a mode where router address(es) rather than prefix(es) are included in t
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.
.B off-link
tells dnsmasq to advertise the prefix without the on-link (aka L) bit set.
.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
@@ -1597,11 +1600,13 @@ option also forces the leasechange script to be called on changes
to the client-id and lease length and expiry time.
.TP
.B --bridge-interface=<interface>,<alias>[,<alias>]
Treat DHCP request packets arriving at any of the <alias> interfaces
as if they had arrived at <interface>. This option is necessary when
using "old style" bridging on BSD platforms, since
packets arrive at tap interfaces which don't have an IP address.
A trailing '*' wildcard can be used in each <alias>.
Treat DHCP (v4 and v6) request and IPv6 Router Solicit packets
arriving at any of the <alias> interfaces as if they had arrived at
<interface>. This option allows dnsmasq to provide DHCP and RA
service over unaddressed and unbridged Ethernet interfaces, e.g. on an
OpenStack compute host where each such interface is a TAP interface to
a VM, or as in "old style bridging" on BSD platforms. A trailing '*'
wildcard can be used in each <alias>.
.TP
.B \-s, --domain=<domain>[,<address range>[,local]]
Specifies DNS domains for the DHCP server. Domains may be be given
+8 -4
View File
@@ -1062,10 +1062,14 @@ esta opci
cuando hay cambios hechos a el client-id y tiempos de arriendo y vencimiento.
.TP
.B --bridge-interface=<nombre de interface>,<alias>[,<alias>]
Tratar paquetes de pedidos DHCP que llegan a cualquiera de las interfaces <alias>
como si hubieran llegado a la interface <nombre de interface>. Esta opción
es necesaria al usar bridging estilo viejo en plataformas BSD, dado a que
los paquetes llegan a interfaces tap que no tienen una dirección IP.
Tratar paquetes de pedidos DHCP (v4 y v6) y de IPv6 Router Solicit que
llegan a cualquiera de las interfaces <alias> como si hubieran llegado
a la interface <nombre de interface>. Esta opción permite que dnsmasq
puede proporcionar los servicios DHCP y RA a través de interfaces
ethernet sin dirección y sin puente; por ejemplo en un nodo de cálculo
de OpenStack, donde cada una de esas interfaces es una interfaz TAP
para una máquina virtual, o al usar bridging estilo viejo en
plataformas BSD.
.TP
.B \-s, --domain=<dominio>[,<rango de IPs>]
Especifica los dominios DNS para el servidor DHCP. Dominios pueden ser
+12 -6
View File
@@ -852,7 +852,7 @@ et
pour plus de détails).
Pour IPv6, le mode peut-être une combinaison des valeurs
.B ra-only, slaac, ra-names, ra-stateless.
.B ra-only, slaac, ra-names, ra-stateless, off-link.
.B ra-only
indique à dnsmasq de n'effectuer que des annonces de routeur (Router
@@ -888,6 +888,9 @@ peut-être combiné avec
et
.B slaac.
.B off-link
indique à dnsmasq d'annoncer le préfixe sans le bit L (sur lien).
.TP
.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,set:<label>][,<adresse IP>][,<nom d'hôte>][,<durée de bail>][,ignore]
Spécifie les paramètres DHCP relatifs à un hôte. Cela permet à une machine
@@ -1655,11 +1658,14 @@ changement d'état de bail à chaque changement de l'identifiant de client, de
longueur de bail ou de date d'expiration.
.TP
.B --bridge-interface=<interface>,<alias>[,<alias>]
Traiter les requêtes DHCP arrivant sur n'importe laquelle des interfaces <alias>
comme si elles arrivaient de l'interface <interface>. Cette option est
nécessaire lors de l'utilisation de pont ethernet "ancien mode" sur plate-forme
BSD, puisque dans ce cas les paquets arrivent sur des interfaces "tap" n'ont
pas d'adresse IP. Chaque <alias> peut finir avec un simple '*' joker.
Traiter les requêtes DHCP (v4 et v6) et IPv6 Router Solicit arrivant
sur n'importe laquelle des interfaces <alias> comme si elles
arrivaient de l'interface <interface>. Cette option permet à dnsmasq
de fournir les service DHCP et RA sur les interfaces ethernet non
adressés et non pontés; par exemple sur un hôte de calcul d'OpenStack
où chaque telle interface est une interface TAP à une machine
virtuelle, ou lors de l'utilisation de pont ethernet "ancien mode" sur
plate-forme BSD. Chaque <alias> peut finir avec un simple '*' joker.
.TP
.B \-s, --domain=<domaine>[,<gamme d'adresses>[,local]]
Spécifie le domaine du serveur DHCP. Le domaine peut être donné de manière
+407 -383
View File
File diff suppressed because it is too large. Load diff
+414 -390
View File
File diff suppressed because it is too large. Load diff
+413 -389
View File
File diff suppressed because it is too large. Load diff
+407 -383
View File
File diff suppressed because it is too large. Load diff
+428 -404
View File
File diff suppressed because it is too large. Load diff
+413 -389
View File
File diff suppressed because it is too large. Load diff
+424 -400
View File
File diff suppressed because it is too large. Load diff
+407 -383
View File
File diff suppressed because it is too large. Load diff
+413 -389
View File
File diff suppressed because it is too large. Load diff
+424 -400
View File
File diff suppressed because it is too large. Load diff
+193 -2
View File
@@ -70,6 +70,21 @@ const char* introspection_xml_template =
" <arg name=\"hwaddr\" type=\"s\"/>\n"
" <arg name=\"hostname\" type=\"s\"/>\n"
" </signal>\n"
#ifdef HAVE_DHCP
" <method name=\"AddDhcpLease\">\n"
" <arg name=\"ipaddr\" type=\"s\"/>\n"
" <arg name=\"hwaddr\" type=\"s\"/>\n"
" <arg name=\"hostname\" type=\"ay\"/>\n"
" <arg name=\"clid\" type=\"ay\"/>\n"
" <arg name=\"lease_duration\" type=\"u\"/>\n"
" <arg name=\"ia_id\" type=\"u\"/>\n"
" <arg name=\"is_temporary\" type=\"b\"/>\n"
" </method>\n"
" <method name=\"DeleteDhcpLease\">\n"
" <arg name=\"ipaddr\" type=\"s\"/>\n"
" <arg name=\"success\" type=\"b\" direction=\"out\"/>\n"
" </method>\n"
#endif
" </interface>\n"
"</node>\n";
@@ -421,18 +436,184 @@ static DBusMessage *dbus_set_bool(DBusMessage *message, int flag, char *name)
if (enabled)
{
my_syslog(LOG_INFO, "Enabling --%s option from D-Bus", name);
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);
my_syslog(LOG_INFO, _("Disabling --%s option from D-Bus"), name);
reset_option_bool(flag);
}
return NULL;
}
#ifdef HAVE_DHCP
static DBusMessage *dbus_add_lease(DBusMessage* message)
{
struct dhcp_lease *lease;
const char *ipaddr, *hwaddr, *hostname, *tmp;
const unsigned char* clid;
int clid_len, hostname_len, hw_len, hw_type;
dbus_uint32_t expires, ia_id;
dbus_bool_t is_temporary;
struct all_addr addr;
time_t now = dnsmasq_time();
unsigned char dhcp_chaddr[DHCP_CHADDR_MAX];
DBusMessageIter iter, array_iter;
if (!dbus_message_iter_init(message, &iter))
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Failed to initialize dbus message iter");
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected string as first argument");
dbus_message_iter_get_basic(&iter, &ipaddr);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected string as second argument");
dbus_message_iter_get_basic(&iter, &hwaddr);
dbus_message_iter_next(&iter);
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
(dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected byte array as third argument");
dbus_message_iter_recurse(&iter, &array_iter);
dbus_message_iter_get_fixed_array(&array_iter, &hostname, &hostname_len);
tmp = memchr(hostname, '\0', hostname_len);
if (tmp)
{
if (tmp == &hostname[hostname_len - 1])
hostname_len--;
else
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Hostname contains an embedded NUL character");
}
dbus_message_iter_next(&iter);
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
(dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected byte array as fourth argument");
dbus_message_iter_recurse(&iter, &array_iter);
dbus_message_iter_get_fixed_array(&array_iter, &clid, &clid_len);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected uint32 as fifth argument");
dbus_message_iter_get_basic(&iter, &expires);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected uint32 as sixth argument");
dbus_message_iter_get_basic(&iter, &ia_id);
dbus_message_iter_next(&iter);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected uint32 as sixth argument");
dbus_message_iter_get_basic(&iter, &is_temporary);
if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
{
if (ia_id != 0 || is_temporary)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"ia_id and is_temporary must be zero for IPv4 lease");
if (!(lease = lease_find_by_addr(addr.addr.addr4)))
lease = lease4_allocate(addr.addr.addr4);
}
#ifdef HAVE_DHCP6
else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
{
if (!(lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0)))
lease = lease6_allocate(&addr.addr.addr6,
is_temporary ? LEASE_TA : LEASE_NA);
lease_set_iaid(lease, ia_id);
}
#endif
else
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
"Invalid IP address '%s'", ipaddr);
hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL,
&hw_type);
if (hw_type == 0 && hw_len != 0)
hw_type = ARPHRD_ETHER;
lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
clid_len, now, 0);
lease_set_expires(lease, expires, now);
if (hostname_len != 0)
lease_set_hostname(lease, hostname, 0, get_domain(lease->addr), NULL);
lease_update_file(now);
lease_update_dns(0);
return NULL;
}
static DBusMessage *dbus_del_lease(DBusMessage* message)
{
struct dhcp_lease *lease;
DBusMessageIter iter;
const char *ipaddr;
DBusMessage *reply;
struct all_addr addr;
dbus_bool_t ret = 1;
time_t now = dnsmasq_time();
if (!dbus_message_iter_init(message, &iter))
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Failed to initialize dbus message iter");
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
"Expected string as first argument");
dbus_message_iter_get_basic(&iter, &ipaddr);
if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
lease = lease_find_by_addr(addr.addr.addr4);
#ifdef HAVE_DHCP6
else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0);
#endif
else
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
"Invalid IP address '%s'", ipaddr);
if (lease)
{
lease_prune(lease, now);
lease_update_file(now);
lease_update_dns(0);
}
else
ret = 0;
if ((reply = dbus_message_new_method_return(message)))
dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &ret,
DBUS_TYPE_INVALID);
return reply;
}
#endif
DBusHandlerResult message_handler(DBusConnection *connection,
DBusMessage *message,
void *user_data)
@@ -490,6 +671,16 @@ DBusHandlerResult message_handler(DBusConnection *connection,
{
reply = dbus_set_bool(message, OPT_BOGUSPRIV, "bogus-priv");
}
#ifdef HAVE_DHCP
else if (strcmp(method, "AddDhcpLease") == 0)
{
reply = dbus_add_lease(message);
}
else if (strcmp(method, "DeleteDhcpLease") == 0)
{
reply = dbus_del_lease(message);
}
#endif
else if (strcmp(method, "ClearCache") == 0)
clear_cache = 1;
else
+8 -5
View File
@@ -225,10 +225,11 @@ void dhcp_packet(time_t now, int pxe_fd)
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
#endif
/* One form of bridging on BSD has the property that packets
can be recieved on bridge interfaces which do not have an IP address.
We allow these to be treated as aliases of another interface which does have
an IP address with --dhcp-bridge=interface,alias,alias */
/* If the interface on which the DHCP request was received is an
alias of some other interface (as specified by the
--bridge-interface option), change ifr.ifr_name so that we look
for DHCP contexts associated with the aliased interface instead
of with the aliasing one. */
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
{
for (alias = bridge->alias; alias; alias = alias->next)
@@ -236,7 +237,9 @@ void dhcp_packet(time_t now, int pxe_fd)
{
if (!(iface_index = if_nametoindex(bridge->iface)))
{
my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), ifr.ifr_name);
my_syslog(MS_DHCP | LOG_WARNING,
_("unknown interface %s in bridge-interface"),
bridge->iface);
return;
}
else
+27 -1
View File
@@ -144,6 +144,8 @@ void dhcp6_packet(time_t now)
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) == 0)
{
struct dhcp_bridge *bridge, *alias;
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
return;
@@ -160,6 +162,30 @@ void dhcp6_packet(time_t now)
memset(&parm.fallback, 0, IN6ADDRSZ);
memset(&parm.ll_addr, 0, IN6ADDRSZ);
memset(&parm.ula_addr, 0, IN6ADDRSZ);
/* If the interface on which the DHCPv6 request was received is
an alias of some other interface (as specified by the
--bridge-interface option), change parm.ind so that we look
for DHCPv6 contexts associated with the aliased interface
instead of with the aliasing one. */
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
{
for (alias = bridge->alias; alias; alias = alias->next)
if (wildcard_matchn(alias->iface, ifr.ifr_name, IF_NAMESIZE))
{
parm.ind = if_nametoindex(bridge->iface);
if (!parm.ind)
{
my_syslog(MS_DHCP | LOG_WARNING,
_("unknown interface %s in bridge-interface"),
bridge->iface);
return;
}
break;
}
if (alias)
break;
}
for (context = daemon->dhcp6; context; context = context->next)
if (IN6_IS_ADDR_UNSPECIFIED(&context->start6) && context->prefix == 0)
@@ -208,7 +234,7 @@ void dhcp6_packet(time_t now)
/* May have configured relay, but not DHCP server */
if (!daemon->doing_dhcp6)
return;
lease_prune(NULL, now); /* lose any expired leases */
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
+1
View File
@@ -868,6 +868,7 @@ struct dhcp_context {
#define CONTEXT_USED (1u<<15)
#define CONTEXT_OLD (1u<<16)
#define CONTEXT_V6 (1u<<17)
#define CONTEXT_RA_OFF_LINK (1u<<18)
struct ping_result {
struct in_addr addr;
+34 -6
View File
@@ -1223,8 +1223,11 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, &neganswer, &nons);
/* Note dnssec_validate_reply() will have cached positive answers */
if (val == STAT_NO_SIG || val == STAT_INSECURE)
if (val == STAT_INSECURE)
val = STAT_BOGUS;
if (val == STAT_NO_SIG)
return val;
p = (unsigned char *)(header+1);
extract_name(header, plen, &p, name, 1, 4);
@@ -1875,11 +1878,14 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
if (neganswer && !have_answer)
*neganswer = 1;
/* No data, therefore no sigs */
if (ntohs(header->ancount) + ntohs(header->nscount) == 0)
return STAT_NO_SIG;
{
*keyname = 0;
return STAT_NO_SIG;
}
for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
{
if (!extract_name(header, plen, &p1, name, 1, 10))
@@ -1948,6 +1954,19 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
{
if (class)
*class = class1; /* Class for DS or DNSKEY */
if (rc == STAT_NO_SIG)
{
/* If we dropped off the end of a CNAME chain, return
STAT_NO_SIG and the last name is keyname. This is used for proving non-existence
if DS records in CNAME chains. */
if (cname_count == CNAME_CHAIN || i < ntohs(header->ancount))
/* No CNAME chain, or no sig in answer section, return empty name. */
*keyname = 0;
else if (!extract_name(header, plen, &qname, keyname, 1, 0))
return STAT_BOGUS;
}
return rc;
}
@@ -2060,8 +2079,17 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
/* NXDOMAIN or NODATA reply, prove that (name, class1, type1) can't exist */
/* First marshall the NSEC records, if we've not done it previously */
if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, qclass)))
return STAT_NO_SIG; /* No NSECs, this is probably a dangling CNAME pointing into
an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
{
/* No NSEC records. If we dropped off the end of a CNAME chain, return
STAT_NO_SIG and the last name is keyname. This is used for proving non-existence
if DS records in CNAME chains. */
if (cname_count == CNAME_CHAIN) /* No CNAME chain, return empty name. */
*keyname = 0;
else if (!extract_name(header, plen, &qname, keyname, 1, 0))
return STAT_BOGUS;
return STAT_NO_SIG; /* No NSECs, this is probably a dangling CNAME pointing into
an unsigned zone. Return STAT_NO_SIG to cause this to be proved. */
}
/* Get name of missing answer */
if (!extract_name(header, plen, &qname, name, 1, 0))
+34 -4
View File
@@ -851,7 +851,7 @@ void reply_query(int fd, int family, time_t now)
Avoid caching a reply with sigs if there's a vaildated break in the
DS chain, so we don't return replies from cache missing sigs. */
status = STAT_INSECURE_DS;
else if (status == STAT_NO_NS)
else if (status == STAT_NO_NS || status == STAT_NO_SIG)
status = STAT_BOGUS;
}
else if (forward->flags & FREC_CHECK_NOSIGN)
@@ -997,7 +997,7 @@ void reply_query(int fd, int family, time_t now)
Avoid caching a reply with sigs if there's a vaildated break in the
DS chain, so we don't return replies from cache missing sigs. */
status = STAT_INSECURE_DS;
else if (status == STAT_NO_NS)
else if (status == STAT_NO_NS || status == STAT_NO_SIG)
status = STAT_BOGUS;
}
else if (forward->flags & FREC_CHECK_NOSIGN)
@@ -1456,6 +1456,21 @@ static int do_check_sign(struct frec *forward, int status, time_t now, char *nam
if (status == STAT_BOGUS)
return STAT_BOGUS;
if (status == STAT_NO_SIG && *keyname != 0)
{
/* There is a validated CNAME chain that doesn't end in a DS record. Start
the search again in that domain. */
blockdata_free(forward->orig_domain);
forward->name_start = strlen(keyname);
forward->name_len = forward->name_start + 1;
if (!(forward->orig_domain = blockdata_alloc(keyname, forward->name_len)))
return STAT_BOGUS;
strcpy(name, keyname);
status = 0; /* force to cache when we iterate. */
continue;
}
/* There's a proven DS record, or we're within a zone, where there doesn't need
to be a DS record. Add a name and try again.
If we've already tried the whole name, then fail */
@@ -1572,6 +1587,21 @@ static int tcp_check_for_unsigned_zone(time_t now, struct dns_header *header, s
return STAT_INSECURE;
}
if (status == STAT_NO_SIG && *keyname != 0)
{
/* There is a validated CNAME chain that doesn't end in a DS record. Start
the search again in that domain. */
blockdata_free(block);
name_len = strlen(keyname) + 1;
name_start = name + name_len - 1;
if (!(block = blockdata_alloc(keyname, name_len)))
return STAT_BOGUS;
strcpy(name, keyname);
continue;
}
if (status == STAT_BOGUS)
{
free(packet);
@@ -1627,7 +1657,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
{
if (new_status == STAT_NO_DS)
new_status = STAT_INSECURE_DS;
else if (new_status == STAT_NO_NS)
else if (new_status == STAT_NO_NS || new_status == STAT_NO_SIG)
new_status = STAT_BOGUS;
}
}
@@ -1692,7 +1722,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
{
if (new_status == STAT_NO_DS)
new_status = STAT_INSECURE_DS;
else if (new_status == STAT_NO_NS)
else if (new_status == STAT_NO_NS || new_status == STAT_NO_SIG)
new_status = STAT_BOGUS; /* Validated no DS */
}
}
+2
View File
@@ -2699,6 +2699,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
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 (strcmp(a[leasepos], "off-link") == 0)
new->flags |= CONTEXT_RA_OFF_LINK;
else if (leasepos == 1 && inet_pton(AF_INET6, a[leasepos], &new->end6))
new->flags |= CONTEXT_DHCP;
else if (strstr(a[leasepos], "constructor:") == a[leasepos])
+133 -11
View File
@@ -40,7 +40,18 @@ struct search_param {
char name[IF_NAMESIZE+1];
};
struct alias_param {
int iface;
struct dhcp_bridge *bridge;
int num_alias_ifs;
int max_alias_ifs;
int *alias_ifs;
};
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest);
static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_addr *dest,
int send_iface);
static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t maclen, void *parm);
static int add_prefixes(struct in6_addr *local, int prefix,
int scope, int if_index, int flags,
unsigned int preferred, unsigned int valid, void *vparam);
@@ -181,6 +192,7 @@ void icmp6_packet(time_t now)
else if (packet[0] == ND_ROUTER_SOLICIT)
{
char *mac = "";
struct dhcp_bridge *bridge, *alias;
/* look for link-layer address option for logging */
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
@@ -191,12 +203,37 @@ void icmp6_packet(time_t now)
if (!option_bool(OPT_QUIET_RA))
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
/* source address may not be valid in solicit request. */
send_ra(now, if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
/* If the incoming interface is an alias of some other one (as
specified by the --bridge-interface option), send an RA using
the context of the aliased interface. */
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
{
int bridge_index = if_nametoindex(bridge->iface);
if (bridge_index)
{
for (alias = bridge->alias; alias; alias = alias->next)
if (wildcard_matchn(alias->iface, interface, IF_NAMESIZE))
{
/* Send an RA on if_index with information from
bridge_index. */
send_ra_alias(now, bridge_index, bridge->iface, NULL, if_index);
break;
}
if (alias)
break;
}
}
/* If the incoming interface wasn't an alias, send an RA using
the context of the incoming interface. */
if (!bridge)
/* source address may not be valid in solicit request. */
send_ra(now, if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
}
}
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest)
static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_addr *dest, int send_iface)
{
struct ra_packet *ra;
struct ra_param parm;
@@ -313,8 +350,10 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
opt->type = ICMP6_OPT_PREFIX;
opt->len = 4;
opt->prefix_len = context->prefix;
/* autonomous only if we're not doing dhcp, always set "on-link" */
opt->flags = do_slaac ? 0xC0 : 0x80;
/* autonomous only if we're not doing dhcp, set
"on-link" unless "off-link" was specified */
opt->flags = (do_slaac ? 0x40 : 0) |
((context->flags & CONTEXT_RA_OFF_LINK) ? 0 : 0x80);
opt->valid_lifetime = htonl(context->saved_valid - old);
opt->preferred_lifetime = htonl(0);
opt->reserved = 0;
@@ -368,7 +407,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
}
#endif
iface_enumerate(AF_LOCAL, &iface, add_lla);
iface_enumerate(AF_LOCAL, &send_iface, add_lla);
/* RDNSS, RFC 6106, use relevant DHCP6 options */
(void)option_filter(parm.tags, NULL, daemon->dhcp_opts6);
@@ -476,7 +515,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
else
{
inet_pton(AF_INET6, ALL_NODES, &addr.sin6_addr);
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface, sizeof(iface));
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &send_iface, sizeof(send_iface));
}
while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,
@@ -485,6 +524,13 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
}
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest)
{
/* Send an RA on the same interface that the RA content is based
on. */
send_ra_alias(now, iface, iface_name, dest, iface);
}
static int add_prefixes(struct in6_addr *local, int prefix,
int scope, int if_index, int flags,
unsigned int preferred, unsigned int valid, void *vparam)
@@ -514,6 +560,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
int deprecate = 0;
int constructed = 0;
int adv_router = 0;
int off_link = 0;
unsigned int time = 0xffffffff;
struct dhcp_context *context;
@@ -586,6 +633,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
context->ra_time = 0;
context->flags |= CONTEXT_RA_DONE;
real_prefix = context->prefix;
off_link = (context->flags & CONTEXT_RA_OFF_LINK);
}
param->first = 0;
@@ -636,8 +684,9 @@ static int add_prefixes(struct in6_addr *local, int prefix,
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 = 0x80;
/* autonomous only if we're not doing dhcp, set
"on-link" unless "off-link" was specified */
opt->flags = (off_link ? 0 : 0x80);
if (do_slaac)
opt->flags |= 0x40;
if (adv_router)
@@ -683,6 +732,7 @@ time_t periodic_ra(time_t now)
struct search_param param;
struct dhcp_context *context;
time_t next_event;
struct alias_param aparam;
param.now = now;
param.iface = 0;
@@ -730,12 +780,84 @@ time_t periodic_ra(time_t now)
if (tmp->name && wildcard_match(tmp->name, param.name))
break;
if (!tmp)
send_ra(now, param.iface, param.name, NULL);
{
send_ra(now, param.iface, param.name, NULL);
/* Also send on all interfaces that are aliases of this
one. */
for (aparam.bridge = daemon->bridges;
aparam.bridge;
aparam.bridge = aparam.bridge->next)
if ((int)if_nametoindex(aparam.bridge->iface) == param.iface)
{
/* Count the number of alias interfaces for this
'bridge', by calling iface_enumerate with
send_ra_to_aliases and NULL alias_ifs. */
aparam.iface = param.iface;
aparam.alias_ifs = NULL;
aparam.num_alias_ifs = 0;
iface_enumerate(AF_LOCAL, &aparam, send_ra_to_aliases);
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s => %d alias(es)",
param.name, daemon->addrbuff, aparam.num_alias_ifs);
/* Allocate memory to store the alias interface
indices. */
aparam.alias_ifs = (int *)whine_malloc(aparam.num_alias_ifs *
sizeof(int));
if (aparam.alias_ifs)
{
/* Use iface_enumerate again to get the alias
interface indices, then send on each of
those. */
aparam.max_alias_ifs = aparam.num_alias_ifs;
aparam.num_alias_ifs = 0;
iface_enumerate(AF_LOCAL, &aparam, send_ra_to_aliases);
for (; aparam.num_alias_ifs; aparam.num_alias_ifs--)
{
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s => i/f %d",
param.name, daemon->addrbuff,
aparam.alias_ifs[aparam.num_alias_ifs - 1]);
send_ra_alias(now,
param.iface,
param.name,
NULL,
aparam.alias_ifs[aparam.num_alias_ifs - 1]);
}
free(aparam.alias_ifs);
}
/* The source interface can only appear in at most
one --bridge-interface. */
break;
}
}
}
}
return next_event;
}
static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t maclen, void *parm)
{
struct alias_param *aparam = (struct alias_param *)parm;
char ifrn_name[IFNAMSIZ];
struct dhcp_bridge *alias;
(void)type;
(void)mac;
(void)maclen;
if (if_indextoname(index, ifrn_name))
for (alias = aparam->bridge->alias; alias; alias = alias->next)
if (wildcard_matchn(alias->iface, ifrn_name, IFNAMSIZ))
{
if (aparam->alias_ifs && (aparam->num_alias_ifs < aparam->max_alias_ifs))
aparam->alias_ifs[aparam->num_alias_ifs] = index;
aparam->num_alias_ifs++;
}
return 1;
}
static int iface_search(struct in6_addr *local, int prefix,
int scope, int if_index, int flags,
int preferred, int valid, void *vparam)