Compare commits

..
33 Commits
Author SHA1 Message Date
Geert Stappers via Dnsmasq-discuss a42ee397f3 Man page BNF error fix.
Move dhcp-range bracket indicating option.

There should already be an end-address or mode  when adding a netmask.

Also the date bumped.

Signed-off-by: Geert Stappers <stappers@stappers.nl>
2021-08-25 14:32:43 +01:00
Simon Kelley e58f8bb8c1 Merge message changes into I18N files. 2021-08-25 14:11:42 +01:00
Dominik DL6ER 58cf958e41 Fix empty domain in server option parsing when more than one domain is given
Signed-off-by: DL6ER <dl6er@dl6er.de>
2021-08-25 14:09:40 +01:00
Etan Kissling 06d01f7ae4 Make comment style consistent.
Majority of code base does not use C90-style // end of line comments.
This formats the few existing exceptions using /* */ for consistency.
2021-08-12 17:02:45 +01:00
Etan Kissling 1a33eec0ba Adjust logging levels for connmark patterns.
This brings the log levels emitted by connmark pattern code in line with
the rest of the code base. LOG_DEBUG is used for diagnostics that may be
verbose depending on the request patterns. LOG_ERR is used for problems
with the implementation itself.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-12 17:02:24 +01:00
Etan Kissling 82de7a1e96 Re-order UBus teardown logic.
When destroying the UBus context, private fields of our ubus_object were
being reset to 0 while UBus was still owning those objects. While this
seems to work out fine, it seems cleaner to first release the object so
that UBus no longer owns it, before proceding to reset those fields.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-12 17:02:07 +01:00
Etan Kissling 8e9bde57c5 Eliminate redundant UBus notify variable.
There was a `notify` variable to keep track whether a subscriber is
observing our UBus object. However, it was not properly cleaned up in
`ubus_destroy`, potentially becoming stale over UBus reconnections.
The variable was removed and the current state is examined when sending
notifications, similarly as is done in other existing OpenWrt code.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-12 17:01:17 +01:00
Etan Kissling 1bb70e08be Handle UBus serialization errors.
The various blob / blobmsg commands can fail, e.g., when memory is low.
Previously, those errors were silently discarded. This patch adds checks
for the error conditions, logging them and exiting from the functions.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-12 17:00:18 +01:00
Simon Kelley 9afcb7ae61 Revert "There was a notify variable to keep track whether a subscriber is"
This reverts commit ea43234c86.
2021-08-12 17:00:10 +01:00
Simon Kelley 545c4955e6 Revert "Re-order UBus teardown logic."
This reverts commit d387f8f06c.
2021-08-12 16:58:30 +01:00
Simon Kelley 2f2d59b35c Define order of reading files when --addn-hosts given a directory.
Also applies to --dhcp-hostsfile and --dhcp-optsfile though it is
less useful there.
2021-08-12 16:48:54 +01:00
Simon Kelley a1729deed3 Fiz sizeof() confusion in 527c3c7d0d 2021-08-11 09:10:39 +01:00
Simon Kelley fc64b97cd5 dhcp_buff2 not availble in log_packet, use daemon->addrbuff 2021-08-10 23:54:13 +01:00
Simon Kelley daddc8cb80 Merge branch 'master' of ssh://thekelleys.org.uk/var/local/git/dnsmasq 2021-08-10 23:15:46 +01:00
Petr Menšík 527c3c7d0d Remove remaining uses of deprecated inet_ntoa() 2021-08-10 22:50:33 +01:00
Petr Menšík fcb4dcaf7c Remove remaining uses of deprecated inet_addr() function. 2021-08-10 22:21:01 +01:00
Matthias Andree 3ca4995d34 CHANGELOG: spell-check 2021-08-10 21:40:06 +01:00
Etan Kissling d387f8f06c Re-order UBus teardown logic.
When destroying the UBus context, private fields of our ubus_object were
being reset to 0 while UBus was still owning those objects. While this
seems to work out fine, it seems cleaner to first release the object so
that UBus no longer owns it, before proceding to reset those fields.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-10 21:16:03 +01:00
Etan Kissling ea43234c86 There was a notify variable to keep track whether a subscriber is
observing our UBus object. However, it was not properly cleaned up in
`ubus_destroy`, potentially becoming stale over UBus reconnections.
The variable was removed and the current state is examined when sending
notifications, similarly as is done in other existing OpenWrt code.

Signed-off-by: Etan Kissling <etan.kissling@gmail.com>
2021-08-10 21:15:09 +01:00
Simon Kelley 867e56a45e Fix NOERR/NXDOMAIN in answers configured by --domain-needed. 2021-08-10 13:00:23 +01:00
Simon Kelley a163c63787 CONNTRACK needs CAP_NET_ADMIN. 2021-08-05 23:40:04 +01:00
Simon Kelley 8389b943d3 Better fix than f2266d9678 2021-07-21 21:27:14 +01:00
Simon Kelley f2266d9678 Add UINT32_MAX if not defined by system. 2021-07-21 00:23:28 +01:00
Simon Kelley 56bd806978 Typo in new EDE code. 2021-07-21 00:15:58 +01:00
Simon Kelley ac7eeea44d Handle empty hostmaster in --auth-soa
Spotted by Max Julian Hofmann and the Advanced Research Team at CrowdStrike
2021-07-21 00:15:15 +01:00
Simon Kelley b741059549 Detect malformed --dhcp-relay option.
Spotted by Max Julian Hofmann and the Advanced Research Team at CrowdStrike
2021-07-20 23:49:38 +01:00
Simon Kelley cbd984287f Fix argument checking for --dhcp-match.
Spotted by Max Julian Hofmann and the Advanced Research Team at CrowdStrike
2021-07-20 23:45:36 +01:00
Simon Kelley 32e15c3f45 canonicalise_opt must always return heap memory.
Thanks to Max Julian Hofmann for spotting this.
2021-07-20 23:22:37 +01:00
Simon Kelley f0dc324e35 Checks on prefix-length in --domain --synth-domain and --rev-server. 2021-07-20 23:15:28 +01:00
Simon Kelley f83c6cf51a Return REFUSED in auth mode when we are not authoritative for the query. 2021-07-20 17:15:36 +01:00
Simon Kelley c068b3ae2f --synth-domain now works in auth mode. 2021-07-19 09:38:48 +01:00
Simon Kelley adf9dec1e6 Allow shorter IPv6 prefix lengths in (some) --synth-domain options. 2021-07-18 18:18:56 +01:00
Kevin Darbyshire-Bryant 767d9cbd96 Add --quiet-tftp. 2021-07-09 22:48:49 +01:00
29 changed files with 7469 additions and 5689 deletions

No files matched your search

