mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-09 16:20:55 +00:00
Compare commits
12
Commits
v2.67test2
...
v2.67test4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f2873d42c | ||
|
|
ab915f837c | ||
|
|
ddd9a6b499 | ||
|
|
7abb69b5dc | ||
|
|
d5052fb24f | ||
|
|
b5a7ff42bb | ||
|
|
48fd1c4dd6 | ||
|
|
2bb73af7d1 | ||
|
|
86e92f9983 | ||
|
|
1c10b9de11 | ||
|
|
a66d36ea11 | ||
|
|
aa63a21ce0 |
No files matched your search
@@ -3,6 +3,34 @@ 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.
|
||||||
|
|
||||||
|
Fix failure to compile ipset.c if old kernel headers are
|
||||||
|
in use. Thanks to Eugene Rudoy for pointing this out.
|
||||||
|
|
||||||
|
Handle IPv4 interface-address labels in Linux. These are
|
||||||
|
often used to emulate the old IP-alias addresses. Before,
|
||||||
|
using --interface=eth0 would service all the addresses of
|
||||||
|
eth0, including ones configured as aliases, which appear
|
||||||
|
in ifconfig as eth0:0. Now, only addresses with the label
|
||||||
|
eth0 are active. This is not backwards compatible: if you
|
||||||
|
want to continue to bind the aliases too, you need to add
|
||||||
|
eg. --interface=eth0:0 to the config.
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
|
|||||||
+25
-9
@@ -519,6 +519,22 @@ 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>[,<prefix>]
|
||||||
|
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,internal-
|
||||||
|
will result in a query for internal-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 if no prefix is
|
||||||
|
configured 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 +575,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 +779,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 +994,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 +1011,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 +1024,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 +1052,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 +1129,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 +1428,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 +1682,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
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
|
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
|
||||||
else
|
else
|
||||||
broadcast.s_addr = 0;
|
broadcast.s_addr = 0;
|
||||||
if (!((*callback)(addr, iface_index, netmask, broadcast, parm)))
|
if (!((*callback)(addr, iface_index, NULL, netmask, broadcast, parm)))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
|
|||||||
-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)
|
||||||
{
|
{
|
||||||
|
|||||||
+4
-4
@@ -279,12 +279,12 @@ HAVE_SOCKADDR_SA_LEN
|
|||||||
#if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY)
|
#if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY)
|
||||||
# define HAVE_IPV6
|
# define HAVE_IPV6
|
||||||
# define ADDRSTRLEN INET6_ADDRSTRLEN
|
# define ADDRSTRLEN INET6_ADDRSTRLEN
|
||||||
#elif defined(INET_ADDRSTRLEN)
|
#else
|
||||||
|
# if !defined(INET_ADDRSTRLEN)
|
||||||
|
# define INET_ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
|
||||||
|
# endif
|
||||||
# undef HAVE_IPV6
|
# undef HAVE_IPV6
|
||||||
# define ADDRSTRLEN INET_ADDRSTRLEN
|
# define ADDRSTRLEN INET_ADDRSTRLEN
|
||||||
#else
|
|
||||||
# undef HAVE_IPV6
|
|
||||||
# define ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+9
-5
@@ -28,9 +28,9 @@ struct match_param {
|
|||||||
struct in_addr netmask, broadcast, addr;
|
struct in_addr netmask, broadcast, addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int complete_context(struct in_addr local, int if_index,
|
static int complete_context(struct in_addr local, int if_index, char *label,
|
||||||
struct in_addr netmask, struct in_addr broadcast, void *vparam);
|
struct in_addr netmask, struct in_addr broadcast, void *vparam);
|
||||||
static int check_listen_addrs(struct in_addr local, int if_index,
|
static int check_listen_addrs(struct in_addr local, int if_index, char *label,
|
||||||
struct in_addr netmask, struct in_addr broadcast, void *vparam);
|
struct in_addr netmask, struct in_addr broadcast, void *vparam);
|
||||||
|
|
||||||
static int make_fd(int port)
|
static int make_fd(int port)
|
||||||
@@ -287,7 +287,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
iface_addr = match.addr;
|
iface_addr = match.addr;
|
||||||
/* make sure secondary address gets priority in case
|
/* make sure secondary address gets priority in case
|
||||||
there is more than one address on the interface in the same subnet */
|
there is more than one address on the interface in the same subnet */
|
||||||
complete_context(match.addr, iface_index, match.netmask, match.broadcast, &parm);
|
complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!iface_enumerate(AF_INET, &parm, complete_context))
|
if (!iface_enumerate(AF_INET, &parm, complete_context))
|
||||||
@@ -411,12 +411,14 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check against secondary interface addresses */
|
/* check against secondary interface addresses */
|
||||||
static int check_listen_addrs(struct in_addr local, int if_index,
|
static int check_listen_addrs(struct in_addr local, int if_index, char *label,
|
||||||
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||||
{
|
{
|
||||||
struct match_param *param = vparam;
|
struct match_param *param = vparam;
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
|
|
||||||
|
(void) label;
|
||||||
|
|
||||||
if (if_index == param->ind)
|
if (if_index == param->ind)
|
||||||
{
|
{
|
||||||
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
||||||
@@ -444,12 +446,14 @@ static int check_listen_addrs(struct in_addr local, int if_index,
|
|||||||
|
|
||||||
Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
|
Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
|
||||||
|
|
||||||
static int complete_context(struct in_addr local, int if_index,
|
static int complete_context(struct in_addr local, int if_index, char *label,
|
||||||
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||||
{
|
{
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
struct iface_param *param = vparam;
|
struct iface_param *param = vparam;
|
||||||
|
|
||||||
|
(void)label;
|
||||||
|
|
||||||
for (context = daemon->dhcp; context; context = context->next)
|
for (context = daemon->dhcp; context; context = context->next)
|
||||||
{
|
{
|
||||||
if (!(context->flags & CONTEXT_NETMASK) &&
|
if (!(context->flags & CONTEXT_NETMASK) &&
|
||||||
|
|||||||
+11
-6
@@ -673,7 +673,7 @@ struct dhcp_bridge {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct cond_domain {
|
struct cond_domain {
|
||||||
char *domain;
|
char *domain, *prefix;
|
||||||
struct in_addr start, end;
|
struct in_addr start, end;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
struct in6_addr start6, end6;
|
struct in6_addr start6, end6;
|
||||||
@@ -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);
|
||||||
@@ -1026,6 +1030,7 @@ void create_bound_listeners(int die);
|
|||||||
int is_dad_listeners(void);
|
int is_dad_listeners(void);
|
||||||
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
|
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
|
||||||
int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
|
int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
|
||||||
|
int label_exception(int index, int family, struct all_addr *addr);
|
||||||
int fix_fd(int fd);
|
int fix_fd(int fd);
|
||||||
int tcp_interface(int fd, int af);
|
int tcp_interface(int fd, int af);
|
||||||
struct in_addr get_ifaddr(char *intr);
|
struct in_addr get_ifaddr(char *intr);
|
||||||
|
|||||||
+232
@@ -0,0 +1,232 @@
|
|||||||
|
/* 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
|
||||||
|
|
||||||
|
for (c = daemon->synth_domains; c; c = c->next)
|
||||||
|
{
|
||||||
|
int found = 0;
|
||||||
|
char *tail, *pref;
|
||||||
|
|
||||||
|
for (tail = name, pref = c->prefix; *tail != 0 && pref && *pref != 0; tail++, pref++)
|
||||||
|
{
|
||||||
|
unsigned int c1 = (unsigned char) *pref;
|
||||||
|
unsigned int c2 = (unsigned char) *tail;
|
||||||
|
|
||||||
|
if (c1 >= 'A' && c1 <= 'Z')
|
||||||
|
c1 += 'a' - 'A';
|
||||||
|
if (c2 >= 'A' && c2 <= 'Z')
|
||||||
|
c2 += 'a' - 'A';
|
||||||
|
|
||||||
|
if (c1 != c2)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pref && *pref != 0)
|
||||||
|
continue; /* prefix match fail */
|
||||||
|
|
||||||
|
/* NB, must not alter name if we return zero */
|
||||||
|
for (p = tail; *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 != '.')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
/* swap . or : for - */
|
||||||
|
for (p = tail; *p; p++)
|
||||||
|
if (*p == '-')
|
||||||
|
{
|
||||||
|
if (prot == AF_INET)
|
||||||
|
*p = '.';
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else
|
||||||
|
*p = ':';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
|
||||||
|
{
|
||||||
|
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))
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
#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))
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restore name */
|
||||||
|
for (p = tail; *p; p++)
|
||||||
|
if (*p == '.' || *p == ':')
|
||||||
|
*p = '-';
|
||||||
|
|
||||||
|
*p = '.';
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
*name = 0;
|
||||||
|
if (c->prefix)
|
||||||
|
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
|
||||||
|
|
||||||
|
inet_ntop(AF_INET, &addr->addr.addr4, name + strlen(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;
|
||||||
|
|
||||||
|
*name = 0;
|
||||||
|
if (c->prefix)
|
||||||
|
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
|
||||||
|
|
||||||
|
inet_ntop(AF_INET6, &addr->addr.addr6, name + strlen(name), ADDRSTRLEN);
|
||||||
|
|
||||||
|
/* IPv6 presentation address can start with ":", but valid domain names
|
||||||
|
cannot start with "-" so prepend a zero in that case. */
|
||||||
|
if (!c->prefix && *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
|
||||||
+2
-1
@@ -789,7 +789,8 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
{
|
{
|
||||||
if (!option_bool(OPT_CLEVERBIND))
|
if (!option_bool(OPT_CLEVERBIND))
|
||||||
enumerate_interfaces();
|
enumerate_interfaces();
|
||||||
if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name))
|
if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
|
||||||
|
!label_exception(if_index, listen->family, &dst_addr))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+39
-15
@@ -26,9 +26,12 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/netfilter/nfnetlink.h>
|
|
||||||
#ifndef NFNL_SUBSYS_IPSET
|
/* We want to be able to compile against old header files
|
||||||
|
Kernel version is handled at run-time. */
|
||||||
|
|
||||||
#define NFNL_SUBSYS_IPSET 6
|
#define NFNL_SUBSYS_IPSET 6
|
||||||
|
|
||||||
#define IPSET_ATTR_DATA 7
|
#define IPSET_ATTR_DATA 7
|
||||||
#define IPSET_ATTR_IP 1
|
#define IPSET_ATTR_IP 1
|
||||||
#define IPSET_ATTR_IPADDR_IPV4 1
|
#define IPSET_ATTR_IPADDR_IPV4 1
|
||||||
@@ -39,10 +42,31 @@
|
|||||||
#define IPSET_CMD_DEL 10
|
#define IPSET_CMD_DEL 10
|
||||||
#define IPSET_MAXNAMELEN 32
|
#define IPSET_MAXNAMELEN 32
|
||||||
#define IPSET_PROTOCOL 6
|
#define IPSET_PROTOCOL 6
|
||||||
#else
|
|
||||||
#include <linux/netfilter/ipset/ip_set.h>
|
#ifndef NFNETLINK_V0
|
||||||
|
#define NFNETLINK_V0 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef NLA_F_NESTED
|
||||||
|
#define NLA_F_NESTED (1 << 15)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NLA_F_NET_BYTEORDER
|
||||||
|
#define NLA_F_NET_BYTEORDER (1 << 14)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct my_nlattr {
|
||||||
|
__u16 nla_len;
|
||||||
|
__u16 nla_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct my_nfgenmsg {
|
||||||
|
__u8 nfgen_family; /* AF_xxx */
|
||||||
|
__u8 version; /* nfnetlink version */
|
||||||
|
__be16 res_id; /* resource id */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* data structure size in here is fixed */
|
/* data structure size in here is fixed */
|
||||||
#define BUFF_SZ 256
|
#define BUFF_SZ 256
|
||||||
|
|
||||||
@@ -53,11 +77,11 @@ static char *buffer;
|
|||||||
|
|
||||||
static inline void add_attr(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
|
static inline void add_attr(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
|
||||||
{
|
{
|
||||||
struct nlattr *attr = (void *)nlh + NL_ALIGN(nlh->nlmsg_len);
|
struct my_nlattr *attr = (void *)nlh + NL_ALIGN(nlh->nlmsg_len);
|
||||||
uint16_t payload_len = NL_ALIGN(sizeof(struct nlattr)) + len;
|
uint16_t payload_len = NL_ALIGN(sizeof(struct my_nlattr)) + len;
|
||||||
attr->nla_type = type;
|
attr->nla_type = type;
|
||||||
attr->nla_len = payload_len;
|
attr->nla_len = payload_len;
|
||||||
memcpy((void *)attr + NL_ALIGN(sizeof(struct nlattr)), data, len);
|
memcpy((void *)attr + NL_ALIGN(sizeof(struct my_nlattr)), data, len);
|
||||||
nlh->nlmsg_len += NL_ALIGN(payload_len);
|
nlh->nlmsg_len += NL_ALIGN(payload_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,8 +117,8 @@ void ipset_init(void)
|
|||||||
static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr, int af, int remove)
|
static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr, int af, int remove)
|
||||||
{
|
{
|
||||||
struct nlmsghdr *nlh;
|
struct nlmsghdr *nlh;
|
||||||
struct nfgenmsg *nfg;
|
struct my_nfgenmsg *nfg;
|
||||||
struct nlattr *nested[2];
|
struct my_nlattr *nested[2];
|
||||||
uint8_t proto;
|
uint8_t proto;
|
||||||
int addrsz = INADDRSZ;
|
int addrsz = INADDRSZ;
|
||||||
ssize_t rc;
|
ssize_t rc;
|
||||||
@@ -117,8 +141,8 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
|||||||
nlh->nlmsg_type = (remove ? IPSET_CMD_DEL : IPSET_CMD_ADD) | (NFNL_SUBSYS_IPSET << 8);
|
nlh->nlmsg_type = (remove ? IPSET_CMD_DEL : IPSET_CMD_ADD) | (NFNL_SUBSYS_IPSET << 8);
|
||||||
nlh->nlmsg_flags = NLM_F_REQUEST;
|
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||||
|
|
||||||
nfg = (struct nfgenmsg *)(buffer + nlh->nlmsg_len);
|
nfg = (struct my_nfgenmsg *)(buffer + nlh->nlmsg_len);
|
||||||
nlh->nlmsg_len += NL_ALIGN(sizeof(struct nfgenmsg));
|
nlh->nlmsg_len += NL_ALIGN(sizeof(struct my_nfgenmsg));
|
||||||
nfg->nfgen_family = af;
|
nfg->nfgen_family = af;
|
||||||
nfg->version = NFNETLINK_V0;
|
nfg->version = NFNETLINK_V0;
|
||||||
nfg->res_id = htons(0);
|
nfg->res_id = htons(0);
|
||||||
@@ -126,11 +150,11 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
|||||||
proto = IPSET_PROTOCOL;
|
proto = IPSET_PROTOCOL;
|
||||||
add_attr(nlh, IPSET_ATTR_PROTOCOL, sizeof(proto), &proto);
|
add_attr(nlh, IPSET_ATTR_PROTOCOL, sizeof(proto), &proto);
|
||||||
add_attr(nlh, IPSET_ATTR_SETNAME, strlen(setname) + 1, setname);
|
add_attr(nlh, IPSET_ATTR_SETNAME, strlen(setname) + 1, setname);
|
||||||
nested[0] = (struct nlattr *)(buffer + NL_ALIGN(nlh->nlmsg_len));
|
nested[0] = (struct my_nlattr *)(buffer + NL_ALIGN(nlh->nlmsg_len));
|
||||||
nlh->nlmsg_len += NL_ALIGN(sizeof(struct nlattr));
|
nlh->nlmsg_len += NL_ALIGN(sizeof(struct my_nlattr));
|
||||||
nested[0]->nla_type = NLA_F_NESTED | IPSET_ATTR_DATA;
|
nested[0]->nla_type = NLA_F_NESTED | IPSET_ATTR_DATA;
|
||||||
nested[1] = (struct nlattr *)(buffer + NL_ALIGN(nlh->nlmsg_len));
|
nested[1] = (struct my_nlattr *)(buffer + NL_ALIGN(nlh->nlmsg_len));
|
||||||
nlh->nlmsg_len += NL_ALIGN(sizeof(struct nlattr));
|
nlh->nlmsg_len += NL_ALIGN(sizeof(struct my_nlattr));
|
||||||
nested[1]->nla_type = NLA_F_NESTED | IPSET_ATTR_IP;
|
nested[1]->nla_type = NLA_F_NESTED | IPSET_ATTR_IP;
|
||||||
add_attr(nlh,
|
add_attr(nlh,
|
||||||
(af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) | NLA_F_NET_BYTEORDER,
|
(af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) | NLA_F_NET_BYTEORDER,
|
||||||
|
|||||||
+2
-1
@@ -345,11 +345,12 @@ void lease_update_file(time_t now)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int find_interface_v4(struct in_addr local, int if_index,
|
static int find_interface_v4(struct in_addr local, int if_index, char *label,
|
||||||
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
|
|
||||||
|
(void) label;
|
||||||
(void) broadcast;
|
(void) broadcast;
|
||||||
(void) vparam;
|
(void) vparam;
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -215,6 +215,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
if (ifa->ifa_family == AF_INET)
|
if (ifa->ifa_family == AF_INET)
|
||||||
{
|
{
|
||||||
struct in_addr netmask, addr, broadcast;
|
struct in_addr netmask, addr, broadcast;
|
||||||
|
char *label = NULL;
|
||||||
|
|
||||||
netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen));
|
netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen));
|
||||||
addr.s_addr = 0;
|
addr.s_addr = 0;
|
||||||
@@ -226,12 +227,14 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
addr = *((struct in_addr *)(rta+1));
|
addr = *((struct in_addr *)(rta+1));
|
||||||
else if (rta->rta_type == IFA_BROADCAST)
|
else if (rta->rta_type == IFA_BROADCAST)
|
||||||
broadcast = *((struct in_addr *)(rta+1));
|
broadcast = *((struct in_addr *)(rta+1));
|
||||||
|
else if (rta->rta_type == IFA_LABEL)
|
||||||
|
label = RTA_DATA(rta);
|
||||||
|
|
||||||
rta = RTA_NEXT(rta, len1);
|
rta = RTA_NEXT(rta, len1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr.s_addr && callback_ok)
|
if (addr.s_addr && callback_ok)
|
||||||
if (!((*callback)(addr, ifa->ifa_index, netmask, broadcast, parm)))
|
if (!((*callback)(addr, ifa->ifa_index, label, netmask, broadcast, parm)))
|
||||||
callback_ok = 0;
|
callback_ok = 0;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
|
|||||||
+30
-7
@@ -204,7 +204,27 @@ int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iface_allowed(struct irec **irecp, int if_index,
|
/* If we're configured with something like --interface=eth0:0 then we'll listen correctly
|
||||||
|
on the relevant address, but the name of the arrival interface, derived from the
|
||||||
|
index won't match the config. Check that we found an interface address for the arrival
|
||||||
|
interface: daemon->interfaces must be up-to-date. */
|
||||||
|
int label_exception(int index, int family, struct all_addr *addr)
|
||||||
|
{
|
||||||
|
struct irec *iface;
|
||||||
|
|
||||||
|
/* labels only supported on IPv4 addresses. */
|
||||||
|
if (family != AF_INET)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||||
|
if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
|
||||||
|
iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iface_allowed(struct irec **irecp, int if_index, char *label,
|
||||||
union mysockaddr *addr, struct in_addr netmask, int dad)
|
union mysockaddr *addr, struct in_addr netmask, int dad)
|
||||||
{
|
{
|
||||||
struct irec *iface;
|
struct irec *iface;
|
||||||
@@ -242,7 +262,7 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
loopback = ifr.ifr_flags & IFF_LOOPBACK;
|
loopback = ifr.ifr_flags & IFF_LOOPBACK;
|
||||||
|
|
||||||
if (loopback)
|
if (loopback)
|
||||||
dhcp_ok = 0;
|
dhcp_ok = 0;
|
||||||
|
|
||||||
if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
|
if (ioctl(fd, SIOCGIFMTU, &ifr) != -1)
|
||||||
mtu = ifr.ifr_mtu;
|
mtu = ifr.ifr_mtu;
|
||||||
@@ -272,13 +292,16 @@ static int iface_allowed(struct irec **irecp, int if_index,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!label)
|
||||||
|
label = ifr.ifr_name;
|
||||||
|
|
||||||
if (addr->sa.sa_family == AF_INET &&
|
if (addr->sa.sa_family == AF_INET &&
|
||||||
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, ifr.ifr_name, &auth_dns))
|
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (addr->sa.sa_family == AF_INET6 &&
|
if (addr->sa.sa_family == AF_INET6 &&
|
||||||
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, ifr.ifr_name, &auth_dns))
|
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -348,11 +371,11 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
|||||||
addr.in6.sin6_port = htons(daemon->port);
|
addr.in6.sin6_port = htons(daemon->port);
|
||||||
addr.in6.sin6_scope_id = if_index;
|
addr.in6.sin6_scope_id = if_index;
|
||||||
|
|
||||||
return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, !!(flags & IFACE_TENTATIVE));
|
return iface_allowed((struct irec **)vparam, if_index, NULL, &addr, netmask, !!(flags & IFACE_TENTATIVE));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int iface_allowed_v4(struct in_addr local, int if_index,
|
static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
|
||||||
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||||
{
|
{
|
||||||
union mysockaddr addr;
|
union mysockaddr addr;
|
||||||
@@ -366,7 +389,7 @@ static int iface_allowed_v4(struct in_addr local, int if_index,
|
|||||||
addr.in.sin_addr = local;
|
addr.in.sin_addr = local;
|
||||||
addr.in.sin_port = htons(daemon->port);
|
addr.in.sin_port = htons(daemon->port);
|
||||||
|
|
||||||
return iface_allowed((struct irec **)vparam, if_index, &addr, netmask, 0);
|
return iface_allowed((struct irec **)vparam, if_index, label, &addr, netmask, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int enumerate_interfaces(void)
|
int enumerate_interfaces(void)
|
||||||
|
|||||||
+66
-40
@@ -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>,[<prefix>]", 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
|
||||||
@@ -657,7 +660,7 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
|||||||
scope_id = split_chr(arg, '%');
|
scope_id = split_chr(arg, '%');
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((addr->in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t) -1)
|
if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
|
||||||
{
|
{
|
||||||
addr->in.sin_port = htons(serv_port);
|
addr->in.sin_port = htons(serv_port);
|
||||||
addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;
|
addr->sa.sa_family = source_addr->sa.sa_family = AF_INET;
|
||||||
@@ -672,7 +675,7 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
|||||||
if (flags)
|
if (flags)
|
||||||
*flags |= SERV_HAS_SOURCE;
|
*flags |= SERV_HAS_SOURCE;
|
||||||
source_addr->in.sin_port = htons(source_port);
|
source_addr->in.sin_port = htons(source_port);
|
||||||
if ((source_addr->in.sin_addr.s_addr = inet_addr(source)) == (in_addr_t) -1)
|
if (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
|
||||||
{
|
{
|
||||||
#if defined(SO_BINDTODEVICE)
|
#if defined(SO_BINDTODEVICE)
|
||||||
source_addr->in.sin_addr.s_addr = INADDR_ANY;
|
source_addr->in.sin_addr.s_addr = INADDR_ANY;
|
||||||
@@ -1028,7 +1031,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|||||||
cp = comma;
|
cp = comma;
|
||||||
comma = split(cp);
|
comma = split(cp);
|
||||||
slash = split_chr(cp, '/');
|
slash = split_chr(cp, '/');
|
||||||
in.s_addr = inet_addr(cp);
|
inet_pton(AF_INET, cp, &in);
|
||||||
if (!slash)
|
if (!slash)
|
||||||
{
|
{
|
||||||
memcpy(op, &in, INADDRSZ);
|
memcpy(op, &in, INADDRSZ);
|
||||||
@@ -1573,7 +1576,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
comma = split(arg);
|
comma = split(arg);
|
||||||
new->name = NULL;
|
new->name = NULL;
|
||||||
unhide_metas(arg);
|
unhide_metas(arg);
|
||||||
if ((new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
|
if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)
|
||||||
new->addr.sa.sa_family = AF_INET;
|
new->addr.sa.sa_family = AF_INET;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
|
else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
|
||||||
@@ -1687,7 +1690,8 @@ 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
|
||||||
@@ -1703,6 +1707,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
|
struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
|
||||||
char *netpart;
|
char *netpart;
|
||||||
|
|
||||||
|
new->prefix = NULL;
|
||||||
|
|
||||||
unhide_metas(comma);
|
unhide_metas(comma);
|
||||||
if ((netpart = split_chr(comma, '/')))
|
if ((netpart = split_chr(comma, '/')))
|
||||||
{
|
{
|
||||||
@@ -1719,15 +1725,20 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
new->end.s_addr = new->start.s_addr | htonl(mask);
|
new->end.s_addr = new->start.s_addr | htonl(mask);
|
||||||
if (arg)
|
if (arg)
|
||||||
{
|
{
|
||||||
/* generate the equivalent of
|
if (option != 's')
|
||||||
local=/<domain>/
|
{
|
||||||
local=/xxx.yyy.zzz.in-addr.arpa/ */
|
if (!(new->prefix = canonicalise_opt(arg)) ||
|
||||||
|
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
|
||||||
if (strcmp(arg, "local") != 0 ||
|
ret_err(_("bad prefix"));
|
||||||
(msize != 8 && msize != 16 && msize != 24))
|
}
|
||||||
|
else if (strcmp(arg, "local") != 0 ||
|
||||||
|
(msize != 8 && msize != 16 && msize != 24))
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* generate the equivalent of
|
||||||
|
local=/<domain>/
|
||||||
|
local=/xxx.yyy.zzz.in-addr.arpa/ */
|
||||||
struct server *serv = opt_malloc(sizeof(struct server));
|
struct server *serv = opt_malloc(sizeof(struct server));
|
||||||
in_addr_t a = ntohl(new->start.s_addr) >> 8;
|
in_addr_t a = ntohl(new->start.s_addr) >> 8;
|
||||||
char *p;
|
char *p;
|
||||||
@@ -1775,14 +1786,19 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
else if (arg)
|
else if (arg)
|
||||||
{
|
{
|
||||||
/* generate the equivalent of
|
if (option != 's')
|
||||||
local=/<domain>/
|
{
|
||||||
local=/xxx.yyy.zzz.ip6.arpa/ */
|
if (!(new->prefix = canonicalise_opt(arg)) ||
|
||||||
|
strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
|
||||||
if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
|
ret_err(_("bad prefix"));
|
||||||
|
}
|
||||||
|
else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* generate the equivalent of
|
||||||
|
local=/<domain>/
|
||||||
|
local=/xxx.yyy.zzz.ip6.arpa/ */
|
||||||
struct server *serv = opt_malloc(sizeof(struct server));
|
struct server *serv = opt_malloc(sizeof(struct server));
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
@@ -1839,11 +1855,21 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
}
|
}
|
||||||
|
|
||||||
new->domain = d;
|
new->domain = d;
|
||||||
new->next = daemon->cond_domain;
|
if (option == 's')
|
||||||
daemon->cond_domain = new;
|
{
|
||||||
|
new->next = daemon->cond_domain;
|
||||||
|
daemon->cond_domain = new;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
new->next = daemon->synth_domains;
|
||||||
|
daemon->synth_domains = new;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (option == 's')
|
||||||
daemon->domain_suffix = d;
|
daemon->domain_suffix = d;
|
||||||
|
else
|
||||||
|
ret_err(gen_err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1901,7 +1927,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
{
|
{
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
unhide_metas(arg);
|
unhide_metas(arg);
|
||||||
if (arg && (addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
|
if (arg && (inet_pton(AF_INET, arg, &addr) > 0))
|
||||||
{
|
{
|
||||||
struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
|
struct bogus_addr *baddr = opt_malloc(sizeof(struct bogus_addr));
|
||||||
baddr->next = daemon->bogus_addr;
|
baddr->next = daemon->bogus_addr;
|
||||||
@@ -1919,7 +1945,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
struct iname *new = opt_malloc(sizeof(struct iname));
|
struct iname *new = opt_malloc(sizeof(struct iname));
|
||||||
comma = split(arg);
|
comma = split(arg);
|
||||||
unhide_metas(arg);
|
unhide_metas(arg);
|
||||||
if (arg && (new->addr.in.sin_addr.s_addr = inet_addr(arg)) != (in_addr_t)-1)
|
if (arg && (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0))
|
||||||
{
|
{
|
||||||
new->addr.sa.sa_family = AF_INET;
|
new->addr.sa.sa_family = AF_INET;
|
||||||
new->addr.in.sin_port = 0;
|
new->addr.in.sin_port = 0;
|
||||||
@@ -2343,7 +2369,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (k >= 3 && strchr(a[2], '.') &&
|
if (k >= 3 && strchr(a[2], '.') &&
|
||||||
((new->netmask.s_addr = inet_addr(a[2])) != (in_addr_t)-1))
|
(inet_pton(AF_INET, a[2], &new->netmask) > 0))
|
||||||
{
|
{
|
||||||
new->flags |= CONTEXT_NETMASK;
|
new->flags |= CONTEXT_NETMASK;
|
||||||
leasepos = 3;
|
leasepos = 3;
|
||||||
@@ -2352,7 +2378,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (k >= 4 && strchr(a[3], '.') &&
|
if (k >= 4 && strchr(a[3], '.') &&
|
||||||
((new->broadcast.s_addr = inet_addr(a[3])) != (in_addr_t)-1))
|
(inet_pton(AF_INET, a[3], &new->broadcast) > 0))
|
||||||
{
|
{
|
||||||
new->flags |= CONTEXT_BRDCAST;
|
new->flags |= CONTEXT_BRDCAST;
|
||||||
leasepos = 4;
|
leasepos = 4;
|
||||||
@@ -2582,7 +2608,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strchr(a[j], '.') && (in.s_addr = inet_addr(a[j])) != (in_addr_t)-1)
|
else if (strchr(a[j], '.') && (inet_pton(AF_INET, a[j], &in) > 0))
|
||||||
{
|
{
|
||||||
struct dhcp_config *configs;
|
struct dhcp_config *configs;
|
||||||
|
|
||||||
@@ -2779,17 +2805,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
if (comma)
|
if (comma)
|
||||||
{
|
{
|
||||||
unhide_metas(comma);
|
unhide_metas(comma);
|
||||||
if ((dhcp_next_server.s_addr = inet_addr(comma)) == (in_addr_t)-1) {
|
if (!(inet_pton(AF_INET, comma, &dhcp_next_server) > 0))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The user may have specified the tftp hostname here.
|
||||||
|
* save it so that it can be resolved/looked up during
|
||||||
|
* actual dhcp_reply().
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
tftp_sname = opt_string_alloc(comma);
|
||||||
* The user may have specified the tftp hostname here.
|
dhcp_next_server.s_addr = 0;
|
||||||
* save it so that it can be resolved/looked up during
|
}
|
||||||
* actual dhcp_reply().
|
|
||||||
*/
|
|
||||||
|
|
||||||
tftp_sname = opt_string_alloc(comma);
|
|
||||||
dhcp_next_server.s_addr = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3118,7 +3144,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
while (arg) {
|
while (arg) {
|
||||||
struct addr_list *new = opt_malloc(sizeof(struct addr_list));
|
struct addr_list *new = opt_malloc(sizeof(struct addr_list));
|
||||||
comma = split(arg);
|
comma = split(arg);
|
||||||
if ((new->addr.s_addr = inet_addr(arg)) == (in_addr_t)-1)
|
if (!(inet_pton(AF_INET, arg, &new->addr) > 0))
|
||||||
ret_err(_("bad dhcp-proxy address"));
|
ret_err(_("bad dhcp-proxy address"));
|
||||||
new->next = daemon->override_relays;
|
new->next = daemon->override_relays;
|
||||||
daemon->override_relays = new;
|
daemon->override_relays = new;
|
||||||
@@ -3161,15 +3187,15 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
dash = split_chr(a[0], '-');
|
dash = split_chr(a[0], '-');
|
||||||
|
|
||||||
if ((k < 2) ||
|
if ((k < 2) ||
|
||||||
((new->in.s_addr = inet_addr(a[0])) == (in_addr_t)-1) ||
|
(!(inet_pton(AF_INET, a[0], &new->in) > 0)) ||
|
||||||
((new->out.s_addr = inet_addr(a[1])) == (in_addr_t)-1))
|
(!(inet_pton(AF_INET, a[1], &new->out) > 0)))
|
||||||
option = '?';
|
option = '?';
|
||||||
|
|
||||||
if (k == 3)
|
if (k == 3)
|
||||||
new->mask.s_addr = inet_addr(a[2]);
|
inet_pton(AF_INET, a[2], &new->mask);
|
||||||
|
|
||||||
if (dash &&
|
if (dash &&
|
||||||
((new->end.s_addr = inet_addr(dash)) == (in_addr_t)-1 ||
|
(!(inet_pton(AF_INET, dash, &new->end) > 0) ||
|
||||||
!is_same_net(new->in, new->end, new->mask) ||
|
!is_same_net(new->in, new->end, new->mask) ||
|
||||||
ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
|
ntohl(new->in.s_addr) > ntohl(new->end.s_addr)))
|
||||||
ret_err(_("invalid alias range"));
|
ret_err(_("invalid alias range"));
|
||||||
|
|||||||
+2
-2
@@ -300,9 +300,9 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!done_dns)
|
if (daemon->port == NAMESERVER_PORT && !done_dns)
|
||||||
{
|
{
|
||||||
/* default == us. */
|
/* default == us, as long as we are supplying DNS service. */
|
||||||
put_opt6_char(ICMP6_OPT_RDNSS);
|
put_opt6_char(ICMP6_OPT_RDNSS);
|
||||||
put_opt6_char(3);
|
put_opt6_char(3);
|
||||||
put_opt6_short(0);
|
put_opt6_short(0);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -202,7 +202,8 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
{
|
{
|
||||||
if (!option_bool(OPT_CLEVERBIND))
|
if (!option_bool(OPT_CLEVERBIND))
|
||||||
enumerate_interfaces();
|
enumerate_interfaces();
|
||||||
if (!loopback_exception(listen->tftpfd, listen->family, &addra, name))
|
if (!loopback_exception(listen->tftpfd, listen->family, &addra, name) &&
|
||||||
|
!label_exception(if_index, listen->family, &addra) )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-4
@@ -142,17 +142,21 @@ static int check_name(char *in)
|
|||||||
int legal_hostname(char *name)
|
int legal_hostname(char *name)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
|
int first;
|
||||||
|
|
||||||
if (!check_name(name))
|
if (!check_name(name))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (; (c = *name); name++)
|
for (first = 1; (c = *name); name++, first = 0)
|
||||||
/* check for legal char a-z A-Z 0-9 - _ . */
|
/* check for legal char a-z A-Z 0-9 - _ . */
|
||||||
{
|
{
|
||||||
if ((c >= 'A' && c <= 'Z') ||
|
if ((c >= 'A' && c <= 'Z') ||
|
||||||
(c >= 'a' && c <= 'z') ||
|
(c >= 'a' && c <= 'z'))
|
||||||
(c >= '0' && c <= '9') ||
|
continue;
|
||||||
c == '-' || c == '_')
|
|
||||||
|
if (!first &&
|
||||||
|
((c >= '0' && c <= '9') ||
|
||||||
|
c == '-' || c == '_'))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* end of hostname part */
|
/* end of hostname part */
|
||||||
|
|||||||
Reference in new issue
Block a user