mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-09 16:20:55 +00:00
Compare commits
5
Commits
v2.67test2
...
v2.67test3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2bb73af7d1 | ||
|
|
86e92f9983 | ||
|
|
1c10b9de11 | ||
|
|
a66d36ea11 | ||
|
|
aa63a21ce0 |
No files matched your search
@@ -3,6 +3,22 @@ version 2.67
|
|||||||
--conntrack in use. Thanks to Giacomo Tazzari for finding
|
--conntrack in use. Thanks to Giacomo Tazzari for finding
|
||||||
this and supplying the patch.
|
this and supplying the patch.
|
||||||
|
|
||||||
|
Repair regression in 2.64. That release stopped sending
|
||||||
|
lease-time information in the reply to DHCPINFORM
|
||||||
|
requests, on the correct grounds that it was a standards
|
||||||
|
violation. However, this broke the dnsmasq-specific
|
||||||
|
dhcp_lease_time utility. Now, DHCPINFORM returns
|
||||||
|
lease-time only if it's specifically requested
|
||||||
|
(maintaining standards) and the dhcp_lease_time utility
|
||||||
|
has been taught to ask for it (restoring functionality).
|
||||||
|
|
||||||
|
Fix --dhcp-match, --dhcp-vendorclass and --dhcp-userclass
|
||||||
|
to work with BOOTP and well as DHCP. Thanks to Peter
|
||||||
|
Korsgaard for spotting the problem.
|
||||||
|
|
||||||
|
Add --synth-domain. Thanks to Vishvananda Ishaya for
|
||||||
|
suggesting this.
|
||||||
|
|
||||||
|
|
||||||
version 2.66
|
version 2.66
|
||||||
Add the ability to act as an authoritative DNS
|
Add the ability to act as an authoritative DNS
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
|
|||||||
objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
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 \
|
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 \
|
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
|
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o domain.o
|
||||||
|
|
||||||
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
||||||
dns-protocol.h radv-protocol.h
|
dns-protocol.h radv-protocol.h
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
|
|||||||
netlink.c network.c option.c rfc1035.c \
|
netlink.c network.c option.c rfc1035.c \
|
||||||
rfc2131.c tftp.c util.c conntrack.c \
|
rfc2131.c tftp.c util.c conntrack.c \
|
||||||
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
||||||
radv.c slaac.c auth.c ipset.c
|
radv.c slaac.c auth.c ipset.c domain.c
|
||||||
|
|
||||||
LOCAL_MODULE := dnsmasq
|
LOCAL_MODULE := dnsmasq
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,11 @@ If an error occurs or no lease exists for the given address,
|
|||||||
nothing is sent to stdout a message is sent to stderr and a
|
nothing is sent to stdout a message is sent to stderr and a
|
||||||
non-zero error code is returned.
|
non-zero error code is returned.
|
||||||
|
|
||||||
Requires dnsmasq 2.40 or later and may not work with other DHCP servers.
|
Requires dnsmasq 2.67 or later and may not work with other DHCP servers.
|
||||||
|
|
||||||
The address argument is a dotted-quad IP addresses and mandatory.
|
The address argument is a dotted-quad IP addresses and mandatory.
|
||||||
|
.SH LIMITATIONS
|
||||||
|
Only works with IPv4 addresses and DHCP leases.
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR dnsmasq (8)
|
.BR dnsmasq (8)
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
nothing is sent to stdout a message is sent to stderr and a
|
nothing is sent to stdout a message is sent to stderr and a
|
||||||
non-zero error code is returned.
|
non-zero error code is returned.
|
||||||
|
|
||||||
Requires dnsmasq 2.40 or later.
|
This version requires dnsmasq 2.67 or later.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@@ -46,6 +46,7 @@
|
|||||||
#define OPTION_LEASE_TIME 51
|
#define OPTION_LEASE_TIME 51
|
||||||
#define OPTION_OVERLOAD 52
|
#define OPTION_OVERLOAD 52
|
||||||
#define OPTION_MESSAGE_TYPE 53
|
#define OPTION_MESSAGE_TYPE 53
|
||||||
|
#define OPTION_REQUESTED_OPTIONS 55
|
||||||
#define OPTION_END 255
|
#define OPTION_END 255
|
||||||
#define DHCPINFORM 8
|
#define DHCPINFORM 8
|
||||||
#define DHCP_SERVER_PORT 67
|
#define DHCP_SERVER_PORT 67
|
||||||
@@ -167,6 +168,12 @@ int main(int argc, char **argv)
|
|||||||
*(p++) = 1;
|
*(p++) = 1;
|
||||||
*(p++) = DHCPINFORM;
|
*(p++) = DHCPINFORM;
|
||||||
|
|
||||||
|
/* Explicity request the lease time, it won't be sent otherwise:
|
||||||
|
this is a dnsmasq extension, not standard. */
|
||||||
|
*(p++) = OPTION_REQUESTED_OPTIONS;
|
||||||
|
*(p++) = 1;
|
||||||
|
*(p++) = OPTION_LEASE_TIME;
|
||||||
|
|
||||||
*(p++) = OPTION_END;
|
*(p++) = OPTION_END;
|
||||||
|
|
||||||
dest.sin_family = AF_INET;
|
dest.sin_family = AF_INET;
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ for ethernet. This encoding is the one used in dnsmasq lease files.
|
|||||||
The client-id is optional. If it is "*" then it treated as being missing.
|
The client-id is optional. If it is "*" then it treated as being missing.
|
||||||
.SH NOTES
|
.SH NOTES
|
||||||
MUST be run as root - will fail otherwise.
|
MUST be run as root - will fail otherwise.
|
||||||
|
.SH LIMITATIONS
|
||||||
|
Only usable on IPv4 DHCP leases.
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR dnsmasq (8)
|
.BR dnsmasq (8)
|
||||||
.SH AUTHOR
|
.SH AUTHOR
|
||||||
|
|||||||
+24
-9
@@ -519,6 +519,21 @@ the name. More than one name may be associated with an interface
|
|||||||
address by repeating the flag; in that case the first instance is used
|
address by repeating the flag; in that case the first instance is used
|
||||||
for the reverse address-to-name mapping.
|
for the reverse address-to-name mapping.
|
||||||
.TP
|
.TP
|
||||||
|
.B --synth-domain=<domain>,<address range>
|
||||||
|
Create artificial A/AAAA and PTR records for an address range. The
|
||||||
|
records use the address, with periods (or colons for IPv6) replaced
|
||||||
|
with dashes.
|
||||||
|
|
||||||
|
An example should make this clearer.
|
||||||
|
.B --synth-domain=thekelleys.org.uk,192.168.0.0/24
|
||||||
|
will result in a query for 192-168-0-56.thekelleys.org.uk returning
|
||||||
|
192.168.0.56 and a reverse query vice versa. The same applies to IPv6, but IPv6 addresses may start with '::'
|
||||||
|
but DNS labels may not start with '-' so in this case a zero is added
|
||||||
|
in front of the label. ::1 becomes 0--1.
|
||||||
|
|
||||||
|
The address range can be of the form
|
||||||
|
<ip address>,<ip address> or <ip address>/<netmask>
|
||||||
|
.TP
|
||||||
.B --add-mac
|
.B --add-mac
|
||||||
Add the MAC address of the requestor to DNS queries which are
|
Add the MAC address of the requestor to DNS queries which are
|
||||||
forwarded upstream. This may be used to DNS filtering by the upstream
|
forwarded upstream. This may be used to DNS filtering by the upstream
|
||||||
@@ -559,7 +574,7 @@ needed for a client to do validation itself.
|
|||||||
.B --auth-zone=<domain>[,<subnet>[,<subnet>.....]]
|
.B --auth-zone=<domain>[,<subnet>[,<subnet>.....]]
|
||||||
Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain
|
Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain
|
||||||
will be served, except that A and AAAA records must be in one of the
|
will be served, except that A and AAAA records must be in one of the
|
||||||
specified subnets, or in a subnet corresponding to a contructed DHCP
|
specified subnets, or in a subnet corresponding to a constructed DHCP
|
||||||
range. The subnet(s) are also used to define in-addr.arpa and
|
range. The subnet(s) are also used to define in-addr.arpa and
|
||||||
ipv6.arpa domains which are served for reverse-DNS queries. For IPv4
|
ipv6.arpa domains which are served for reverse-DNS queries. For IPv4
|
||||||
subnets, the prefix length is limited to the values 8, 16 or 24.
|
subnets, the prefix length is limited to the values 8, 16 or 24.
|
||||||
@@ -763,7 +778,7 @@ This is
|
|||||||
useful when there is another DHCP server on the network which should
|
useful when there is another DHCP server on the network which should
|
||||||
be used by some machines.
|
be used by some machines.
|
||||||
|
|
||||||
The set:<tag> contruct sets the tag
|
The set:<tag> construct sets the tag
|
||||||
whenever this dhcp-host directive is in use. This can be used to
|
whenever this dhcp-host directive is in use. This can be used to
|
||||||
selectively send DHCP options just for this host. More than one tag
|
selectively send DHCP options just for this host. More than one tag
|
||||||
can be set in a dhcp-host directive (but not in other places where
|
can be set in a dhcp-host directive (but not in other places where
|
||||||
@@ -978,7 +993,7 @@ agent ID and one provided by a relay agent, the tag is set.
|
|||||||
(IPv4 only) A normal DHCP relay agent is only used to forward the initial parts of
|
(IPv4 only) A normal DHCP relay agent is only used to forward the initial parts of
|
||||||
a DHCP interaction to the DHCP server. Once a client is configured, it
|
a DHCP interaction to the DHCP server. Once a client is configured, it
|
||||||
communicates directly with the server. This is undesirable if the
|
communicates directly with the server. This is undesirable if the
|
||||||
relay agent is addding extra information to the DHCP packets, such as
|
relay agent is adding extra information to the DHCP packets, such as
|
||||||
that used by
|
that used by
|
||||||
.B dhcp-circuitid
|
.B dhcp-circuitid
|
||||||
and
|
and
|
||||||
@@ -995,7 +1010,7 @@ relays at those addresses are affected.
|
|||||||
Without a value, set the tag if the client sends a DHCP
|
Without a value, set the tag if the client sends a DHCP
|
||||||
option of the given number or name. When a value is given, set the tag only if
|
option of the given number or name. When a value is given, set the tag only if
|
||||||
the option is sent and matches the value. The value may be of the form
|
the option is sent and matches the value. The value may be of the form
|
||||||
"01:ff:*:02" in which case the value must match (apart from widcards)
|
"01:ff:*:02" in which case the value must match (apart from wildcards)
|
||||||
but the option sent may have unmatched data past the end of the
|
but the option sent may have unmatched data past the end of the
|
||||||
value. The value may also be of the same form as in
|
value. The value may also be of the same form as in
|
||||||
.B dhcp-option
|
.B dhcp-option
|
||||||
@@ -1008,7 +1023,7 @@ will set the tag "efi-ia32" if the the number 6 appears in the list of
|
|||||||
architectures sent by the client in option 93. (See RFC 4578 for
|
architectures sent by the client in option 93. (See RFC 4578 for
|
||||||
details.) If the value is a string, substring matching is used.
|
details.) If the value is a string, substring matching is used.
|
||||||
|
|
||||||
The special form with vi-encap:<enterpise number> matches against
|
The special form with vi-encap:<enterprise number> matches against
|
||||||
vendor-identifying vendor classes for the specified enterprise. Please
|
vendor-identifying vendor classes for the specified enterprise. Please
|
||||||
see RFC 3925 for more details of these rare and interesting beasts.
|
see RFC 3925 for more details of these rare and interesting beasts.
|
||||||
.TP
|
.TP
|
||||||
@@ -1036,7 +1051,7 @@ dhcp-host configuration in dnsmasq and the contents of /etc/hosts and
|
|||||||
.TP
|
.TP
|
||||||
.B --dhcp-generate-names=tag:<tag>[,tag:<tag>]
|
.B --dhcp-generate-names=tag:<tag>[,tag:<tag>]
|
||||||
(IPv4 only) Generate a name for DHCP clients which do not otherwise have one,
|
(IPv4 only) Generate a name for DHCP clients which do not otherwise have one,
|
||||||
using the MAC address expressed in hex, seperated by dashes. Note that
|
using the MAC address expressed in hex, separated by dashes. Note that
|
||||||
if a host provides a name, it will be used by preference to this,
|
if a host provides a name, it will be used by preference to this,
|
||||||
unless
|
unless
|
||||||
.B --dhcp-ignore-names
|
.B --dhcp-ignore-names
|
||||||
@@ -1113,7 +1128,7 @@ timeout has elapsed with no keyboard input, the first available menu
|
|||||||
option will be automatically executed. If the timeout is zero then the first available menu
|
option will be automatically executed. If the timeout is zero then the first available menu
|
||||||
item will be executed immediately. If
|
item will be executed immediately. If
|
||||||
.B pxe-prompt
|
.B pxe-prompt
|
||||||
is ommitted the system will wait for user input if there are multiple
|
is omitted the system will wait for user input if there are multiple
|
||||||
items in the menu, but boot immediately if
|
items in the menu, but boot immediately if
|
||||||
there is only one. See
|
there is only one. See
|
||||||
.B pxe-service
|
.B pxe-service
|
||||||
@@ -1412,7 +1427,7 @@ In the default mode, dnsmasq inserts the unqualified names of
|
|||||||
DHCP clients into the DNS. For this reason, the names must be unique,
|
DHCP clients into the DNS. For this reason, the names must be unique,
|
||||||
even if two clients which have the same name are in different
|
even if two clients which have the same name are in different
|
||||||
domains. If a second DHCP client appears which has the same name as an
|
domains. If a second DHCP client appears which has the same name as an
|
||||||
existing client, the name is transfered to the new client. If
|
existing client, the name is transferred to the new client. If
|
||||||
.B --dhcp-fqdn
|
.B --dhcp-fqdn
|
||||||
is set, this behaviour changes: the unqualified name is no longer
|
is set, this behaviour changes: the unqualified name is no longer
|
||||||
put in the DNS, only the qualified name. Two DHCP clients with the
|
put in the DNS, only the qualified name. Two DHCP clients with the
|
||||||
@@ -1666,7 +1681,7 @@ used to allocate the address, one from any matching
|
|||||||
The tag "bootp" is set for BOOTP requests, and a tag whose name is the
|
The tag "bootp" is set for BOOTP requests, and a tag whose name is the
|
||||||
name of the interface on which the request arrived is also set.
|
name of the interface on which the request arrived is also set.
|
||||||
|
|
||||||
Any configuration lines which includes one or more tag:<tag> contructs
|
Any configuration lines which include one or more tag:<tag> constructs
|
||||||
will only be valid if all that tags are matched in the set derived
|
will only be valid if all that tags are matched in the set derived
|
||||||
above. Typically this is dhcp-option.
|
above. Typically this is dhcp-option.
|
||||||
.B dhcp-option
|
.B dhcp-option
|
||||||
|
|||||||
-32
@@ -971,38 +971,6 @@ void cache_reload(void)
|
|||||||
total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
|
total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *get_domain(struct in_addr addr)
|
|
||||||
{
|
|
||||||
struct cond_domain *c;
|
|
||||||
|
|
||||||
for (c = daemon->cond_domain; c; c = c->next)
|
|
||||||
if (!c->is6 &&
|
|
||||||
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
|
|
||||||
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
|
|
||||||
return c->domain;
|
|
||||||
|
|
||||||
return daemon->domain_suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
char *get_domain6(struct in6_addr *addr)
|
|
||||||
{
|
|
||||||
struct cond_domain *c;
|
|
||||||
|
|
||||||
u64 addrpart = addr6part(addr);
|
|
||||||
|
|
||||||
for (c = daemon->cond_domain; c; c = c->next)
|
|
||||||
if (c->is6 &&
|
|
||||||
is_same_net6(addr, &c->start6, 64) &&
|
|
||||||
addrpart >= addr6part(&c->start6) &&
|
|
||||||
addrpart <= addr6part(&c->end6))
|
|
||||||
return c->domain;
|
|
||||||
|
|
||||||
return daemon->domain_suffix;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
struct in_addr a_record_from_hosts(char *name, time_t now)
|
struct in_addr a_record_from_hosts(char *name, time_t now)
|
||||||
{
|
{
|
||||||
|
|||||||
+9
-5
@@ -789,7 +789,7 @@ extern struct daemon {
|
|||||||
struct name_list *secondary_forward_server;
|
struct name_list *secondary_forward_server;
|
||||||
int group_set, osport;
|
int group_set, osport;
|
||||||
char *domain_suffix;
|
char *domain_suffix;
|
||||||
struct cond_domain *cond_domain;
|
struct cond_domain *cond_domain, *synth_domains;
|
||||||
char *runfile;
|
char *runfile;
|
||||||
char *lease_change_command;
|
char *lease_change_command;
|
||||||
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers;
|
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers;
|
||||||
@@ -907,15 +907,19 @@ void cache_unhash_dhcp(void);
|
|||||||
void dump_cache(time_t now);
|
void dump_cache(time_t now);
|
||||||
char *cache_get_name(struct crec *crecp);
|
char *cache_get_name(struct crec *crecp);
|
||||||
struct crec *cache_enumerate(int init);
|
struct crec *cache_enumerate(int init);
|
||||||
char *get_domain(struct in_addr addr);
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
char *get_domain6(struct in6_addr *addr);
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
struct keydata *keydata_alloc(char *data, size_t len);
|
struct keydata *keydata_alloc(char *data, size_t len);
|
||||||
void keydata_free(struct keydata *blocks);
|
void keydata_free(struct keydata *blocks);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* domain.c */
|
||||||
|
char *get_domain(struct in_addr addr);
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
char *get_domain6(struct in6_addr *addr);
|
||||||
|
#endif
|
||||||
|
int is_name_synthetic(int flags, char *name, struct all_addr *addr);
|
||||||
|
int is_rev_synth(int flag, struct all_addr *addr, char *name);
|
||||||
|
|
||||||
/* rfc1035.c */
|
/* rfc1035.c */
|
||||||
unsigned int extract_request(struct dns_header *header, size_t qlen,
|
unsigned int extract_request(struct dns_header *header, size_t qlen,
|
||||||
char *name, unsigned short *typep);
|
char *name, unsigned short *typep);
|
||||||
|
|||||||
+200
@@ -0,0 +1,200 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000-2013 Simon Kelley
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
|
||||||
|
static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c);
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int is_name_synthetic(int flags, char *name, struct all_addr *addr)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
struct cond_domain *c = NULL;
|
||||||
|
int prot = AF_INET;
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (flags & F_IPV6)
|
||||||
|
prot = AF_INET6;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* NB, must not alter name if we return zero */
|
||||||
|
for (p = name; *p; p++)
|
||||||
|
{
|
||||||
|
char c = *p;
|
||||||
|
|
||||||
|
if ((c >='0' && c <= '9') || c == '-')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f')))
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p != '.')
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
for (p = name; *p; p++)
|
||||||
|
if (*p == '-')
|
||||||
|
{
|
||||||
|
if (prot == AF_INET)
|
||||||
|
*p = '.';
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else
|
||||||
|
*p = ':';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inet_pton(prot, name, addr))
|
||||||
|
for (c = daemon->synth_domains; c; c = c->next)
|
||||||
|
if (hostname_isequal(c->domain, p+1))
|
||||||
|
{
|
||||||
|
if (prot == AF_INET)
|
||||||
|
{
|
||||||
|
if (!c->is6 &&
|
||||||
|
ntohl(addr->addr.addr4.s_addr) >= ntohl(c->start.s_addr) &&
|
||||||
|
ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 addrpart = addr6part(&addr->addr.addr6);
|
||||||
|
|
||||||
|
if (c->is6 &&
|
||||||
|
is_same_net6(&addr->addr.addr6, &c->start6, 64) &&
|
||||||
|
addrpart >= addr6part(&c->start6) &&
|
||||||
|
addrpart <= addr6part(&c->end6))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restore name */
|
||||||
|
for (p = name; *p; p++)
|
||||||
|
if (*p == '.' || *p == ':')
|
||||||
|
*p = '-';
|
||||||
|
|
||||||
|
*p = '.';
|
||||||
|
|
||||||
|
return (c != NULL);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int is_rev_synth(int flag, struct all_addr *addr, char *name)
|
||||||
|
{
|
||||||
|
struct cond_domain *c;
|
||||||
|
|
||||||
|
if (flag & F_IPV4 && (c = search_domain(addr->addr.addr4, daemon->synth_domains)))
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
inet_ntop(AF_INET, &addr->addr.addr4, name, ADDRSTRLEN);
|
||||||
|
for (p = name; *p; p++)
|
||||||
|
if (*p == '.')
|
||||||
|
*p = '-';
|
||||||
|
|
||||||
|
strncat(name, ".", MAXDNAME);
|
||||||
|
strncat(name, c->domain, MAXDNAME);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (flag & F_IPV6 && (c = search_domain6(&addr->addr.addr6, daemon->synth_domains)))
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
inet_ntop(AF_INET6, &addr->addr.addr6, name, ADDRSTRLEN);
|
||||||
|
|
||||||
|
/* IPv6 presentation address can start with ":", but valid domain names
|
||||||
|
cannot start with "-" so prepend a zero in that case. */
|
||||||
|
if (*name == ':')
|
||||||
|
{
|
||||||
|
*name = '0';
|
||||||
|
inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (p = name; *p; p++)
|
||||||
|
if (*p == ':')
|
||||||
|
*p = '-';
|
||||||
|
|
||||||
|
strncat(name, ".", MAXDNAME);
|
||||||
|
strncat(name, c->domain, MAXDNAME);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c)
|
||||||
|
{
|
||||||
|
for (; c; c = c->next)
|
||||||
|
if (!c->is6 &&
|
||||||
|
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
|
||||||
|
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
|
||||||
|
return c;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *get_domain(struct in_addr addr)
|
||||||
|
{
|
||||||
|
struct cond_domain *c;
|
||||||
|
|
||||||
|
if ((c = search_domain(addr, daemon->cond_domain)))
|
||||||
|
return c->domain;
|
||||||
|
|
||||||
|
return daemon->domain_suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c)
|
||||||
|
{
|
||||||
|
u64 addrpart = addr6part(addr);
|
||||||
|
|
||||||
|
for (; c; c = c->next)
|
||||||
|
if (c->is6 &&
|
||||||
|
is_same_net6(addr, &c->start6, 64) &&
|
||||||
|
addrpart >= addr6part(&c->start6) &&
|
||||||
|
addrpart <= addr6part(&c->end6))
|
||||||
|
return c;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *get_domain6(struct in6_addr *addr)
|
||||||
|
{
|
||||||
|
struct cond_domain *c;
|
||||||
|
|
||||||
|
if ((c = search_domain6(addr, daemon->cond_domain)))
|
||||||
|
return c->domain;
|
||||||
|
|
||||||
|
return daemon->domain_suffix;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+19
-2
@@ -128,8 +128,9 @@ struct myoption {
|
|||||||
#define LOPT_AUTHSFS 317
|
#define LOPT_AUTHSFS 317
|
||||||
#define LOPT_AUTHPEER 318
|
#define LOPT_AUTHPEER 318
|
||||||
#define LOPT_IPSET 319
|
#define LOPT_IPSET 319
|
||||||
|
#define LOPT_SYNTH 320
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
#ifdef OPTION6_PREFIX_CLASS
|
||||||
#define LOPT_PREF_CLSS 320
|
#define LOPT_PREF_CLSS 321
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_GETOPT_LONG
|
#ifdef HAVE_GETOPT_LONG
|
||||||
@@ -264,6 +265,7 @@ static const struct myoption opts[] =
|
|||||||
{ "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
|
{ "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
|
||||||
{ "auth-peer", 1, 0, LOPT_AUTHPEER },
|
{ "auth-peer", 1, 0, LOPT_AUTHPEER },
|
||||||
{ "ipset", 1, 0, LOPT_IPSET },
|
{ "ipset", 1, 0, LOPT_IPSET },
|
||||||
|
{ "synth-domain", 1, 0, LOPT_SYNTH },
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
#ifdef OPTION6_PREFIX_CLASS
|
||||||
{ "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
|
{ "dhcp-prefix-class", 1, 0, LOPT_PREF_CLSS },
|
||||||
#endif
|
#endif
|
||||||
@@ -406,6 +408,7 @@ static struct {
|
|||||||
{ LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
|
{ LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
|
||||||
{ LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
|
{ LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
|
||||||
{ LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
|
{ LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
|
||||||
|
{ LOPT_SYNTH, ARG_DUP, "<domain>,<range>", gettext_noop("Specify a domain and address range for sythesised names"), NULL },
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
#ifdef OPTION6_PREFIX_CLASS
|
||||||
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
|
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
|
||||||
#endif
|
#endif
|
||||||
@@ -1688,6 +1691,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 's': /* --domain */
|
case 's': /* --domain */
|
||||||
|
case LOPT_SYNTH: /* --synth-domain */
|
||||||
if (strcmp (arg, "#") == 0)
|
if (strcmp (arg, "#") == 0)
|
||||||
set_option_bool(OPT_RESOLV_DOMAIN);
|
set_option_bool(OPT_RESOLV_DOMAIN);
|
||||||
else
|
else
|
||||||
@@ -1724,6 +1728,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
local=/xxx.yyy.zzz.in-addr.arpa/ */
|
local=/xxx.yyy.zzz.in-addr.arpa/ */
|
||||||
|
|
||||||
if (strcmp(arg, "local") != 0 ||
|
if (strcmp(arg, "local") != 0 ||
|
||||||
|
option != 's' ||
|
||||||
(msize != 8 && msize != 16 && msize != 24))
|
(msize != 8 && msize != 16 && msize != 24))
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
else
|
else
|
||||||
@@ -1779,7 +1784,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
local=/<domain>/
|
local=/<domain>/
|
||||||
local=/xxx.yyy.zzz.ip6.arpa/ */
|
local=/xxx.yyy.zzz.ip6.arpa/ */
|
||||||
|
|
||||||
if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
|
if (strcmp(arg, "local") != 0 ||
|
||||||
|
option != 's' ||
|
||||||
|
((msize & 4) != 0))
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1839,11 +1846,21 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
}
|
}
|
||||||
|
|
||||||
new->domain = d;
|
new->domain = d;
|
||||||
|
if (option == 's')
|
||||||
|
{
|
||||||
new->next = daemon->cond_domain;
|
new->next = daemon->cond_domain;
|
||||||
daemon->cond_domain = new;
|
daemon->cond_domain = new;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
new->next = daemon->synth_domains;
|
||||||
|
daemon->synth_domains = new;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (option == 's')
|
||||||
daemon->domain_suffix = d;
|
daemon->domain_suffix = d;
|
||||||
|
else
|
||||||
|
ret_err(gen_err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1517,6 +1517,19 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa)));
|
} while ((crecp = cache_find_by_addr(crecp, &addr, now, is_arpa)));
|
||||||
|
else if (is_rev_synth(is_arpa, &addr, name))
|
||||||
|
{
|
||||||
|
ans = 1;
|
||||||
|
if (!dryrun)
|
||||||
|
{
|
||||||
|
log_query(F_CONFIG | F_REVERSE | is_arpa, name, &addr, NULL);
|
||||||
|
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->local_ttl, NULL,
|
||||||
|
T_PTR, C_IN, "d", name))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (is_arpa == F_IPV4 &&
|
else if (is_arpa == F_IPV4 &&
|
||||||
option_bool(OPT_BOGUSPRIV) &&
|
option_bool(OPT_BOGUSPRIV) &&
|
||||||
private_net(addr.addr.addr4, 1))
|
private_net(addr.addr.addr4, 1))
|
||||||
@@ -1687,6 +1700,17 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
}
|
}
|
||||||
} while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
|
} while ((crecp = cache_find_by_name(crecp, name, now, flag | F_CNAME)));
|
||||||
}
|
}
|
||||||
|
else if (is_name_synthetic(flag, name, &addr))
|
||||||
|
{
|
||||||
|
ans = 1;
|
||||||
|
if (!dryrun)
|
||||||
|
{
|
||||||
|
log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL);
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
daemon->local_ttl, NULL, type, C_IN, type == T_A ? "4" : "6", &addr))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qtype == T_CNAME || qtype == T_ANY)
|
if (qtype == T_CNAME || qtype == T_ANY)
|
||||||
|
|||||||
+127
-113
@@ -39,6 +39,7 @@ static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt
|
|||||||
static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);
|
static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);
|
||||||
static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end);
|
static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end);
|
||||||
static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
|
static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
|
||||||
|
static int in_list(unsigned char *list, int opt);
|
||||||
static void do_options(struct dhcp_context *context,
|
static void do_options(struct dhcp_context *context,
|
||||||
struct dhcp_packet *mess,
|
struct dhcp_packet *mess,
|
||||||
unsigned char *real_end,
|
unsigned char *real_end,
|
||||||
@@ -355,6 +356,117 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
|
||||||
|
Otherwise assume the option is an array, and look for a matching element.
|
||||||
|
If no data given, existance of the option is enough. This code handles
|
||||||
|
rfc3925 V-I classes too. */
|
||||||
|
for (o = daemon->dhcp_match; o; o = o->next)
|
||||||
|
{
|
||||||
|
unsigned int len, elen, match = 0;
|
||||||
|
size_t offset, o2;
|
||||||
|
|
||||||
|
if (o->flags & DHOPT_RFC3925)
|
||||||
|
{
|
||||||
|
if (!(opt = option_find(mess, sz, OPTION_VENDOR_IDENT, 5)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5)
|
||||||
|
{
|
||||||
|
len = option_uint(opt, offset + 4 , 1);
|
||||||
|
/* Need to take care that bad data can't run us off the end of the packet */
|
||||||
|
if ((offset + len + 5 <= (option_len(opt))) &&
|
||||||
|
(option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
|
||||||
|
for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
|
||||||
|
{
|
||||||
|
elen = option_uint(opt, o2, 1);
|
||||||
|
if ((o2 + elen + 1 <= option_len(opt)) &&
|
||||||
|
(match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (match)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(opt = option_find(mess, sz, o->opt, 1)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
match = match_bytes(o, option_ptr(opt, 0), option_len(opt));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match)
|
||||||
|
{
|
||||||
|
o->netid->next = netid;
|
||||||
|
netid = o->netid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* user-class options are, according to RFC3004, supposed to contain
|
||||||
|
a set of counted strings. Here we check that this is so (by seeing
|
||||||
|
if the counts are consistent with the overall option length) and if
|
||||||
|
so zero the counts so that we don't get spurious matches between
|
||||||
|
the vendor string and the counts. If the lengths don't add up, we
|
||||||
|
assume that the option is a single string and non RFC3004 compliant
|
||||||
|
and just do the substring match. dhclient provides these broken options.
|
||||||
|
The code, later, which sends user-class data to the lease-change script
|
||||||
|
relies on the transformation done here.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
|
||||||
|
{
|
||||||
|
unsigned char *ucp = option_ptr(opt, 0);
|
||||||
|
int tmp, j;
|
||||||
|
for (j = 0; j < option_len(opt); j += ucp[j] + 1);
|
||||||
|
if (j == option_len(opt))
|
||||||
|
for (j = 0; j < option_len(opt); j = tmp)
|
||||||
|
{
|
||||||
|
tmp = j + ucp[j] + 1;
|
||||||
|
ucp[j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
|
||||||
|
{
|
||||||
|
int mopt;
|
||||||
|
|
||||||
|
if (vendor->match_type == MATCH_VENDOR)
|
||||||
|
mopt = OPTION_VENDOR_ID;
|
||||||
|
else if (vendor->match_type == MATCH_USER)
|
||||||
|
mopt = OPTION_USER_CLASS;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((opt = option_find(mess, sz, mopt, 1)))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i <= (option_len(opt) - vendor->len); i++)
|
||||||
|
if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)
|
||||||
|
{
|
||||||
|
vendor->netid.next = netid;
|
||||||
|
netid = &vendor->netid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mark vendor-encapsulated options which match the client-supplied vendor class,
|
||||||
|
save client-supplied vendor class */
|
||||||
|
if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
|
||||||
|
{
|
||||||
|
memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt));
|
||||||
|
vendor_class_len = option_len(opt);
|
||||||
|
}
|
||||||
|
match_vendor_opts(opt, daemon->dhcp_opts);
|
||||||
|
|
||||||
|
if (option_bool(OPT_LOG_OPTS))
|
||||||
|
{
|
||||||
|
if (sanitise(opt, daemon->namebuff))
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
|
||||||
|
if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff);
|
||||||
|
}
|
||||||
|
|
||||||
mess->op = BOOTREPLY;
|
mess->op = BOOTREPLY;
|
||||||
|
|
||||||
config = find_config(daemon->dhcp_conf, context, clid, clid_len,
|
config = find_config(daemon->dhcp_conf, context, clid, clid_len,
|
||||||
@@ -493,9 +605,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
lease_set_interface(lease, int_index, now);
|
lease_set_interface(lease, int_index, now);
|
||||||
|
|
||||||
clear_packet(mess, end);
|
clear_packet(mess, end);
|
||||||
match_vendor_opts(NULL, daemon->dhcp_opts); /* clear flags */
|
|
||||||
do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
|
do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
|
||||||
netid, subnet_addr, 0, 0, -1, NULL, 0, now);
|
netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,117 +733,6 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
|
|
||||||
Otherwise assume the option is an array, and look for a matching element.
|
|
||||||
If no data given, existance of the option is enough. This code handles
|
|
||||||
rfc3925 V-I classes too. */
|
|
||||||
for (o = daemon->dhcp_match; o; o = o->next)
|
|
||||||
{
|
|
||||||
unsigned int len, elen, match = 0;
|
|
||||||
size_t offset, o2;
|
|
||||||
|
|
||||||
if (o->flags & DHOPT_RFC3925)
|
|
||||||
{
|
|
||||||
if (!(opt = option_find(mess, sz, OPTION_VENDOR_IDENT, 5)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5)
|
|
||||||
{
|
|
||||||
len = option_uint(opt, offset + 4 , 1);
|
|
||||||
/* Need to take care that bad data can't run us off the end of the packet */
|
|
||||||
if ((offset + len + 5 <= (option_len(opt))) &&
|
|
||||||
(option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
|
|
||||||
for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
|
|
||||||
{
|
|
||||||
elen = option_uint(opt, o2, 1);
|
|
||||||
if ((o2 + elen + 1 <= option_len(opt)) &&
|
|
||||||
(match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (match)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!(opt = option_find(mess, sz, o->opt, 1)))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
match = match_bytes(o, option_ptr(opt, 0), option_len(opt));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match)
|
|
||||||
{
|
|
||||||
o->netid->next = netid;
|
|
||||||
netid = o->netid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* user-class options are, according to RFC3004, supposed to contain
|
|
||||||
a set of counted strings. Here we check that this is so (by seeing
|
|
||||||
if the counts are consistent with the overall option length) and if
|
|
||||||
so zero the counts so that we don't get spurious matches between
|
|
||||||
the vendor string and the counts. If the lengths don't add up, we
|
|
||||||
assume that the option is a single string and non RFC3004 compliant
|
|
||||||
and just do the substring match. dhclient provides these broken options.
|
|
||||||
The code, later, which sends user-class data to the lease-change script
|
|
||||||
relies on the transformation done here.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
|
|
||||||
{
|
|
||||||
unsigned char *ucp = option_ptr(opt, 0);
|
|
||||||
int tmp, j;
|
|
||||||
for (j = 0; j < option_len(opt); j += ucp[j] + 1);
|
|
||||||
if (j == option_len(opt))
|
|
||||||
for (j = 0; j < option_len(opt); j = tmp)
|
|
||||||
{
|
|
||||||
tmp = j + ucp[j] + 1;
|
|
||||||
ucp[j] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
|
|
||||||
{
|
|
||||||
int mopt;
|
|
||||||
|
|
||||||
if (vendor->match_type == MATCH_VENDOR)
|
|
||||||
mopt = OPTION_VENDOR_ID;
|
|
||||||
else if (vendor->match_type == MATCH_USER)
|
|
||||||
mopt = OPTION_USER_CLASS;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ((opt = option_find(mess, sz, mopt, 1)))
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = 0; i <= (option_len(opt) - vendor->len); i++)
|
|
||||||
if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)
|
|
||||||
{
|
|
||||||
vendor->netid.next = netid;
|
|
||||||
netid = &vendor->netid;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* mark vendor-encapsulated options which match the client-supplied vendor class,
|
|
||||||
save client-supplied vendor class */
|
|
||||||
if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
|
|
||||||
{
|
|
||||||
memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt));
|
|
||||||
vendor_class_len = option_len(opt);
|
|
||||||
}
|
|
||||||
match_vendor_opts(opt, daemon->dhcp_opts);
|
|
||||||
|
|
||||||
if (option_bool(OPT_LOG_OPTS))
|
|
||||||
{
|
|
||||||
if (sanitise(opt, daemon->namebuff))
|
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
|
|
||||||
if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))
|
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff);
|
|
||||||
}
|
|
||||||
|
|
||||||
tagif_netid = run_tag_if(netid);
|
tagif_netid = run_tag_if(netid);
|
||||||
|
|
||||||
/* if all the netids in the ignore list are present, ignore this client */
|
/* if all the netids in the ignore list are present, ignore this client */
|
||||||
@@ -1411,6 +1411,20 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
||||||
|
|
||||||
|
/* RFC 2131 says that DHCPINFORM shouldn't include lease-time parameters, but
|
||||||
|
we supply a utility which makes DHCPINFORM requests to get this information.
|
||||||
|
Only include lease time if OPTION_LEASE_TIME is in the parameter request list,
|
||||||
|
which won't be true for ordinary clients, but will be true for the
|
||||||
|
dhcp_lease_time utility. */
|
||||||
|
if (lease && in_list(req_options, OPTION_LEASE_TIME))
|
||||||
|
{
|
||||||
|
if (lease->expires == 0)
|
||||||
|
time = 0xffffffff;
|
||||||
|
else
|
||||||
|
time = (unsigned int)difftime(lease->expires, now);
|
||||||
|
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
||||||
|
}
|
||||||
|
|
||||||
do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
|
do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
|
||||||
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
|
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user