+18 -2
View File
@@ -1,6 +1,6 @@
version 2.86 version 2.86
Handle DHCPREBIND requests in the DHCPv6 server code. Handle DHCPREBIND requests in the DHCPv6 server code.
Thanks to Aichun Li for spotting this ommision, and the initial Thanks to Aichun Li for spotting this omission, and the initial
patch. patch.
Fix bug which caused dnsmasq to lose track of processes forked Fix bug which caused dnsmasq to lose track of processes forked
@@ -33,7 +33,7 @@ version 2.86
address=/example.com/1.2.3.4 address=/example.com/1.2.3.4
address=/example.com/5.6.7.8 address=/example.com/5.6.7.8
It also handles multiple upstream servers for a domain better; using It also handles multiple upstream servers for a domain better; using
the same try/retry alogrithms as non domain-specific servers. This the same try/retry algorithms as non domain-specific servers. This
also applies to DNSSEC-generated queries. also applies to DNSSEC-generated queries.
Finally, some of the oldest and gnarliest code in dnsmasq has had Finally, some of the oldest and gnarliest code in dnsmasq has had
a significant clean-up. It's far from perfect, but it _is_ better. a significant clean-up. It's far from perfect, but it _is_ better.
@@ -76,6 +76,22 @@ version 2.86
Disallowed queries are not forwarded; they are rejected Disallowed queries are not forwarded; they are rejected
with a REFUSED error code. with a REFUSED error code.
Allow smaller than 64 prefix lengths in synth-domain, with caveats.
--synth-domain=1234:4567::/56,example.com is now valid.
Make domains generated by --synth-domain appear in replies
when in authoritative mode.
Ensure CAP_NET_ADMIN capability is available when
conntrack is configured. Thanks to Yick Xie for spotting
the lack of this.
When --dhcp-hostsfile --dhcp-optsfile and --addn-hosts are
given a directory as argument, define the order in which
files within that directory are read (alphabetical order
of filename). Thanks to Ed Wildgoose for the initial patch
and motivation for this.
version 2.85 version 2.85
Fix problem with DNS retries in 2.83/2.84. Fix problem with DNS retries in 2.83/2.84.
+6 -2
View File
@@ -153,7 +153,11 @@ int main(int argc, char **argv)
exit(1); exit(1);
} }
lease.s_addr = inet_addr(argv[1]); if (inet_pton(AF_INET, argv[1], &lease) < 1)
{
fprintf(stderr, "invalid address: %s\n", argv[1]);
exit(1);
}
memset(&packet, 0, sizeof(packet)); memset(&packet, 0, sizeof(packet));
@@ -177,7 +181,7 @@ int main(int argc, char **argv)
*(p++) = OPTION_END; *(p++) = OPTION_END;
dest.sin_family = AF_INET; dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr("127.0.0.1"); (void)inet_pton(AF_INET, "127.0.0.1", &dest.sin_addr);
dest.sin_port = ntohs(DHCP_SERVER_PORT); dest.sin_port = ntohs(DHCP_SERVER_PORT);
if (sendto(fd, &packet, sizeof(packet), 0, if (sendto(fd, &packet, sizeof(packet), 0,
+1 -2
View File
@@ -288,13 +288,12 @@ int main(int argc, char **argv)
exit(1); exit(1);
} }
if (inet_addr(argv[2]) == INADDR_NONE) if (inet_pton(AF_INET, argv[2], &lease.s_addr) < 1)
{ {
perror("invalid ip address"); perror("invalid ip address");
exit(1); exit(1);
} }
lease.s_addr = inet_addr(argv[2]);
server = find_interface(lease, nl, if_nametoindex(argv[1]), fd, &ifr); server = find_interface(lease, nl, if_nametoindex(argv[1]), fd, &ifr);
memset(&packet, 0, sizeof(packet)); memset(&packet, 0, sizeof(packet));
+18 -10
View File
@@ -1,4 +1,4 @@
.TH DNSMASQ 8 2020-04-05 .TH DNSMASQ 8 2021-08-16
.SH NAME .SH NAME
dnsmasq \- A lightweight DHCP and caching DNS server. dnsmasq \- A lightweight DHCP and caching DNS server.
.SH SYNOPSIS .SH SYNOPSIS
@@ -55,7 +55,8 @@ Don't read the hostnames in /etc/hosts.
.B \-H, --addn-hosts=<file> .B \-H, --addn-hosts=<file>
Additional hosts file. Read the specified file as well as /etc/hosts. If \fB--no-hosts\fP is given, read Additional hosts file. Read the specified file as well as /etc/hosts. If \fB--no-hosts\fP is given, read
only the specified file. This option may be repeated for more than one only the specified file. This option may be repeated for more than one
additional hosts file. If a directory is given, then read all the files contained in that directory. additional hosts file. If a directory is given, then read all the files contained in that directory
in alphabetical order.
.TP .TP
.B --hostsdir=<path> .B --hostsdir=<path>
Read all the hosts files contained in the directory. New or changed files Read all the hosts files contained in the directory. New or changed files
@@ -705,7 +706,8 @@ configured a zero is added in front of the label. ::1 becomes 0--1.
V4 mapped IPv6 addresses, which have a representation like ::ffff:1.2.3.4 are handled specially, and become like 0--ffff-1-2-3-4 V4 mapped IPv6 addresses, which have a representation like ::ffff:1.2.3.4 are handled specially, and become like 0--ffff-1-2-3-4
The address range can be of the form The address range can be of the form
<ip address>,<ip address> or <ip address>/<netmask> in both forms of the option. <start address>,<end address> or <ip address>/<prefix-length> in both forms of the option. For IPv6 the start and end addresses
must fall in the same /64 network, or prefix-length must be greater than or equal to 64 except that shorter prefix lengths than 64 are allowed only if non-sequential names are in use.
.TP .TP
.B --dumpfile=<path/to/file> .B --dumpfile=<path/to/file>
Specify the location of a pcap-format file which dnsmasq uses to dump copies of network packets for debugging purposes. If the file exists when dnsmasq starts, it is not deleted; new packets are added to the end. Specify the location of a pcap-format file which dnsmasq uses to dump copies of network packets for debugging purposes. If the file exists when dnsmasq starts, it is not deleted; new packets are added to the end.
@@ -904,7 +906,7 @@ compiled in and the kernel must have conntrack support
included and configured. This option cannot be combined with included and configured. This option cannot be combined with
.B --query-port. .B --query-port.
.TP .TP
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-addr>[,<end-addr>|<mode>][,<netmask>[,<broadcast>]][,<lease time>] .B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-addr>[,<end-addr>|<mode>[,<netmask>[,<broadcast>]]][,<lease time>]
.TP .TP
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-IPv6addr>[,<end-IPv6addr>|constructor:<interface>][,<mode>][,<prefix-len>][,<lease time>] .B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-IPv6addr>[,<end-IPv6addr>|constructor:<interface>][,<mode>][,<prefix-len>][,<lease time>]
@@ -1164,7 +1166,7 @@ has both wired and wireless interfaces.
.TP .TP
.B --dhcp-hostsfile=<path> .B --dhcp-hostsfile=<path>
Read DHCP host information from the specified file. If a directory Read DHCP host information from the specified file. If a directory
is given, then read all the files contained in that directory. The file contains is given, then read all the files contained in that directory in alphabetical order. The file contains
information about one host per line. The format of a line is the same information about one host per line. The format of a line is the same
as text to the right of '=' in \fB--dhcp-host\fP. The advantage of storing DHCP host information as text to the right of '=' in \fB--dhcp-host\fP. The advantage of storing DHCP host information
in this file is that it can be changed without re-starting dnsmasq: in this file is that it can be changed without re-starting dnsmasq:
@@ -1172,7 +1174,7 @@ the file will be re-read when dnsmasq receives SIGHUP.
.TP .TP
.B --dhcp-optsfile=<path> .B --dhcp-optsfile=<path>
Read DHCP option information from the specified file. If a directory Read DHCP option information from the specified file. If a directory
is given, then read all the files contained in that directory. The advantage of is given, then read all the files contained in that directory in alphabetical order. The advantage of
using this option is the same as for \fB--dhcp-hostsfile\fP: the using this option is the same as for \fB--dhcp-hostsfile\fP: the
\fB--dhcp-optsfile\fP will be re-read when dnsmasq receives SIGHUP. Note that \fB--dhcp-optsfile\fP will be re-read when dnsmasq receives SIGHUP. Note that
it is possible to encode the information in a it is possible to encode the information in a
@@ -1187,7 +1189,8 @@ directory, and not an individual file. Changed or new files within
the directory are read automatically, without the need to send SIGHUP. the directory are read automatically, without the need to send SIGHUP.
If a file is deleted or changed after it has been read by dnsmasq, then the If a file is deleted or changed after it has been read by dnsmasq, then the
host record it contained will remain until dnsmasq receives a SIGHUP, or host record it contained will remain until dnsmasq receives a SIGHUP, or
is restarted; ie host records are only added dynamically. is restarted; ie host records are only added dynamically. The order in which the
files in a directory are read is not defined.
.TP .TP
.B --dhcp-optsdir=<path> .B --dhcp-optsdir=<path>
This is equivalent to \fB--dhcp-optsfile\fP, with the differences noted for \fB--dhcp-hostsdir\fP. This is equivalent to \fB--dhcp-optsfile\fP, with the differences noted for \fB--dhcp-hostsdir\fP.
@@ -1612,10 +1615,11 @@ tried. This flag disables this check. Use with caution.
Extra logging for DHCP: log all the options sent to DHCP clients and Extra logging for DHCP: log all the options sent to DHCP clients and
the tags used to determine them. the tags used to determine them.
.TP .TP
.B --quiet-dhcp, --quiet-dhcp6, --quiet-ra .B --quiet-dhcp, --quiet-dhcp6, --quiet-ra, --quiet-tftp
Suppress logging of the routine operation of these protocols. Errors and Suppress logging of the routine operation of these protocols. Errors and
problems will still be logged. \fB--quiet-dhcp\fP and quiet-dhcp6 are problems will still be logged. \fB--quiet-tftp\fP does not consider file not
over-ridden by \fB--log-dhcp\fP. found to be an error. \fB--quiet-dhcp\fP and quiet-dhcp6 are over-ridden by
\fB--log-dhcp\fP.
.TP .TP
.B \-l, --dhcp-leasefile=<path> .B \-l, --dhcp-leasefile=<path>
Use the specified file to store DHCP lease information. Use the specified file to store DHCP lease information.
@@ -2417,6 +2421,10 @@ following data is used to populate the authoritative zone.
.B --mx-host, --srv-host, --dns-rr, --txt-record, --naptr-record, --caa-record, .B --mx-host, --srv-host, --dns-rr, --txt-record, --naptr-record, --caa-record,
as long as the record names are in the authoritative domain. as long as the record names are in the authoritative domain.
.PP .PP
.B --synth-domain
as long as the domain is in the authoritative zone and, for
reverse (PTR) queries, the address is in the relevant subnet.
.PP
.B --cname .B --cname
as long as the record name is in the authoritative domain. If the as long as the record name is in the authoritative domain. If the
target of the CNAME is unqualified, then it is qualified with the target of the CNAME is unqualified, then it is qualified with the
+671 -512
View File
File diff suppressed because it is too large. Load diff
+689 -524
View File
File diff suppressed because it is too large. Load diff
+731 -579
View File
File diff suppressed because it is too large. Load diff
+690 -525
View File
File diff suppressed because it is too large. Load diff
+698 -530
View File
File diff suppressed because it is too large. Load diff
+731 -579
View File
File diff suppressed because it is too large. Load diff
+717 -554
View File
File diff suppressed because it is too large. Load diff
+690 -524
View File
File diff suppressed because it is too large. Load diff
+731 -579
View File
File diff suppressed because it is too large. Load diff
+717 -554
View File
File diff suppressed because it is too large. Load diff
+38 -1
View File
@@ -105,7 +105,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
int nameoffset, axfroffset = 0; int nameoffset, axfroffset = 0;
int q, anscount = 0, authcount = 0; int q, anscount = 0, authcount = 0;
struct crec *crecp; struct crec *crecp;
int auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0; int auth = !local_query, trunc = 0, nxdomain = 1, soa = 0, ns = 0, axfr = 0, out_of_zone = 0;
struct auth_zone *zone = NULL; struct auth_zone *zone = NULL;
struct addrlist *subnet = NULL; struct addrlist *subnet = NULL;
char *cut; char *cut;
@@ -146,6 +146,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (qclass != C_IN) if (qclass != C_IN)
{ {
auth = 0; auth = 0;
out_of_zone = 1;
continue; continue;
} }
@@ -159,6 +160,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (!zone) if (!zone)
{ {
out_of_zone = 1;
auth = 0; auth = 0;
continue; continue;
} }
@@ -253,6 +255,17 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
} while ((crecp = cache_find_by_addr(crecp, &addr, now, flag))); } while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
if (!found && is_rev_synth(flag, &addr, name) && (local_query || in_zone(zone, name, NULL)))
{
log_query(F_CONFIG | F_REVERSE | flag, name, &addr, NULL);
found = 1;
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL,
T_PTR, C_IN, "d", name))
anscount++;
}
if (found) if (found)
nxdomain = 0; nxdomain = 0;
else else
@@ -273,6 +286,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
if (!zone) if (!zone)
{ {
out_of_zone = 1;
auth = 0; auth = 0;
continue; continue;
} }
@@ -401,6 +415,17 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
} }
} }
if (!found && is_name_synthetic(flag, name, &addr) )
{
found = 1;
nxdomain = 0;
log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL);
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
daemon->auth_ttl, NULL, qtype, C_IN, qtype == T_A ? "4" : "6", &addr))
anscount++;
}
if (!cut) if (!cut)
{ {
nxdomain = 0; nxdomain = 0;
@@ -855,10 +880,22 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
SET_RCODE(header, NXDOMAIN); SET_RCODE(header, NXDOMAIN);
else else
SET_RCODE(header, NOERROR); /* no error */ SET_RCODE(header, NOERROR); /* no error */
header->ancount = htons(anscount); header->ancount = htons(anscount);
header->nscount = htons(authcount); header->nscount = htons(authcount);
header->arcount = htons(0); header->arcount = htons(0);
if (!local_query && out_of_zone)
{
SET_RCODE(header, REFUSED);
header->ancount = htons(0);
header->nscount = htons(0);
addr.log.rcode = REFUSED;
addr.log.ede = EDE_NOT_AUTH;
log_query(F_UPSTREAM | F_RCODE, "error", &addr, NULL);
return resize_packet(header, ansp - (unsigned char *)header, NULL, 0);
}
/* Advertise our packet size limit in our reply */ /* Advertise our packet size limit in our reply */
if (have_pseudoheader) if (have_pseudoheader)
return add_pseudoheader(header, ansp - (unsigned char *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0); return add_pseudoheader(header, ansp - (unsigned char *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
+2 -2
View File
@@ -1974,7 +1974,7 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg)
source = "reply"; source = "reply";
else if (flags & F_SECSTAT) else if (flags & F_SECSTAT)
{ {
if (addr && addr->log.ede != EDE_UNSET) if (addr && addr->log.ede != EDE_UNSET && option_bool(OPT_EXTRALOG))
{ {
extra = daemon->addrbuff; extra = daemon->addrbuff;
sprintf(extra, " (EDE: %s)", edestr(addr->log.ede)); sprintf(extra, " (EDE: %s)", edestr(addr->log.ede));
@@ -2023,5 +2023,5 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg)
} }
} }
else else
my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest); my_syslog(LOG_INFO, "%s %s %s %s%s", source, name, verb, dest, extra);
} }
+12 -7
View File
@@ -468,8 +468,11 @@ void dhcp_packet(time_t now, int pxe_fd)
/* This can fail when, eg, iptables DROPS destination 255.255.255.255 */ /* This can fail when, eg, iptables DROPS destination 255.255.255.255 */
if (errno != 0) if (errno != 0)
my_syslog(MS_DHCP | LOG_WARNING, _("Error sending DHCP packet to %s: %s"), {
inet_ntoa(dest.sin_addr), strerror(errno)); inet_ntop(AF_INET, &dest.sin_addr, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("Error sending DHCP packet to %s: %s"),
daemon->addrbuff, strerror(errno));
}
} }
/* check against secondary interface addresses */ /* check against secondary interface addresses */
@@ -521,10 +524,11 @@ static void guess_range_netmask(struct in_addr addr, struct in_addr netmask)
!(is_same_net(addr, context->start, netmask) && !(is_same_net(addr, context->start, netmask) &&
is_same_net(addr, context->end, netmask))) is_same_net(addr, context->end, netmask)))
{ {
strcpy(daemon->dhcp_buff, inet_ntoa(context->start)); inet_ntop(AF_INET, &context->start, daemon->dhcp_buff, DHCP_BUFF_SZ);
strcpy(daemon->dhcp_buff2, inet_ntoa(context->end)); inet_ntop(AF_INET, &context->end, daemon->dhcp_buff2, DHCP_BUFF_SZ);
inet_ntop(AF_INET, &netmask, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"), my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask)); daemon->dhcp_buff, daemon->dhcp_buff2, daemon->addrbuff);
} }
context->netmask = netmask; context->netmask = netmask;
} }
@@ -922,7 +926,7 @@ void dhcp_read_ethers(void)
if (!*cp) if (!*cp)
{ {
if ((addr.s_addr = inet_addr(ip)) == (in_addr_t)-1) if (inet_pton(AF_INET, ip, &addr.s_addr) < 1)
{ {
my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno); my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno);
continue; continue;
@@ -1097,7 +1101,8 @@ static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess,
if (option_bool(OPT_LOG_OPTS)) if (option_bool(OPT_LOG_OPTS))
{ {
inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN); inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, inet_ntoa(relay->server.addr4)); inet_ntop(AF_INET, &relay->server.addr4, daemon->dhcp_buff2, DHCP_BUFF_SZ);
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, daemon->dhcp_buff2);
} }
/* Save this for replies */ /* Save this for replies */
+7 -3
View File
@@ -109,7 +109,6 @@ int main (int argc, char **argv)
daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ; daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
daemon->packet = safe_malloc(daemon->packet_buff_sz); daemon->packet = safe_malloc(daemon->packet_buff_sz);
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
if (option_bool(OPT_EXTRALOG)) if (option_bool(OPT_EXTRALOG))
daemon->addrbuff2 = safe_malloc(ADDRSTRLEN); daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
@@ -212,8 +211,13 @@ int main (int argc, char **argv)
#endif #endif
#ifdef HAVE_CONNTRACK #ifdef HAVE_CONNTRACK
if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport)) if (option_bool(OPT_CONNTRACK))
die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF); {
if (daemon->query_port != 0 || daemon->osport)
die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
need_cap_net_admin = 1;
}
#else #else
if (option_bool(OPT_CONNTRACK)) if (option_bool(OPT_CONNTRACK))
die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF); die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
+5 -3
View File
@@ -107,6 +107,7 @@ typedef unsigned long long u64;
#endif #endif
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <fcntl.h> #include <fcntl.h>
@@ -273,7 +274,8 @@ struct event_desc {
#define OPT_UMBRELLA 63 #define OPT_UMBRELLA 63
#define OPT_UMBRELLA_DEVID 64 #define OPT_UMBRELLA_DEVID 64
#define OPT_CMARK_ALST_EN 65 #define OPT_CMARK_ALST_EN 65
#define OPT_LAST 66 #define OPT_QUIET_TFTP 66
#define OPT_LAST 67
#define OPTION_BITS (sizeof(unsigned int)*8) #define OPTION_BITS (sizeof(unsigned int)*8)
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) ) #define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
@@ -959,10 +961,10 @@ struct dhcp_bridge {
}; };
struct cond_domain { struct cond_domain {
char *domain, *prefix; char *domain, *prefix; /* prefix is text-prefix on domain name */
struct in_addr start, end; struct in_addr start, end;
struct in6_addr start6, end6; struct in6_addr start6, end6;
int is6, indexed; int is6, indexed, prefixlen;
struct cond_domain *next; struct cond_domain *next;
}; };
+34 -30
View File
@@ -18,8 +18,9 @@
static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c); static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c);
static int match_domain(struct in_addr addr, struct cond_domain *c);
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c); static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c);
static int match_domain6(struct in6_addr *addr, struct cond_domain *c);
int is_name_synthetic(int flags, char *name, union all_addr *addr) int is_name_synthetic(int flags, char *name, union all_addr *addr)
{ {
@@ -135,26 +136,7 @@ int is_name_synthetic(int flags, char *name, union all_addr *addr)
} }
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr)) if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
{ found = (prot == AF_INET) ? match_domain(addr->addr4, c) : match_domain6(&addr->addr6, c);
if (prot == AF_INET)
{
if (!c->is6 &&
ntohl(addr->addr4.s_addr) >= ntohl(c->start.s_addr) &&
ntohl(addr->addr4.s_addr) <= ntohl(c->end.s_addr))
found = 1;
}
else
{
u64 addrpart = addr6part(&addr->addr6);
if (c->is6 &&
is_same_net6(&addr->addr6, &c->start6, 64) &&
addrpart >= addr6part(&c->start6) &&
addrpart <= addr6part(&c->end6))
found = 1;
}
}
} }
/* restore name */ /* restore name */
@@ -246,12 +228,20 @@ int is_rev_synth(int flag, union all_addr *addr, char *name)
} }
static int match_domain(struct in_addr addr, struct cond_domain *c)
{
if (!c->is6 &&
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
return 1;
return 0;
}
static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c) static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c)
{ {
for (; c; c = c->next) for (; c; c = c->next)
if (!c->is6 && if (match_domain(addr, c))
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
return c; return c;
return NULL; return NULL;
@@ -267,16 +257,30 @@ char *get_domain(struct in_addr addr)
return daemon->domain_suffix; return daemon->domain_suffix;
} }
static int match_domain6(struct in6_addr *addr, struct cond_domain *c)
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c)
{ {
u64 addrpart = addr6part(addr); u64 addrpart = addr6part(addr);
if (c->is6)
{
if (c->prefixlen >= 64)
{
if (is_same_net6(addr, &c->start6, 64) &&
addrpart >= addr6part(&c->start6) &&
addrpart <= addr6part(&c->end6))
return 1;
}
else if (is_same_net6(addr, &c->start6, c->prefixlen))
return 1;
}
return 0;
}
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c)
{
for (; c; c = c->next) for (; c; c = c->next)
if (c->is6 && if (match_domain6(addr, c))
is_same_net6(addr, &c->start6, 64) &&
addrpart >= addr6part(&c->start6) &&
addrpart <= addr6part(&c->end6))
return c; return c;
return NULL; return NULL;
+27 -22
View File
@@ -255,29 +255,25 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
/* new query */ /* new query */
if (!forward) if (!forward)
{ {
/* new query */ if (lookup_domain(daemon->namebuff, gotname, &first, &last))
flags = is_local_answer(now, first, daemon->namebuff);
else
{
/* no available server. */
ede = EDE_NOT_READY;
flags = 0;
}
/* don't forward A or AAAA queries for simple names, except the empty name */ /* don't forward A or AAAA queries for simple names, except the empty name */
if (option_bool(OPT_NODOTS_LOCAL) && if (!flags &&
option_bool(OPT_NODOTS_LOCAL) &&
(gotname & (F_IPV4 | F_IPV6)) && (gotname & (F_IPV4 | F_IPV6)) &&
!strchr(daemon->namebuff, '.') && !strchr(daemon->namebuff, '.') &&
strlen(daemon->namebuff) != 0) strlen(daemon->namebuff) != 0)
{ flags = check_for_local_domain(daemon->namebuff, now) ? F_NOERR : F_NXDOMAIN;
flags = F_NOERR;
goto reply;
}
flags = 0;
/* no available server. */
if (!lookup_domain(daemon->namebuff, gotname, &first, &last))
{
ede = EDE_NOT_READY;
goto reply;
}
/* Configured answer. */ /* Configured answer. */
if ((flags = is_local_answer(now, first, daemon->namebuff))) if (flags || ede == EDE_NOT_READY)
goto reply; goto reply;
master = daemon->serverarray[first]; master = daemon->serverarray[first];
@@ -537,7 +533,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
{ {
u16 swap = htons((u16)ede); u16 swap = htons((u16)ede);
if (ede != -EDE_UNSET) if (ede != EDE_UNSET)
plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0); plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 0);
else else
plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0); plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
@@ -2038,15 +2034,24 @@ unsigned char *tcp_request(int confd, time_t now,
struct server *master; struct server *master;
int start; int start;
if (lookup_domain(daemon->namebuff, gotname, &first, &last))
flags = is_local_answer(now, first, daemon->namebuff);
else
{
/* No configured servers */
ede = EDE_NOT_READY;
flags = 0;
}
/* don't forward A or AAAA queries for simple names, except the empty name */ /* don't forward A or AAAA queries for simple names, except the empty name */
if (option_bool(OPT_NODOTS_LOCAL) && if (!flags &&
option_bool(OPT_NODOTS_LOCAL) &&
(gotname & (F_IPV4 | F_IPV6)) && (gotname & (F_IPV4 | F_IPV6)) &&
!strchr(daemon->namebuff, '.') && !strchr(daemon->namebuff, '.') &&
strlen(daemon->namebuff) != 0) strlen(daemon->namebuff) != 0)
flags = F_NOERR; flags = check_for_local_domain(daemon->namebuff, now) ? F_NOERR : F_NXDOMAIN;
else if (!lookup_domain(daemon->namebuff, gotname, &first, &last))
ede = EDE_NOT_READY; /* No configured servers */ if (!flags && ede != EDE_NOT_READY)
else if (!(flags = is_local_answer(now, first, daemon->namebuff)))
{ {
master = daemon->serverarray[first]; master = daemon->serverarray[first];
+7 -7
View File
@@ -76,9 +76,9 @@ unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name
#else /* HAVE_DNSSEC || HAVE_CRYPTOHASH */ #else /* HAVE_DNSSEC || HAVE_CRYPTOHASH */
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest #define SHA256_BLOCK_SIZE 32 /* SHA256 outputs a 32 byte digest */
typedef unsigned char BYTE; // 8-bit byte typedef unsigned char BYTE; /* 8-bit byte */
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines typedef unsigned int WORD; /* 32-bit word, change to "long" for 16-bit machines */
typedef struct { typedef struct {
BYTE data[64]; BYTE data[64];
@@ -238,7 +238,7 @@ static void sha256_final(SHA256_CTX *ctx, BYTE hash[])
i = ctx->datalen; i = ctx->datalen;
// Pad whatever data is left in the buffer. /* Pad whatever data is left in the buffer. */
if (ctx->datalen < 56) if (ctx->datalen < 56)
{ {
ctx->data[i++] = 0x80; ctx->data[i++] = 0x80;
@@ -254,7 +254,7 @@ static void sha256_final(SHA256_CTX *ctx, BYTE hash[])
memset(ctx->data, 0, 56); memset(ctx->data, 0, 56);
} }
// Append to the padding the total message's length in bits and transform. /* Append to the padding the total message's length in bits and transform. */
ctx->bitlen += ctx->datalen * 8; ctx->bitlen += ctx->datalen * 8;
ctx->data[63] = ctx->bitlen; ctx->data[63] = ctx->bitlen;
ctx->data[62] = ctx->bitlen >> 8; ctx->data[62] = ctx->bitlen >> 8;
@@ -266,8 +266,8 @@ static void sha256_final(SHA256_CTX *ctx, BYTE hash[])
ctx->data[56] = ctx->bitlen >> 56; ctx->data[56] = ctx->bitlen >> 56;
sha256_transform(ctx, ctx->data); sha256_transform(ctx, ctx->data);
// Since this implementation uses little endian byte ordering and SHA uses big endian, /* Since this implementation uses little endian byte ordering and SHA uses big endian,
// reverse all the bytes when copying the final state to the output hash. reverse all the bytes when copying the final state to the output hash. */
for (i = 0; i < 4; ++i) for (i = 0; i < 4; ++i)
{ {
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
+8 -2
View File
@@ -432,7 +432,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
buf = grab_extradata_lua(buf, end, "relay_address"); buf = grab_extradata_lua(buf, end, "relay_address");
else if (data.giaddr.s_addr != 0) else if (data.giaddr.s_addr != 0)
{ {
lua_pushstring(lua, inet_ntoa(data.giaddr)); inet_ntop(AF_INET, &data.giaddr, daemon->addrbuff, ADDRSTRLEN);
lua_pushstring(lua, daemon->addrbuff);
lua_setfield(lua, -2, "relay_address"); lua_setfield(lua, -2, "relay_address");
} }
@@ -611,7 +612,12 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
if (is6) if (is6)
buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err); buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err);
else else
my_setenv("DNSMASQ_RELAY_ADDRESS", data.giaddr.s_addr != 0 ? inet_ntoa(data.giaddr) : NULL, &err); {
const char *giaddr = NULL;
if (data.giaddr.s_addr != 0)
giaddr = inet_ntop(AF_INET, &data.giaddr, daemon->addrbuff, ADDRSTRLEN);
my_setenv("DNSMASQ_RELAY_ADDRESS", giaddr, &err);
}
for (i = 0; buf; i++) for (i = 0; buf; i++)
{ {
+1 -1
View File
@@ -1688,7 +1688,7 @@ int reload_servers(char *fname)
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
memset(&source_addr, 0, sizeof(source_addr)); memset(&source_addr, 0, sizeof(source_addr));
if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1) if (inet_pton(AF_INET, token, &addr.in.sin_addr) > 0)
{ {
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in); source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
+86 -38
View File
@@ -173,6 +173,7 @@ struct myoption {
#define LOPT_UMBRELLA 364 #define LOPT_UMBRELLA 364
#define LOPT_CMARK_ALST_EN 365 #define LOPT_CMARK_ALST_EN 365
#define LOPT_CMARK_ALST 366 #define LOPT_CMARK_ALST 366
#define LOPT_QUIET_TFTP 367
#ifdef HAVE_GETOPT_LONG #ifdef HAVE_GETOPT_LONG
static const struct option opts[] = static const struct option opts[] =
@@ -351,6 +352,7 @@ static const struct myoption opts[] =
{ "dynamic-host", 1, 0, LOPT_DYNHOST }, { "dynamic-host", 1, 0, LOPT_DYNHOST },
{ "log-debug", 0, 0, LOPT_LOG_DEBUG }, { "log-debug", 0, 0, LOPT_LOG_DEBUG },
{ "umbrella", 2, 0, LOPT_UMBRELLA }, { "umbrella", 2, 0, LOPT_UMBRELLA },
{ "quiet-tftp", 0, 0, LOPT_QUIET_TFTP },
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
@@ -536,6 +538,7 @@ static struct {
{ LOPT_DUMPMASK, ARG_ONE, "<hex>", gettext_noop("Mask which packets to dump"), NULL }, { LOPT_DUMPMASK, ARG_ONE, "<hex>", gettext_noop("Mask which packets to dump"), NULL },
{ LOPT_SCRIPT_TIME, OPT_LEASE_RENEW, NULL, gettext_noop("Call dhcp-script when lease expiry changes."), NULL }, { LOPT_SCRIPT_TIME, OPT_LEASE_RENEW, NULL, gettext_noop("Call dhcp-script when lease expiry changes."), NULL },
{ LOPT_UMBRELLA, ARG_ONE, "[=<optspec>]", gettext_noop("Send Cisco Umbrella identifiers including remote IP."), NULL }, { LOPT_UMBRELLA, ARG_ONE, "[=<optspec>]", gettext_noop("Send Cisco Umbrella identifiers including remote IP."), NULL },
{ LOPT_QUIET_TFTP, OPT_QUIET_TFTP, NULL, gettext_noop("Do not log routine TFTP."), NULL },
{ 0, 0, NULL, NULL, NULL } { 0, 0, NULL, NULL, NULL }
}; };
@@ -651,7 +654,7 @@ static char *canonicalise_opt(char *s)
return 0; return 0;
if (strlen(s) == 0) if (strlen(s) == 0)
return ""; return opt_string_alloc("");
unhide_metas(s); unhide_metas(s);
if (!(ret = canonicalise(s, &nomem)) && nomem) if (!(ret = canonicalise(s, &nomem)) && nomem)
@@ -965,7 +968,7 @@ static int domain_rev6(char *domain, struct in6_addr *addr, int msize)
{ {
int i; int i;
if (msize%4) if (msize > 128 || msize%4)
return 0; return 0;
*domain = 0; *domain = 0;
@@ -1185,11 +1188,15 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
{ {
new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7); new->u.vendor_class = (unsigned char *)opt_string_alloc(arg+7);
new->flags |= DHOPT_VENDOR; new->flags |= DHOPT_VENDOR;
if ((new->flags & DHOPT_ENCAPSULATE) || flags == DHOPT_MATCH)
goto_err(_("inappropriate vendor:"));
} }
else if (strstr(arg, "encap:") == arg) else if (strstr(arg, "encap:") == arg)
{ {
new->u.encap = atoi(arg+6); new->u.encap = atoi(arg+6);
new->flags |= DHOPT_ENCAPSULATE; new->flags |= DHOPT_ENCAPSULATE;
if ((new->flags & DHOPT_VENDOR) || flags == DHOPT_MATCH)
goto_err(_("inappropriate encap:"));
} }
else if (strstr(arg, "vi-encap:") == arg) else if (strstr(arg, "vi-encap:") == arg)
{ {
@@ -2224,7 +2231,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
arg = comma; arg = comma;
comma = split(arg); comma = split(arg);
daemon->hostmaster = opt_string_alloc(arg); daemon->hostmaster = opt_string_alloc(arg);
for (cp = daemon->hostmaster; *cp; cp++) for (cp = daemon->hostmaster; cp && *cp; cp++)
if (*cp == '@') if (*cp == '@')
*cp = '.'; *cp = '.';
@@ -2254,10 +2261,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
{ {
char *d, *d_raw = arg; char *d, *d_raw = arg;
comma = split(arg); comma = split(arg);
if (!(d = canonicalise_opt(arg))) if (!(d = canonicalise_opt(d_raw)))
ret_err(gen_err); ret_err(gen_err);
else else
{ {
free(d); /* allocate this again below. */
if (comma) if (comma)
{ {
struct cond_domain *new = opt_malloc(sizeof(struct cond_domain)); struct cond_domain *new = opt_malloc(sizeof(struct cond_domain));
@@ -2265,6 +2273,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->prefix = NULL; new->prefix = NULL;
new->indexed = 0; new->indexed = 0;
new->prefixlen = 0;
unhide_metas(comma); unhide_metas(comma);
if ((netpart = split_chr(comma, '/'))) if ((netpart = split_chr(comma, '/')))
@@ -2276,7 +2285,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
ret_err_free(gen_err, new); ret_err_free(gen_err, new);
else if (inet_pton(AF_INET, comma, &new->start)) else if (inet_pton(AF_INET, comma, &new->start))
{ {
int mask = (1 << (32 - msize)) - 1; int mask;
if (msize > 32)
ret_err_free(_("bad prefix length"), new);
mask = (1 << (32 - msize)) - 1;
new->is6 = 0; new->is6 = 0;
new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask); new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
new->end.s_addr = new->start.s_addr | htonl(mask); new->end.s_addr = new->start.s_addr | htonl(mask);
@@ -2307,21 +2321,25 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
} }
else if (inet_pton(AF_INET6, comma, &new->start6)) else if (inet_pton(AF_INET6, comma, &new->start6))
{ {
u64 mask = (1LLU << (128 - msize)) - 1LLU; u64 mask, addrpart = addr6part(&new->start6);
u64 addrpart = addr6part(&new->start6);
if (msize > 128)
ret_err_free(_("bad prefix length"), new);
mask = (1LLU << (128 - msize)) - 1LLU;
new->is6 = 1; new->is6 = 1;
new->prefixlen = msize;
/* prefix==64 overflows the mask calculation above */ /* prefix==64 overflows the mask calculation above */
if (msize == 64) if (msize <= 64)
mask = (u64)-1LL; mask = (u64)-1LL;
new->end6 = new->start6; new->end6 = new->start6;
setaddr6part(&new->start6, addrpart & ~mask); setaddr6part(&new->start6, addrpart & ~mask);
setaddr6part(&new->end6, addrpart | mask); setaddr6part(&new->end6, addrpart | mask);
if (msize < 64) if (arg)
ret_err_free(gen_err, new);
else if (arg)
{ {
if (option != 's') if (option != 's')
{ {
@@ -2381,7 +2399,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
} }
} }
new->domain = d; new->domain = canonicalise_opt(d_raw);
if (option == 's') if (option == 's')
{ {
new->next = daemon->cond_domain; new->next = daemon->cond_domain;
@@ -2390,19 +2408,21 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
else else
{ {
char *star; char *star;
new->next = daemon->synth_domains;
daemon->synth_domains = new;
if (new->prefix && if (new->prefix &&
(star = strrchr(new->prefix, '*')) (star = strrchr(new->prefix, '*'))
&& *(star+1) == 0) && *(star+1) == 0)
{ {
*star = 0; *star = 0;
new->indexed = 1; new->indexed = 1;
if (new->is6 && new->prefixlen < 64)
ret_err_free(_("prefix length too small"), new);
} }
new->next = daemon->synth_domains;
daemon->synth_domains = new;
} }
} }
else if (option == 's') else if (option == 's')
daemon->domain_suffix = d; daemon->domain_suffix = canonicalise_opt(d_raw);
else else
ret_err(gen_err); ret_err(gen_err);
} }
@@ -2680,11 +2700,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
{ {
if ((err = parse_server(arg, &serv_addr, &source_addr, interface, &flags))) if ((err = parse_server(arg, &serv_addr, &source_addr, interface, &flags)))
ret_err(err); ret_err(err);
/* server=//1.2.3.4 is special. */
if (strlen(domain) == 0 && lastdomain)
flags |= SERV_FOR_NODOTS;
} }
if (servers_only && option == 'S') if (servers_only && option == 'S')
@@ -2692,6 +2707,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
while (1) while (1)
{ {
/* server=//1.2.3.4 is special. */
if (strlen(domain) == 0 && lastdomain)
flags |= SERV_FOR_NODOTS;
else
flags &= ~SERV_FOR_NODOTS;
if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, &addr)) if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, &addr))
ret_err(gen_err); ret_err(gen_err);
@@ -3592,7 +3613,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
for (configs = daemon->dhcp_conf; configs; configs = configs->next) for (configs = daemon->dhcp_conf; configs; configs = configs->next)
if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr) if ((configs->flags & CONFIG_ADDR) && configs->addr.s_addr == in.s_addr)
{ {
sprintf(errstr, _("duplicate dhcp-host IP address %s"), inet_ntoa(in)); inet_ntop(AF_INET, &in, daemon->addrbuff, ADDRSTRLEN);
sprintf(errstr, _("duplicate dhcp-host IP address %s"),
daemon->addrbuff);
return 0; return 0;
} }
} }
@@ -4163,13 +4186,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
comma = split(arg); comma = split(arg);
new->interface = opt_string_alloc(split(comma)); new->interface = opt_string_alloc(split(comma));
new->iface_index = 0; new->iface_index = 0;
if (inet_pton(AF_INET, arg, &new->local) && inet_pton(AF_INET, comma, &new->server)) if (comma && inet_pton(AF_INET, arg, &new->local) && inet_pton(AF_INET, comma, &new->server))
{ {
new->next = daemon->relay4; new->next = daemon->relay4;
daemon->relay4 = new; daemon->relay4 = new;
} }
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
else if (inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, comma, &new->server)) else if (comma && inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, comma, &new->server))
{ {
new->next = daemon->relay6; new->next = daemon->relay6;
daemon->relay6 = new; daemon->relay6 = new;
@@ -5005,15 +5028,33 @@ static int one_file(char *file, int hard_opt)
return 1; return 1;
} }
static int file_filter(const struct dirent *ent)
{
size_t lenfile = strlen(ent->d_name);
/* ignore emacs backups and dotfiles */
if (lenfile == 0 ||
ent->d_name[lenfile - 1] == '~' ||
(ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
ent->d_name[0] == '.')
return 0;
return 1;
}
/* expand any name which is a directory */ /* expand any name which is a directory */
struct hostsfile *expand_filelist(struct hostsfile *list) struct hostsfile *expand_filelist(struct hostsfile *list)
{ {
unsigned int i; unsigned int i;
struct hostsfile *ah; int entcnt, n;
struct hostsfile *ah, *last, *next, **up;
struct dirent **namelist;
/* find largest used index */ /* find largest used index */
for (i = SRC_AH, ah = list; ah; ah = ah->next) for (i = SRC_AH, ah = list; ah; ah = ah->next)
{ {
last = ah;
if (i <= ah->index) if (i <= ah->index)
i = ah->index + 1; i = ah->index + 1;
@@ -5029,46 +5070,48 @@ struct hostsfile *expand_filelist(struct hostsfile *list)
struct stat buf; struct stat buf;
if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode)) if (stat(ah->fname, &buf) != -1 && S_ISDIR(buf.st_mode))
{ {
DIR *dir_stream;
struct dirent *ent; struct dirent *ent;
/* don't read this as a file */ /* don't read this as a file */
ah->flags |= AH_INACTIVE; ah->flags |= AH_INACTIVE;
if (!(dir_stream = opendir(ah->fname))) entcnt = scandir(ah->fname, &namelist, file_filter, alphasort);
if (entcnt < 0)
my_syslog(LOG_ERR, _("cannot access directory %s: %s"), my_syslog(LOG_ERR, _("cannot access directory %s: %s"),
ah->fname, strerror(errno)); ah->fname, strerror(errno));
else else
{ {
while ((ent = readdir(dir_stream))) for (n = 0; n < entcnt; n++)
{ {
ent = namelist[n];
size_t lendir = strlen(ah->fname); size_t lendir = strlen(ah->fname);
size_t lenfile = strlen(ent->d_name); size_t lenfile = strlen(ent->d_name);
struct hostsfile *ah1; struct hostsfile *ah1;
char *path; char *path;
/* ignore emacs backups and dotfiles */
if (lenfile == 0 ||
ent->d_name[lenfile - 1] == '~' ||
(ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
ent->d_name[0] == '.')
continue;
/* see if we have an existing record. /* see if we have an existing record.
dir is ah->fname dir is ah->fname
file is ent->d_name file is ent->d_name
path to match is ah1->fname */ path to match is ah1->fname */
for (ah1 = list; ah1; ah1 = ah1->next) for (up = &list, ah1 = list; ah1; ah1 = next)
{ {
next = ah1->next;
if (lendir < strlen(ah1->fname) && if (lendir < strlen(ah1->fname) &&
strstr(ah1->fname, ah->fname) == ah1->fname && strstr(ah1->fname, ah->fname) == ah1->fname &&
ah1->fname[lendir] == '/' && ah1->fname[lendir] == '/' &&
strcmp(ah1->fname + lendir + 1, ent->d_name) == 0) strcmp(ah1->fname + lendir + 1, ent->d_name) == 0)
{ {
ah1->flags &= ~AH_INACTIVE; ah1->flags &= ~AH_INACTIVE;
/* If found, remove from list to re-insert at the end.
Unless it's already at the end. */
if (last != ah1)
*up = next;
break; break;
} }
up = &ah1->next;
} }
/* make new record */ /* make new record */
@@ -5089,17 +5132,21 @@ struct hostsfile *expand_filelist(struct hostsfile *list)
ah1->fname = path; ah1->fname = path;
ah1->index = i++; ah1->index = i++;
ah1->flags = AH_DIR; ah1->flags = AH_DIR;
ah1->next = list;
list = ah1;
} }
/* Edge case, may be the last in the list anyway */
if (last != ah1)
last->next = ah1;
ah1->next = NULL;
last = ah1;
/* inactivate record if not regular file */ /* inactivate record if not regular file */
if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode)) if ((ah1->flags & AH_DIR) && stat(ah1->fname, &buf) != -1 && !S_ISREG(buf.st_mode))
ah1->flags |= AH_INACTIVE; ah1->flags |= AH_INACTIVE;
} }
closedir(dir_stream);
} }
free(namelist);
} }
} }
@@ -5214,6 +5261,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
daemon = opt_malloc(sizeof(struct daemon)); daemon = opt_malloc(sizeof(struct daemon));
memset(daemon, 0, sizeof(struct daemon)); memset(daemon, 0, sizeof(struct daemon));
daemon->namebuff = buff; daemon->namebuff = buff;
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
/* Set defaults - everything else is zero or NULL */ /* Set defaults - everything else is zero or NULL */
daemon->cachesize = CACHESIZ; daemon->cachesize = CACHESIZ;
+26 -26
View File
@@ -20,13 +20,13 @@
#define LOG(...) \ #define LOG(...) \
do { \ do { \
my_syslog(LOG_WARNING, __VA_ARGS__); \ my_syslog(LOG_DEBUG, __VA_ARGS__); \
} while (0) } while (0)
#define ASSERT(condition) \ #define ASSERT(condition) \
do { \ do { \
if (!(condition)) \ if (!(condition)) \
LOG("[pattern.c:%d] Assertion failure: %s", __LINE__, #condition); \ my_syslog(LOG_ERR, _("[pattern.c:%d] Assertion failure: %s"), __LINE__, #condition); \
} while (0) } while (0)
/** /**
@@ -66,8 +66,8 @@ static int is_string_matching_glob_pattern(
pattern_character -= 'a' - 'A'; pattern_character -= 'a' - 'A';
if (pattern_character == '*') if (pattern_character == '*')
{ {
// zero-or-more-character wildcard /* zero-or-more-character wildcard */
// Try to match at value_index, otherwise restart at value_index + 1 next. /* Try to match at value_index, otherwise restart at value_index + 1 next. */
next_pattern_index = pattern_index; next_pattern_index = pattern_index;
pattern_index++; pattern_index++;
if (value_index < num_value_bytes) if (value_index < num_value_bytes)
@@ -78,7 +78,7 @@ static int is_string_matching_glob_pattern(
} }
else else
{ {
// ordinary character /* ordinary character */
if (value_index < num_value_bytes) if (value_index < num_value_bytes)
{ {
char value_character = value[value_index]; char value_character = value[value_index];
@@ -139,7 +139,7 @@ int is_valid_dns_name(const char *value)
(*c < 'A' || *c > 'Z') && (*c < 'A' || *c > 'Z') &&
(*c < 'a' || *c > 'z')) (*c < 'a' || *c > 'z'))
{ {
LOG("Invalid DNS name: Invalid character %c.", *c); LOG(_("Invalid DNS name: Invalid character %c."), *c);
return 0; return 0;
} }
if (*c) if (*c)
@@ -148,12 +148,12 @@ int is_valid_dns_name(const char *value)
{ {
if (!*c || *c == '.') if (!*c || *c == '.')
{ {
LOG("Invalid DNS name: Empty label."); LOG(_("Invalid DNS name: Empty label."));
return 0; return 0;
} }
if (*c == '-') if (*c == '-')
{ {
LOG("Invalid DNS name: Label starts with hyphen."); LOG(_("Invalid DNS name: Label starts with hyphen."));
return 0; return 0;
} }
label = c; label = c;
@@ -167,13 +167,13 @@ int is_valid_dns_name(const char *value)
{ {
if (c[-1] == '-') if (c[-1] == '-')
{ {
LOG("Invalid DNS name: Label ends with hyphen."); LOG(_("Invalid DNS name: Label ends with hyphen."));
return 0; return 0;
} }
size_t num_label_bytes = (size_t) (c - label); size_t num_label_bytes = (size_t) (c - label);
if (num_label_bytes > 63) if (num_label_bytes > 63)
{ {
LOG("Invalid DNS name: Label is too long (%zu).", num_label_bytes); LOG(_("Invalid DNS name: Label is too long (%zu)."), num_label_bytes);
return 0; return 0;
} }
num_labels++; num_labels++;
@@ -181,12 +181,12 @@ int is_valid_dns_name(const char *value)
{ {
if (num_labels < 2) if (num_labels < 2)
{ {
LOG("Invalid DNS name: Not enough labels (%zu).", num_labels); LOG(_("Invalid DNS name: Not enough labels (%zu)."), num_labels);
return 0; return 0;
} }
if (is_label_numeric) if (is_label_numeric)
{ {
LOG("Invalid DNS name: Final label is fully numeric."); LOG(_("Invalid DNS name: Final label is fully numeric."));
return 0; return 0;
} }
if (num_label_bytes == 5 && if (num_label_bytes == 5 &&
@@ -196,12 +196,12 @@ int is_valid_dns_name(const char *value)
(label[3] == 'a' || label[3] == 'A') && (label[3] == 'a' || label[3] == 'A') &&
(label[4] == 'l' || label[4] == 'L')) (label[4] == 'l' || label[4] == 'L'))
{ {
LOG("Invalid DNS name: \"local\" pseudo-TLD."); LOG(_("Invalid DNS name: \"local\" pseudo-TLD."));
return 0; return 0;
} }
if (num_bytes < 1 || num_bytes > 253) if (num_bytes < 1 || num_bytes > 253)
{ {
LOG("DNS name has invalid length (%zu).", num_bytes); LOG(_("DNS name has invalid length (%zu)."), num_bytes);
return 0; return 0;
} }
return 1; return 1;
@@ -249,13 +249,13 @@ int is_valid_dns_name_pattern(const char *value)
for (const char *c = value;; c++) for (const char *c = value;; c++)
{ {
if (*c && if (*c &&
*c != '*' && // Wildcard. *c != '*' && /* Wildcard. */
*c != '-' && *c != '.' && *c != '-' && *c != '.' &&
(*c < '0' || *c > '9') && (*c < '0' || *c > '9') &&
(*c < 'A' || *c > 'Z') && (*c < 'A' || *c > 'Z') &&
(*c < 'a' || *c > 'z')) (*c < 'a' || *c > 'z'))
{ {
LOG("Invalid DNS name pattern: Invalid character %c.", *c); LOG(_("Invalid DNS name pattern: Invalid character %c."), *c);
return 0; return 0;
} }
if (*c && *c != '*') if (*c && *c != '*')
@@ -264,12 +264,12 @@ int is_valid_dns_name_pattern(const char *value)
{ {
if (!*c || *c == '.') if (!*c || *c == '.')
{ {
LOG("Invalid DNS name pattern: Empty label."); LOG(_("Invalid DNS name pattern: Empty label."));
return 0; return 0;
} }
if (*c == '-') if (*c == '-')
{ {
LOG("Invalid DNS name pattern: Label starts with hyphen."); LOG(_("Invalid DNS name pattern: Label starts with hyphen."));
return 0; return 0;
} }
label = c; label = c;
@@ -282,7 +282,7 @@ int is_valid_dns_name_pattern(const char *value)
{ {
if (num_wildcards >= 2) if (num_wildcards >= 2)
{ {
LOG("Invalid DNS name pattern: Wildcard character used more than twice per label."); LOG(_("Invalid DNS name pattern: Wildcard character used more than twice per label."));
return 0; return 0;
} }
num_wildcards++; num_wildcards++;
@@ -292,13 +292,13 @@ int is_valid_dns_name_pattern(const char *value)
{ {
if (c[-1] == '-') if (c[-1] == '-')
{ {
LOG("Invalid DNS name pattern: Label ends with hyphen."); LOG(_("Invalid DNS name pattern: Label ends with hyphen."));
return 0; return 0;
} }
size_t num_label_bytes = (size_t) (c - label) - num_wildcards; size_t num_label_bytes = (size_t) (c - label) - num_wildcards;
if (num_label_bytes > 63) if (num_label_bytes > 63)
{ {
LOG("Invalid DNS name pattern: Label is too long (%zu).", num_label_bytes); LOG(_("Invalid DNS name pattern: Label is too long (%zu)."), num_label_bytes);
return 0; return 0;
} }
num_labels++; num_labels++;
@@ -306,17 +306,17 @@ int is_valid_dns_name_pattern(const char *value)
{ {
if (num_labels < 2) if (num_labels < 2)
{ {
LOG("Invalid DNS name pattern: Not enough labels (%zu).", num_labels); LOG(_("Invalid DNS name pattern: Not enough labels (%zu)."), num_labels);
return 0; return 0;
} }
if (num_wildcards != 0 || previous_label_has_wildcard) if (num_wildcards != 0 || previous_label_has_wildcard)
{ {
LOG("Invalid DNS name pattern: Wildcard within final two labels."); LOG(_("Invalid DNS name pattern: Wildcard within final two labels."));
return 0; return 0;
} }
if (is_label_numeric) if (is_label_numeric)
{ {
LOG("Invalid DNS name pattern: Final label is fully numeric."); LOG(_("Invalid DNS name pattern: Final label is fully numeric."));
return 0; return 0;
} }
if (num_label_bytes == 5 && if (num_label_bytes == 5 &&
@@ -326,12 +326,12 @@ int is_valid_dns_name_pattern(const char *value)
(label[3] == 'a' || label[3] == 'A') && (label[3] == 'a' || label[3] == 'A') &&
(label[4] == 'l' || label[4] == 'L')) (label[4] == 'l' || label[4] == 'L'))
{ {
LOG("Invalid DNS name pattern: \"local\" pseudo-TLD."); LOG(_("Invalid DNS name pattern: \"local\" pseudo-TLD."));
return 0; return 0;
} }
if (num_bytes < 1 || num_bytes > 253) if (num_bytes < 1 || num_bytes > 253)
{ {
LOG("DNS name pattern has invalid length after removing wildcards (%zu).", num_bytes); LOG(_("DNS name pattern has invalid length after removing wildcards (%zu)."), num_bytes);
return 0; return 0;
} }
return 1; return 1;
+55 -33
View File
@@ -372,9 +372,22 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (!context) if (!context)
{ {
const char *via;
if (subnet_addr.s_addr)
{
via = _("with subnet selector");
inet_ntop(AF_INET, &subnet_addr, daemon->addrbuff, ADDRSTRLEN);
}
else
{
via = _("via");
if (mess->giaddr.s_addr)
inet_ntop(AF_INET, &mess->giaddr, daemon->addrbuff, ADDRSTRLEN);
else
safe_strncpy(daemon->addrbuff, iface_name, ADDRSTRLEN);
}
my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"), my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"),
subnet_addr.s_addr ? _("with subnet selector") : _("via"), via, daemon->addrbuff);
subnet_addr.s_addr ? inet_ntoa(subnet_addr) : (mess->giaddr.s_addr ? inet_ntoa(mess->giaddr) : iface_name));
return 0; return 0;
} }
@@ -383,13 +396,19 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
struct dhcp_context *context_tmp; struct dhcp_context *context_tmp;
for (context_tmp = context; context_tmp; context_tmp = context_tmp->current) for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
{ {
strcpy(daemon->namebuff, inet_ntoa(context_tmp->start)); inet_ntop(AF_INET, &context_tmp->start, daemon->namebuff, MAXDNAME);
if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY)) if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"), {
ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->netmask)); inet_ntop(AF_INET, &context_tmp->netmask, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"),
ntohl(mess->xid), daemon->namebuff, daemon->addrbuff);
}
else else
my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"), {
ntohl(mess->xid), daemon->namebuff, inet_ntoa(context_tmp->end)); inet_ntop(AF_INET, &context_tmp->end, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
ntohl(mess->xid), daemon->namebuff, daemon->addrbuff);
}
} }
} }
@@ -1031,8 +1050,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
config->addr.s_addr == option_addr(opt).s_addr) config->addr.s_addr == option_addr(opt).s_addr)
{ {
prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF); prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
inet_ntop(AF_INET, &config->addr, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"), my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
inet_ntoa(config->addr), daemon->dhcp_buff); daemon->addrbuff, daemon->dhcp_buff);
config->flags |= CONFIG_DECLINED; config->flags |= CONFIG_DECLINED;
config->decline_time = now; config->decline_time = now;
} }
@@ -1078,7 +1098,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (have_config(config, CONFIG_ADDR)) if (have_config(config, CONFIG_ADDR))
{ {
char *addrs = inet_ntoa(config->addr); inet_ntop(AF_INET, &config->addr, daemon->addrbuff, ADDRSTRLEN);
if ((ltmp = lease_find_by_addr(config->addr)) && if ((ltmp = lease_find_by_addr(config->addr)) &&
ltmp != lease && ltmp != lease &&
@@ -1088,7 +1108,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len, unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len); ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len);
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"), my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
addrs, print_mac(daemon->namebuff, mac, len)); daemon->addrbuff, print_mac(daemon->namebuff, mac, len));
} }
else else
{ {
@@ -1097,10 +1117,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (context->router.s_addr == config->addr.s_addr) if (context->router.s_addr == config->addr.s_addr)
break; break;
if (tmp) if (tmp)
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), addrs); my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), daemon->addrbuff);
else if (have_config(config, CONFIG_DECLINED) && else if (have_config(config, CONFIG_DECLINED) &&
difftime(now, config->decline_time) < (float)DECLINE_BACKOFF) difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs); my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), daemon->addrbuff);
else else
conf = config->addr; conf = config->addr;
} }
@@ -1303,9 +1323,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
a lease from one of it's MACs to give the address to another. */ a lease from one of it's MACs to give the address to another. */
if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type)) if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
{ {
inet_ntop(AF_INET, &ltmp->addr, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"), my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"),
print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len), print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len),
inet_ntoa(ltmp->addr)); daemon->addrbuff);
lease = ltmp; lease = ltmp;
} }
else else
@@ -1674,42 +1695,40 @@ static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt)
static void log_packet(char *type, void *addr, unsigned char *ext_mac, static void log_packet(char *type, void *addr, unsigned char *ext_mac,
int mac_len, char *interface, char *string, char *err, u32 xid) int mac_len, char *interface, char *string, char *err, u32 xid)
{ {
struct in_addr a;
if (!err && !option_bool(OPT_LOG_OPTS) && option_bool(OPT_QUIET_DHCP)) if (!err && !option_bool(OPT_LOG_OPTS) && option_bool(OPT_QUIET_DHCP))
return; return;
/* addr may be misaligned */ daemon->addrbuff[0] = 0;
if (addr) if (addr)
memcpy(&a, addr, sizeof(a)); inet_ntop(AF_INET, addr, daemon->addrbuff, ADDRSTRLEN);
print_mac(daemon->namebuff, ext_mac, mac_len); print_mac(daemon->namebuff, ext_mac, mac_len);
if(option_bool(OPT_LOG_OPTS)) if (option_bool(OPT_LOG_OPTS))
my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s%s", my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s%s",
ntohl(xid), ntohl(xid),
type, type,
interface, interface,
addr ? inet_ntoa(a) : "", daemon->addrbuff,
addr ? " " : "", addr ? " " : "",
daemon->namebuff, daemon->namebuff,
string ? string : "", string ? string : "",
err ? err : ""); err ? err : "");
else else
my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s%s", my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s%s",
type, type,
interface, interface,
addr ? inet_ntoa(a) : "", daemon->addrbuff,
addr ? " " : "", addr ? " " : "",
daemon->namebuff, daemon->namebuff,
string ? string : "", string ? string : "",
err ? err : ""); err ? err : "");
#ifdef HAVE_UBUS #ifdef HAVE_UBUS
if (!strcmp(type, "DHCPACK")) if (!strcmp(type, "DHCPACK"))
ubus_event_bcast("dhcp.ack", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface); ubus_event_bcast("dhcp.ack", daemon->namebuff, addr ? daemon->addrbuff : NULL, string, interface);
else if (!strcmp(type, "DHCPRELEASE")) else if (!strcmp(type, "DHCPRELEASE"))
ubus_event_bcast("dhcp.release", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface); ubus_event_bcast("dhcp.release", daemon->namebuff, addr ? daemon->addrbuff : NULL, string, interface);
#endif #endif
} }
@@ -1861,7 +1880,10 @@ static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id
if (option_bool(OPT_LOG_OPTS)) if (option_bool(OPT_LOG_OPTS))
{ {
if (mess->siaddr.s_addr != 0) if (mess->siaddr.s_addr != 0)
my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), inet_ntoa(mess->siaddr)); {
inet_ntop(AF_INET, &mess->siaddr, daemon->addrbuff, ADDRSTRLEN);
my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), daemon->addrbuff);
}
if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0) if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0)
my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid)); my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid));
+2 -1
View File
@@ -761,7 +761,8 @@ static ssize_t tftp_err(int err, char *packet, char *message, char *file)
len = snprintf(mess->message, MAXMESSAGE, message, file, errstr); len = snprintf(mess->message, MAXMESSAGE, message, file, errstr);
ret += (len < MAXMESSAGE) ? len + 1 : MAXMESSAGE; /* include terminating zero */ ret += (len < MAXMESSAGE) ? len + 1 : MAXMESSAGE; /* include terminating zero */
my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message); if (err != ERR_FNF || !option_bool(OPT_QUIET_TFTP))
my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message);
return ret; return ret;
} }
+51 -37
View File
@@ -21,7 +21,6 @@
#include <libubus.h> #include <libubus.h>
static struct blob_buf b; static struct blob_buf b;
static int notify;
static int error_logged = 0; static int error_logged = 0;
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj, static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
@@ -78,17 +77,16 @@ static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj)
(void)ctx; (void)ctx;
my_syslog(LOG_DEBUG, _("UBus subscription callback: %s subscriber(s)"), obj->has_subscribers ? "1" : "0"); my_syslog(LOG_DEBUG, _("UBus subscription callback: %s subscriber(s)"), obj->has_subscribers ? "1" : "0");
notify = obj->has_subscribers;
} }
static void ubus_destroy(struct ubus_context *ubus) static void ubus_destroy(struct ubus_context *ubus)
{ {
// Forces re-initialization when we're reusing the same definitions later on.
ubus_object.id = 0;
ubus_object_type.id = 0;
ubus_free(ubus); ubus_free(ubus);
daemon->ubus = NULL; daemon->ubus = NULL;
/* Forces re-initialization when we're reusing the same definitions later on. */
ubus_object.id = 0;
ubus_object_type.id = 0;
} }
static void ubus_disconnect_cb(struct ubus_context *ubus) static void ubus_disconnect_cb(struct ubus_context *ubus)
@@ -173,6 +171,16 @@ void check_ubus_listeners()
} }
} }
#define CHECK(stmt) \
do { \
int e = (stmt); \
if (e) \
{ \
my_syslog(LOG_ERR, _("UBus command failed: %d (%s)"), e, #stmt); \
return (UBUS_STATUS_UNKNOWN_ERROR); \
} \
} while (0)
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj, static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct ubus_request_data *req, const char *method,
struct blob_attr *msg) struct blob_attr *msg)
@@ -183,12 +191,13 @@ static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj
(void)method; (void)method;
(void)msg; (void)msg;
blob_buf_init(&b, BLOBMSG_TYPE_TABLE); CHECK(blob_buf_init(&b, BLOBMSG_TYPE_TABLE));
for (i=0; i < __METRIC_MAX; i++) for (i=0; i < __METRIC_MAX; i++)
blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]); CHECK(blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]));
return ubus_send_reply(ctx, req, b.head); CHECK(ubus_send_reply(ctx, req, b.head));
return UBUS_STATUS_OK;
} }
#ifdef HAVE_CONNTRACK #ifdef HAVE_CONNTRACK
@@ -307,66 +316,71 @@ fail:
} }
#endif #endif
#undef CHECK
#define CHECK(stmt) \
do { \
int e = (stmt); \
if (e) \
{ \
my_syslog(LOG_ERR, _("UBus command failed: %d (%s)"), e, #stmt); \
return; \
} \
} while (0)
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface) void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface)
{ {
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus; struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
int ret;
if (!ubus || !notify) if (!ubus || !ubus_object.has_subscribers)
return; return;
blob_buf_init(&b, BLOBMSG_TYPE_TABLE); CHECK(blob_buf_init(&b, BLOBMSG_TYPE_TABLE));
if (mac) if (mac)
blobmsg_add_string(&b, "mac", mac); CHECK(blobmsg_add_string(&b, "mac", mac));
if (ip) if (ip)
blobmsg_add_string(&b, "ip", ip); CHECK(blobmsg_add_string(&b, "ip", ip));
if (name) if (name)
blobmsg_add_string(&b, "name", name); CHECK(blobmsg_add_string(&b, "name", name));
if (interface) if (interface)
blobmsg_add_string(&b, "interface", interface); CHECK(blobmsg_add_string(&b, "interface", interface));
ret = ubus_notify(ubus, &ubus_object, type, b.head, -1); CHECK(ubus_notify(ubus, &ubus_object, type, b.head, -1));
if (ret)
my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
} }
#ifdef HAVE_CONNTRACK #ifdef HAVE_CONNTRACK
void ubus_event_bcast_connmark_allowlist_refused(u32 mark, const char *name) void ubus_event_bcast_connmark_allowlist_refused(u32 mark, const char *name)
{ {
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus; struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
int ret;
if (!ubus || !notify) if (!ubus || !ubus_object.has_subscribers)
return; return;
blob_buf_init(&b, 0); CHECK(blob_buf_init(&b, 0));
blobmsg_add_u32(&b, "mark", mark); CHECK(blobmsg_add_u32(&b, "mark", mark));
blobmsg_add_string(&b, "name", name); CHECK(blobmsg_add_string(&b, "name", name));
ret = ubus_notify(ubus, &ubus_object, "connmark-allowlist.refused", b.head, -1); CHECK(ubus_notify(ubus, &ubus_object, "connmark-allowlist.refused", b.head, -1));
if (ret)
my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
} }
void ubus_event_bcast_connmark_allowlist_resolved(u32 mark, const char *name, const char *value, u32 ttl) void ubus_event_bcast_connmark_allowlist_resolved(u32 mark, const char *name, const char *value, u32 ttl)
{ {
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus; struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
int ret;
if (!ubus || !notify) if (!ubus || !ubus_object.has_subscribers)
return; return;
blob_buf_init(&b, 0); CHECK(blob_buf_init(&b, 0));
blobmsg_add_u32(&b, "mark", mark); CHECK(blobmsg_add_u32(&b, "mark", mark));
blobmsg_add_string(&b, "name", name); CHECK(blobmsg_add_string(&b, "name", name));
blobmsg_add_string(&b, "value", value); CHECK(blobmsg_add_string(&b, "value", value));
blobmsg_add_u32(&b, "ttl", ttl); CHECK(blobmsg_add_u32(&b, "ttl", ttl));
ret = ubus_notify(ubus, &ubus_object, "connmark-allowlist.resolved", b.head, /* timeout: */ 1000); /* Set timeout to allow UBus subscriber to configure firewall rules before returning. */
if (ret) CHECK(ubus_notify(ubus, &ubus_object, "connmark-allowlist.resolved", b.head, /* timeout: */ 1000));
my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
} }
#endif #endif
#undef CHECK
#endif /* HAVE_UBUS */ #endif /* HAVE_UBUS */