mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-06 15:51:41 +00:00
Compare commits
25
Commits
v2.78test2
...
v2.79test1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a49c5c2265 | ||
|
|
30858e3b9b | ||
|
|
30df7efc96 | ||
|
|
3e8c42cba5 | ||
|
|
62cb936cb7 | ||
|
|
39921d03ba | ||
|
|
6a0b00f0d6 | ||
|
|
51eadb692a | ||
|
|
897c113fda | ||
|
|
33e3f1029c | ||
|
|
3d4ff1ba84 | ||
|
|
24036ea507 | ||
|
|
0549c73b7e | ||
|
|
b697fbb7f1 | ||
|
|
96e063c43d | ||
|
|
4e841da1a6 | ||
|
|
09ce307bdb | ||
|
|
a3303e196e | ||
|
|
63437ffbb5 | ||
|
|
69a815aa8f | ||
|
|
1d224949cc | ||
|
|
391f708a09 | ||
|
|
cbd29e5da8 | ||
|
|
50a2841d34 | ||
|
|
9396752c11 |
No files matched your search
@@ -1,3 +1,8 @@
|
|||||||
|
version 2.79
|
||||||
|
Fix parsing of CNAME arguments, which are confused by extra spaces.
|
||||||
|
Thanks to Diego Aguirre for spotting the bug.
|
||||||
|
|
||||||
|
|
||||||
version 2.78
|
version 2.78
|
||||||
Fix logic of appending ".<layer>" to PXE basename. Thanks to Chris
|
Fix logic of appending ".<layer>" to PXE basename. Thanks to Chris
|
||||||
Novakovic for the patch.
|
Novakovic for the patch.
|
||||||
@@ -13,6 +18,76 @@ version 2.78
|
|||||||
ff325644c7afae2588583f935f4ea9b9694eb52e. Thanks to
|
ff325644c7afae2588583f935f4ea9b9694eb52e. Thanks to
|
||||||
John Fitzgibbon for the diagnosis and patch.
|
John Fitzgibbon for the diagnosis and patch.
|
||||||
|
|
||||||
|
Try other servers if first returns REFUSED when
|
||||||
|
--strict-order active. Thanks to Hans Dedecker
|
||||||
|
for the patch
|
||||||
|
|
||||||
|
Fix regression in 2.77, ironically added as a security
|
||||||
|
improvement, which resulted in a crash when a DNS
|
||||||
|
query exceeded 512 bytes (or the EDNS0 packet size,
|
||||||
|
if different.) Thanks to Christian Kujau, Arne Woerner
|
||||||
|
Juan Manuel Fernandez and Kevin Darbyshire-Bryant for
|
||||||
|
chasing this one down. CVE-2017-13704 applies.
|
||||||
|
|
||||||
|
Fix heap overflow in DNS code. This is a potentially serious
|
||||||
|
security hole. It allows an attacker who can make DNS
|
||||||
|
requests to dnsmasq, and who controls the contents of
|
||||||
|
a domain, which is thereby queried, to overflow
|
||||||
|
(by 2 bytes) a heap buffer and either crash, or
|
||||||
|
even take control of, dnsmasq.
|
||||||
|
CVE-2017-14491 applies.
|
||||||
|
Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
|
||||||
|
Kevin Hamacher and Ron Bowes of the Google Security Team for
|
||||||
|
finding this.
|
||||||
|
|
||||||
|
Fix heap overflow in IPv6 router advertisement code.
|
||||||
|
This is a potentially serious security hole, as a
|
||||||
|
crafted RA request can overflow a buffer and crash or
|
||||||
|
control dnsmasq. Attacker must be on the local network.
|
||||||
|
CVE-2017-14492 applies.
|
||||||
|
Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
|
||||||
|
and Kevin Hamacher of the Google Security Team for
|
||||||
|
finding this.
|
||||||
|
|
||||||
|
Fix stack overflow in DHCPv6 code. An attacker who can send
|
||||||
|
a DHCPv6 request to dnsmasq can overflow the stack frame and
|
||||||
|
crash or control dnsmasq.
|
||||||
|
CVE-2017-14493 applies.
|
||||||
|
Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
|
||||||
|
Kevin Hamacher and Ron Bowes of the Google Security Team for
|
||||||
|
finding this.
|
||||||
|
|
||||||
|
Fix information leak in DHCPv6. A crafted DHCPv6 packet can
|
||||||
|
cause dnsmasq to forward memory from outside the packet
|
||||||
|
buffer to a DHCPv6 server when acting as a relay.
|
||||||
|
CVE-2017-14494 applies.
|
||||||
|
Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
|
||||||
|
Kevin Hamacher and Ron Bowes of the Google Security Team for
|
||||||
|
finding this.
|
||||||
|
|
||||||
|
Fix DoS in DNS. Invalid boundary checks in the
|
||||||
|
add_pseudoheader function allows a memcpy call with negative
|
||||||
|
size An attacker which can send malicious DNS queries
|
||||||
|
to dnsmasq can trigger a DoS remotely.
|
||||||
|
dnsmasq is vulnerable only if one of the following option is
|
||||||
|
specified: --add-mac, --add-cpe-id or --add-subnet.
|
||||||
|
CVE-2017-14496 applies.
|
||||||
|
Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
|
||||||
|
Kevin Hamacher and Ron Bowes of the Google Security Team for
|
||||||
|
finding this.
|
||||||
|
|
||||||
|
Fix out-of-memory Dos vulnerability. An attacker which can
|
||||||
|
send malicious DNS queries to dnsmasq can trigger memory
|
||||||
|
allocations in the add_pseudoheader function
|
||||||
|
The allocated memory is never freed which leads to a DoS
|
||||||
|
through memory exhaustion. dnsmasq is vulnerable only
|
||||||
|
if one of the following option is specified:
|
||||||
|
--add-mac, --add-cpe-id or --add-subnet.
|
||||||
|
CVE-2017-14495 applies.
|
||||||
|
Credit to Felix Wilhelm, Fermin J. Serna, Gabriel Campana
|
||||||
|
Kevin Hamacher and Ron Bowes of the Google Security Team for
|
||||||
|
finding this.
|
||||||
|
|
||||||
|
|
||||||
version 2.77
|
version 2.77
|
||||||
Generate an error when configured with a CNAME loop,
|
Generate an error when configured with a CNAME loop,
|
||||||
|
|||||||
@@ -206,13 +206,13 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
unsigned int x;
|
unsigned int x;
|
||||||
if ((x = t/86400))
|
if ((x = t/86400))
|
||||||
printf("%dd", x);
|
printf("%ud", x);
|
||||||
if ((x = (t/3600)%24))
|
if ((x = (t/3600)%24))
|
||||||
printf("%dh", x);
|
printf("%uh", x);
|
||||||
if ((x = (t/60)%60))
|
if ((x = (t/60)%60))
|
||||||
printf("%dm", x);
|
printf("%um", x);
|
||||||
if ((x = t%60))
|
if ((x = t%60))
|
||||||
printf("%ds", x);
|
printf("%us", x);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
Hi,
|
||||||
|
I updated the try-all-ns patch to work with the latest version of git. Ended up implementing it on top of master, 2.78test2-7-g63437ff. As that specific if-clause has been changed in the last few commits, it's not compatible for 2.77, sadly.
|
||||||
|
|
||||||
|
Find the patch attached.
|
||||||
|
|
||||||
|
Regards,
|
||||||
|
|
||||||
|
Rasmus Ahlberg
|
||||||
|
Software Developer, R&D
|
||||||
|
Electrolux Small Appliances
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
diff --git a/src/forward.c b/src/forward.c
|
||||||
|
index e3fa94b..ecf3b98 100644
|
||||||
|
--- a/src/forward.c
|
||||||
|
+++ b/src/forward.c
|
||||||
|
@@ -789,9 +789,12 @@ void reply_query(int fd, int family, time_t now)
|
||||||
|
|
||||||
|
/* Note: if we send extra options in the EDNS0 header, we can't recreate
|
||||||
|
the query from the reply. */
|
||||||
|
- if (RCODE(header) == REFUSED &&
|
||||||
|
- forward->forwardall == 0 &&
|
||||||
|
- !(forward->flags & FREC_HAS_EXTRADATA))
|
||||||
|
+ if ((RCODE(header) == REFUSED &&
|
||||||
|
+ forward->forwardall == 0 &&
|
||||||
|
+ !(forward->flags & FREC_HAS_EXTRADATA)) ||
|
||||||
|
+ /* If strict-order is set, try next server on NXDOMAIN reply */
|
||||||
|
+ (RCODE(header) == NXDOMAIN && option_bool(OPT_ORDER) &&
|
||||||
|
+ server->next != NULL))
|
||||||
|
/* for broken servers, attempt to send to another one. */
|
||||||
|
{
|
||||||
|
unsigned char *pheader;
|
||||||
Vendored
+4
-2
@@ -1,8 +1,10 @@
|
|||||||
dnsmasq (2.78-1) unstable; urgency=low
|
dnsmasq (2.78-1) unstable; urgency=high
|
||||||
|
|
||||||
* New upstream.
|
* New upstream.
|
||||||
|
Security fixes for CVE-2017-13704 (closes: #877102)
|
||||||
|
Security fixes for CVE-2017-14491 - CVE-2017-14496 inclusive.
|
||||||
|
|
||||||
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 25 Jun 2017 21:34:00 +0000
|
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 29 Sep 2017 21:34:00 +0000
|
||||||
|
|
||||||
dnsmasq (2.77-2) unstable; urgency=low
|
dnsmasq (2.77-2) unstable; urgency=low
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -2048,7 +2048,7 @@ include set:<tag>, including one from the
|
|||||||
.B dhcp-range
|
.B dhcp-range
|
||||||
used to allocate the address, one from any matching
|
used to allocate the address, one from any matching
|
||||||
.B dhcp-host
|
.B dhcp-host
|
||||||
(and "known" if a dhcp-host matches)
|
(and "known" or "known-othernet" if a dhcp-host matches)
|
||||||
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.
|
||||||
|
|
||||||
|
|||||||
+492
-453
File diff suppressed because it is too large.
Load diff
+3
-8
@@ -119,11 +119,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
struct cname *a, *candidate;
|
struct cname *a, *candidate;
|
||||||
unsigned int wclen;
|
unsigned int wclen;
|
||||||
|
|
||||||
/* Clear buffer beyond request to avoid risk of
|
|
||||||
information disclosure. */
|
|
||||||
memset(((char *)header) + qlen, 0,
|
|
||||||
(limit - ((char *)header)) - qlen);
|
|
||||||
|
|
||||||
if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
|
if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -597,12 +592,12 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
char *p = name;
|
char *p = name;
|
||||||
|
|
||||||
if (subnet->prefixlen >= 24)
|
if (subnet->prefixlen >= 24)
|
||||||
p += sprintf(p, "%d.", a & 0xff);
|
p += sprintf(p, "%u.", a & 0xff);
|
||||||
a = a >> 8;
|
a = a >> 8;
|
||||||
if (subnet->prefixlen >= 16 )
|
if (subnet->prefixlen >= 16 )
|
||||||
p += sprintf(p, "%d.", a & 0xff);
|
p += sprintf(p, "%u.", a & 0xff);
|
||||||
a = a >> 8;
|
a = a >> 8;
|
||||||
p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
|
p += sprintf(p, "%u.in-addr.arpa", a & 0xff);
|
||||||
|
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
|
|||||||
+1
-1
@@ -1511,7 +1511,7 @@ void dump_cache(time_t now)
|
|||||||
/* ctime includes trailing \n - eat it */
|
/* ctime includes trailing \n - eat it */
|
||||||
*(p-1) = 0;
|
*(p-1) = 0;
|
||||||
#endif
|
#endif
|
||||||
my_syslog(LOG_INFO, daemon->namebuff);
|
my_syslog(LOG_INFO, "%s", daemon->namebuff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+28
-20
@@ -16,6 +16,12 @@
|
|||||||
|
|
||||||
#define COPYRIGHT "Copyright (c) 2000-2017 Simon Kelley"
|
#define COPYRIGHT "Copyright (c) 2000-2017 Simon Kelley"
|
||||||
|
|
||||||
|
/* We do defines that influence behavior of stdio.h, so complain
|
||||||
|
if included too early. */
|
||||||
|
#ifdef _STDIO_H
|
||||||
|
# error "Header file stdio.h included too early!"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef NO_LARGEFILE
|
#ifndef NO_LARGEFILE
|
||||||
/* Ensure we can use files >2GB (log files may grow this big) */
|
/* Ensure we can use files >2GB (log files may grow this big) */
|
||||||
# define _LARGEFILE_SOURCE 1
|
# define _LARGEFILE_SOURCE 1
|
||||||
@@ -1130,18 +1136,18 @@ unsigned int extract_request(struct dns_header *header, size_t qlen,
|
|||||||
char *name, unsigned short *typep);
|
char *name, unsigned short *typep);
|
||||||
size_t setup_reply(struct dns_header *header, size_t qlen,
|
size_t setup_reply(struct dns_header *header, size_t qlen,
|
||||||
struct all_addr *addrp, unsigned int flags,
|
struct all_addr *addrp, unsigned int flags,
|
||||||
unsigned long local_ttl);
|
unsigned long ttl);
|
||||||
int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff,
|
int extract_addresses(struct dns_header *header, size_t qlen, char *name,
|
||||||
time_t now, char **ipsets, int is_sign, int checkrebind,
|
time_t now, char **ipsets, int is_sign, int check_rebind,
|
||||||
int no_cache, int secure, int *doctored);
|
int no_cache_dnssec, int secure, int *doctored);
|
||||||
size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||||
struct in_addr local_addr, struct in_addr local_netmask,
|
struct in_addr local_addr, struct in_addr local_netmask,
|
||||||
time_t now, int ad_reqd, int do_bit, int have_pseudoheader);
|
time_t now, int ad_reqd, int do_bit, int have_pseudoheader);
|
||||||
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
||||||
struct bogus_addr *addr, time_t now);
|
struct bogus_addr *baddr, time_t now);
|
||||||
int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
|
int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
|
||||||
int check_for_local_domain(char *name, time_t now);
|
int check_for_local_domain(char *name, time_t now);
|
||||||
unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
|
unsigned int questions_crc(struct dns_header *header, size_t plen, char *name);
|
||||||
size_t resize_packet(struct dns_header *header, size_t plen,
|
size_t resize_packet(struct dns_header *header, size_t plen,
|
||||||
unsigned char *pheader, size_t hlen);
|
unsigned char *pheader, size_t hlen);
|
||||||
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
|
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
|
||||||
@@ -1163,11 +1169,11 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
|
|||||||
|
|
||||||
/* dnssec.c */
|
/* dnssec.c */
|
||||||
size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
|
size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
|
||||||
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, char *name, char *keyname, int class);
|
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
|
||||||
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
|
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
|
||||||
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class,
|
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class,
|
||||||
int check_unsigned, int *neganswer, int *nons);
|
int check_unsigned, int *neganswer, int *nons);
|
||||||
int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
|
int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen);
|
||||||
size_t filter_rrsigs(struct dns_header *header, size_t plen);
|
size_t filter_rrsigs(struct dns_header *header, size_t plen);
|
||||||
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
|
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
|
||||||
int setup_timestamp(void);
|
int setup_timestamp(void);
|
||||||
@@ -1177,9 +1183,9 @@ void rand_init(void);
|
|||||||
unsigned short rand16(void);
|
unsigned short rand16(void);
|
||||||
u32 rand32(void);
|
u32 rand32(void);
|
||||||
u64 rand64(void);
|
u64 rand64(void);
|
||||||
int legal_hostname(char *c);
|
int legal_hostname(char *name);
|
||||||
char *canonicalise(char *s, int *nomem);
|
char *canonicalise(char *in, int *nomem);
|
||||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
|
unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
|
||||||
void *safe_malloc(size_t size);
|
void *safe_malloc(size_t size);
|
||||||
void safe_pipe(int *fd, int read_noblock);
|
void safe_pipe(int *fd, int read_noblock);
|
||||||
void *whine_malloc(size_t size);
|
void *whine_malloc(size_t size);
|
||||||
@@ -1212,7 +1218,9 @@ int wildcard_matchn(const char* wildcard, const char* match, int num);
|
|||||||
void die(char *message, char *arg1, int exit_code);
|
void die(char *message, char *arg1, int exit_code);
|
||||||
int log_start(struct passwd *ent_pw, int errfd);
|
int log_start(struct passwd *ent_pw, int errfd);
|
||||||
int log_reopen(char *log_file);
|
int log_reopen(char *log_file);
|
||||||
|
|
||||||
void my_syslog(int priority, const char *format, ...);
|
void my_syslog(int priority, const char *format, ...);
|
||||||
|
|
||||||
void set_log_writer(void);
|
void set_log_writer(void);
|
||||||
void check_log_writer(int force);
|
void check_log_writer(int force);
|
||||||
void flush_log(void);
|
void flush_log(void);
|
||||||
@@ -1240,7 +1248,7 @@ struct frec *get_new_frec(time_t now, int *wait, int force);
|
|||||||
int send_from(int fd, int nowild, char *packet, size_t len,
|
int send_from(int fd, int nowild, char *packet, size_t len,
|
||||||
union mysockaddr *to, struct all_addr *source,
|
union mysockaddr *to, struct all_addr *source,
|
||||||
unsigned int iface);
|
unsigned int iface);
|
||||||
void resend_query();
|
void resend_query(void);
|
||||||
struct randfd *allocate_rfd(int family);
|
struct randfd *allocate_rfd(int family);
|
||||||
void free_rfd(struct randfd *rfd);
|
void free_rfd(struct randfd *rfd);
|
||||||
|
|
||||||
@@ -1260,12 +1268,12 @@ void add_update_server(int flags,
|
|||||||
void check_servers(void);
|
void check_servers(void);
|
||||||
int enumerate_interfaces(int reset);
|
int enumerate_interfaces(int reset);
|
||||||
void create_wildcard_listeners(void);
|
void create_wildcard_listeners(void);
|
||||||
void create_bound_listeners(int die);
|
void create_bound_listeners(int dienow);
|
||||||
void warn_bound_listeners(void);
|
void warn_bound_listeners(void);
|
||||||
void warn_wild_labels(void);
|
void warn_wild_labels(void);
|
||||||
void warn_int_names(void);
|
void warn_int_names(void);
|
||||||
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);
|
||||||
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 label_exception(int index, int family, struct all_addr *addr);
|
||||||
int fix_fd(int fd);
|
int fix_fd(int fd);
|
||||||
@@ -1286,7 +1294,7 @@ void newaddress(time_t now);
|
|||||||
void dhcp_init(void);
|
void dhcp_init(void);
|
||||||
void dhcp_packet(time_t now, int pxe_fd);
|
void dhcp_packet(time_t now, int pxe_fd);
|
||||||
struct dhcp_context *address_available(struct dhcp_context *context,
|
struct dhcp_context *address_available(struct dhcp_context *context,
|
||||||
struct in_addr addr,
|
struct in_addr taddr,
|
||||||
struct dhcp_netid *netids);
|
struct dhcp_netid *netids);
|
||||||
struct dhcp_context *narrow_context(struct dhcp_context *context,
|
struct dhcp_context *narrow_context(struct dhcp_context *context,
|
||||||
struct in_addr taddr,
|
struct in_addr taddr,
|
||||||
@@ -1345,7 +1353,7 @@ void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data,
|
|||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||||
size_t sz, time_t now, int unicast_dest, int loopback,
|
size_t sz, time_t now, int unicast_dest, int loopback,
|
||||||
int *is_inform, int pxe_fd, struct in_addr fallback, time_t recvtime);
|
int *is_inform, int pxe, struct in_addr fallback, time_t recvtime);
|
||||||
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
||||||
int clid_len, unsigned char *clid, int *len_out);
|
int clid_len, unsigned char *clid, int *len_out);
|
||||||
#endif
|
#endif
|
||||||
@@ -1460,10 +1468,10 @@ unsigned short relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arriva
|
|||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
void dhcp_common_init(void);
|
void dhcp_common_init(void);
|
||||||
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg);
|
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg);
|
||||||
struct dhcp_netid *run_tag_if(struct dhcp_netid *input);
|
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags);
|
||||||
struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *context_tags,
|
struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *context_tags,
|
||||||
struct dhcp_opt *opts);
|
struct dhcp_opt *opts);
|
||||||
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);
|
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded);
|
||||||
char *strip_hostname(char *hostname);
|
char *strip_hostname(char *hostname);
|
||||||
void log_tags(struct dhcp_netid *netid, u32 xid);
|
void log_tags(struct dhcp_netid *netid, u32 xid);
|
||||||
int match_bytes(struct dhcp_opt *o, unsigned char *p, int len);
|
int match_bytes(struct dhcp_opt *o, unsigned char *p, int len);
|
||||||
@@ -1521,13 +1529,13 @@ void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
|
|||||||
|
|
||||||
/* loop.c */
|
/* loop.c */
|
||||||
#ifdef HAVE_LOOP
|
#ifdef HAVE_LOOP
|
||||||
void loop_send_probes();
|
void loop_send_probes(void);
|
||||||
int detect_loop(char *query, int type);
|
int detect_loop(char *query, int type);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* inotify.c */
|
/* inotify.c */
|
||||||
#ifdef HAVE_INOTIFY
|
#ifdef HAVE_INOTIFY
|
||||||
void inotify_dnsmasq_init();
|
void inotify_dnsmasq_init(void);
|
||||||
int inotify_check(time_t now);
|
int inotify_check(time_t now);
|
||||||
void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz);
|
void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1
-1
@@ -2230,7 +2230,7 @@ size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char
|
|||||||
|
|
||||||
p = (unsigned char *)(header+1);
|
p = (unsigned char *)(header+1);
|
||||||
|
|
||||||
p = do_rfc1035_name(p, name);
|
p = do_rfc1035_name(p, name, NULL);
|
||||||
*p++ = 0;
|
*p++ = 0;
|
||||||
PUTSHORT(type, p);
|
PUTSHORT(type, p);
|
||||||
PUTSHORT(class, p);
|
PUTSHORT(class, p);
|
||||||
|
|||||||
+23
-3
@@ -144,7 +144,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
|||||||
GETSHORT(len, p);
|
GETSHORT(len, p);
|
||||||
|
|
||||||
/* malformed option, delete the whole OPT RR and start again. */
|
/* malformed option, delete the whole OPT RR and start again. */
|
||||||
if (i + len > rdlen)
|
if (i + 4 + len > rdlen)
|
||||||
{
|
{
|
||||||
rdlen = 0;
|
rdlen = 0;
|
||||||
is_last = 0;
|
is_last = 0;
|
||||||
@@ -159,7 +159,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
|||||||
/* delete option if we're to replace it. */
|
/* delete option if we're to replace it. */
|
||||||
p -= 4;
|
p -= 4;
|
||||||
rdlen -= len + 4;
|
rdlen -= len + 4;
|
||||||
memcpy(p, p+len+4, rdlen - i);
|
memmove(p, p+len+4, rdlen - i);
|
||||||
PUTSHORT(rdlen, lenp);
|
PUTSHORT(rdlen, lenp);
|
||||||
lenp -= 2;
|
lenp -= 2;
|
||||||
}
|
}
|
||||||
@@ -192,7 +192,15 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
|||||||
!(p = skip_section(p,
|
!(p = skip_section(p,
|
||||||
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
|
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
|
||||||
header, plen)))
|
header, plen)))
|
||||||
|
{
|
||||||
|
free(buff);
|
||||||
return plen;
|
return plen;
|
||||||
|
}
|
||||||
|
if (p + 11 > limit)
|
||||||
|
{
|
||||||
|
free(buff);
|
||||||
|
return plen; /* Too big */
|
||||||
|
}
|
||||||
*p++ = 0; /* empty name */
|
*p++ = 0; /* empty name */
|
||||||
PUTSHORT(T_OPT, p);
|
PUTSHORT(T_OPT, p);
|
||||||
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
|
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
|
||||||
@@ -204,11 +212,19 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
|||||||
/* Copy back any options */
|
/* Copy back any options */
|
||||||
if (buff)
|
if (buff)
|
||||||
{
|
{
|
||||||
|
if (p + rdlen > limit)
|
||||||
|
{
|
||||||
|
free(buff);
|
||||||
|
return plen; /* Too big */
|
||||||
|
}
|
||||||
memcpy(p, buff, rdlen);
|
memcpy(p, buff, rdlen);
|
||||||
free(buff);
|
free(buff);
|
||||||
p += rdlen;
|
p += rdlen;
|
||||||
}
|
}
|
||||||
header->arcount = htons(ntohs(header->arcount) + 1);
|
|
||||||
|
/* Only bump arcount if RR is going to fit */
|
||||||
|
if (((ssize_t)optlen) <= (limit - (p + 4)))
|
||||||
|
header->arcount = htons(ntohs(header->arcount) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((ssize_t)optlen) > (limit - (p + 4)))
|
if (((ssize_t)optlen) > (limit - (p + 4)))
|
||||||
@@ -217,8 +233,12 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
|||||||
/* Add new option */
|
/* Add new option */
|
||||||
if (optno != 0 && replace != 2)
|
if (optno != 0 && replace != 2)
|
||||||
{
|
{
|
||||||
|
if (p + 4 > limit)
|
||||||
|
return plen; /* Too big */
|
||||||
PUTSHORT(optno, p);
|
PUTSHORT(optno, p);
|
||||||
PUTSHORT(optlen, p);
|
PUTSHORT(optlen, p);
|
||||||
|
if (p + optlen > limit)
|
||||||
|
return plen; /* Too big */
|
||||||
memcpy(p, opt, optlen);
|
memcpy(p, opt, optlen);
|
||||||
p += optlen;
|
p += optlen;
|
||||||
PUTSHORT(p - datap, lenp);
|
PUTSHORT(p - datap, lenp);
|
||||||
|
|||||||
+10
-1
@@ -790,7 +790,6 @@ void reply_query(int fd, int family, time_t now)
|
|||||||
/* Note: if we send extra options in the EDNS0 header, we can't recreate
|
/* Note: if we send extra options in the EDNS0 header, we can't recreate
|
||||||
the query from the reply. */
|
the query from the reply. */
|
||||||
if (RCODE(header) == REFUSED &&
|
if (RCODE(header) == REFUSED &&
|
||||||
!option_bool(OPT_ORDER) &&
|
|
||||||
forward->forwardall == 0 &&
|
forward->forwardall == 0 &&
|
||||||
!(forward->flags & FREC_HAS_EXTRADATA))
|
!(forward->flags & FREC_HAS_EXTRADATA))
|
||||||
/* for broken servers, attempt to send to another one. */
|
/* for broken servers, attempt to send to another one. */
|
||||||
@@ -1189,6 +1188,10 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
(msg.msg_flags & MSG_TRUNC) ||
|
(msg.msg_flags & MSG_TRUNC) ||
|
||||||
(header->hb3 & HB3_QR))
|
(header->hb3 & HB3_QR))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Clear buffer beyond request to avoid risk of
|
||||||
|
information disclosure. */
|
||||||
|
memset(daemon->packet + n, 0, daemon->edns_pktsz - n);
|
||||||
|
|
||||||
source_addr.sa.sa_family = listen->family;
|
source_addr.sa.sa_family = listen->family;
|
||||||
|
|
||||||
@@ -1409,6 +1412,8 @@ void receive_query(struct listener *listen, time_t now)
|
|||||||
defaults to 512 */
|
defaults to 512 */
|
||||||
if (udp_size > daemon->edns_pktsz)
|
if (udp_size > daemon->edns_pktsz)
|
||||||
udp_size = daemon->edns_pktsz;
|
udp_size = daemon->edns_pktsz;
|
||||||
|
else if (udp_size < PACKETSZ)
|
||||||
|
udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_AUTH
|
#ifdef HAVE_AUTH
|
||||||
@@ -1689,6 +1694,10 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
|
|
||||||
if (size < (int)sizeof(struct dns_header))
|
if (size < (int)sizeof(struct dns_header))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
/* Clear buffer beyond request to avoid risk of
|
||||||
|
information disclosure. */
|
||||||
|
memset(payload + size, 0, 65536 - size);
|
||||||
|
|
||||||
query_count++;
|
query_count++;
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
#ifdef HAVE_SCRIPT
|
#ifdef HAVE_SCRIPT
|
||||||
|
|||||||
+1
-1
@@ -229,7 +229,7 @@ void lease_update_from_configs(void)
|
|||||||
else if ((name = host_from_dns(lease->addr)))
|
else if ((name = host_from_dns(lease->addr)))
|
||||||
lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */
|
lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ourprintf(int *errp, char *format, ...)
|
static void ourprintf(int *errp, char *format, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|||||||
+5
-9
@@ -1460,13 +1460,6 @@ void check_servers(void)
|
|||||||
for (sfd = daemon->sfds; sfd; sfd = sfd->next)
|
for (sfd = daemon->sfds; sfd; sfd = sfd->next)
|
||||||
sfd->used = 0;
|
sfd->used = 0;
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
/* Disable DNSSEC validation when using server=/domain/.... servers
|
|
||||||
unless there's a configured trust anchor. */
|
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
|
||||||
serv->flags |= SERV_DO_DNSSEC;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (count = 0, serv = daemon->servers; serv; serv = serv->next)
|
for (count = 0, serv = daemon->servers; serv; serv = serv->next)
|
||||||
{
|
{
|
||||||
if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
|
if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
|
||||||
@@ -1478,6 +1471,11 @@ void check_servers(void)
|
|||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
{
|
{
|
||||||
|
if (!(serv->flags & SERV_FOR_NODOTS))
|
||||||
|
serv->flags |= SERV_DO_DNSSEC;
|
||||||
|
|
||||||
|
/* Disable DNSSEC validation when using server=/domain/.... servers
|
||||||
|
unless there's a configured trust anchor. */
|
||||||
if (serv->flags & SERV_HAS_DOMAIN)
|
if (serv->flags & SERV_HAS_DOMAIN)
|
||||||
{
|
{
|
||||||
struct ds_config *ds;
|
struct ds_config *ds;
|
||||||
@@ -1494,8 +1492,6 @@ void check_servers(void)
|
|||||||
if (!ds)
|
if (!ds)
|
||||||
serv->flags &= ~SERV_DO_DNSSEC;
|
serv->flags &= ~SERV_DO_DNSSEC;
|
||||||
}
|
}
|
||||||
else if (serv->flags & SERV_FOR_NODOTS)
|
|
||||||
serv->flags &= ~SERV_DO_DNSSEC;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -882,7 +882,7 @@ static struct server *add_rev4(struct in_addr addr, int msize)
|
|||||||
switch (msize)
|
switch (msize)
|
||||||
{
|
{
|
||||||
case 32:
|
case 32:
|
||||||
p += sprintf(p, "%d.", a & 0xff);
|
p += sprintf(p, "%u.", a & 0xff);
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case 24:
|
case 24:
|
||||||
p += sprintf(p, "%d.", (a >> 8) & 0xff);
|
p += sprintf(p, "%d.", (a >> 8) & 0xff);
|
||||||
@@ -1415,7 +1415,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
p = newp;
|
p = newp;
|
||||||
end = do_rfc1035_name(p + len, dom);
|
end = do_rfc1035_name(p + len, dom, NULL);
|
||||||
*end++ = 0;
|
*end++ = 0;
|
||||||
len = end - p;
|
len = end - p;
|
||||||
free(dom);
|
free(dom);
|
||||||
@@ -3862,7 +3862,7 @@ err:
|
|||||||
new->target = target;
|
new->target = target;
|
||||||
new->ttl = ttl;
|
new->ttl = ttl;
|
||||||
|
|
||||||
arg += strlen(arg)+1;
|
for (arg += strlen(arg)+1; *arg == ' '; arg++);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -198,6 +198,9 @@ void icmp6_packet(time_t now)
|
|||||||
/* look for link-layer address option for logging */
|
/* look for link-layer address option for logging */
|
||||||
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
|
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
|
||||||
{
|
{
|
||||||
|
if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
|
print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
|
||||||
mac = daemon->namebuff;
|
mac = daemon->namebuff;
|
||||||
}
|
}
|
||||||
|
|||||||
+49
-17
@@ -37,7 +37,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
/* end marker */
|
/* end marker */
|
||||||
{
|
{
|
||||||
/* check that there are the correct no of bytes after the name */
|
/* check that there are the correct no of bytes after the name */
|
||||||
if (!CHECK_LEN(header, p, plen, extrabytes))
|
if (!CHECK_LEN(header, p1 ? p1 : p, plen, extrabytes))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (isExtract)
|
if (isExtract)
|
||||||
@@ -498,6 +498,8 @@ static unsigned char *do_doctor(unsigned char *p, int count, struct dns_header *
|
|||||||
{
|
{
|
||||||
unsigned int i, len = *p1;
|
unsigned int i, len = *p1;
|
||||||
unsigned char *p2 = p1;
|
unsigned char *p2 = p1;
|
||||||
|
if ((p1 + len - p) >= rdlen)
|
||||||
|
return 0; /* bad packet */
|
||||||
/* make counted string zero-term and sanitise */
|
/* make counted string zero-term and sanitise */
|
||||||
for (i = 0; i < len; i++)
|
for (i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
@@ -1062,6 +1064,7 @@ int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bog
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
|
int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
|
||||||
unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
|
unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
|
||||||
{
|
{
|
||||||
@@ -1071,29 +1074,47 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
|||||||
unsigned short usval;
|
unsigned short usval;
|
||||||
long lval;
|
long lval;
|
||||||
char *sval;
|
char *sval;
|
||||||
|
#define CHECK_LIMIT(size) \
|
||||||
|
if (limit && p + (size) > (unsigned char*)limit) \
|
||||||
|
{ \
|
||||||
|
va_end(ap); \
|
||||||
|
goto truncated; \
|
||||||
|
}
|
||||||
|
|
||||||
if (truncp && *truncp)
|
if (truncp && *truncp)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
va_start(ap, format); /* make ap point to 1st unamed argument */
|
va_start(ap, format); /* make ap point to 1st unamed argument */
|
||||||
|
|
||||||
if (nameoffset > 0)
|
if (nameoffset > 0)
|
||||||
{
|
{
|
||||||
|
CHECK_LIMIT(2);
|
||||||
PUTSHORT(nameoffset | 0xc000, p);
|
PUTSHORT(nameoffset | 0xc000, p);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *name = va_arg(ap, char *);
|
char *name = va_arg(ap, char *);
|
||||||
if (name)
|
if (name && !(p = do_rfc1035_name(p, name, limit)))
|
||||||
p = do_rfc1035_name(p, name);
|
{
|
||||||
|
va_end(ap);
|
||||||
|
goto truncated;
|
||||||
|
}
|
||||||
|
|
||||||
if (nameoffset < 0)
|
if (nameoffset < 0)
|
||||||
{
|
{
|
||||||
|
CHECK_LIMIT(2);
|
||||||
PUTSHORT(-nameoffset | 0xc000, p);
|
PUTSHORT(-nameoffset | 0xc000, p);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*p++ = 0;
|
{
|
||||||
|
CHECK_LIMIT(1);
|
||||||
|
*p++ = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* type (2) + class (2) + ttl (4) + rdlen (2) */
|
||||||
|
CHECK_LIMIT(10);
|
||||||
|
|
||||||
PUTSHORT(type, p);
|
PUTSHORT(type, p);
|
||||||
PUTSHORT(class, p);
|
PUTSHORT(class, p);
|
||||||
PUTLONG(ttl, p); /* TTL */
|
PUTLONG(ttl, p); /* TTL */
|
||||||
@@ -1106,6 +1127,7 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
|||||||
{
|
{
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
case '6':
|
case '6':
|
||||||
|
CHECK_LIMIT(IN6ADDRSZ);
|
||||||
sval = va_arg(ap, char *);
|
sval = va_arg(ap, char *);
|
||||||
memcpy(p, sval, IN6ADDRSZ);
|
memcpy(p, sval, IN6ADDRSZ);
|
||||||
p += IN6ADDRSZ;
|
p += IN6ADDRSZ;
|
||||||
@@ -1113,36 +1135,47 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
case '4':
|
case '4':
|
||||||
|
CHECK_LIMIT(INADDRSZ);
|
||||||
sval = va_arg(ap, char *);
|
sval = va_arg(ap, char *);
|
||||||
memcpy(p, sval, INADDRSZ);
|
memcpy(p, sval, INADDRSZ);
|
||||||
p += INADDRSZ;
|
p += INADDRSZ;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
|
CHECK_LIMIT(1);
|
||||||
usval = va_arg(ap, int);
|
usval = va_arg(ap, int);
|
||||||
*p++ = usval;
|
*p++ = usval;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
|
CHECK_LIMIT(2);
|
||||||
usval = va_arg(ap, int);
|
usval = va_arg(ap, int);
|
||||||
PUTSHORT(usval, p);
|
PUTSHORT(usval, p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
|
CHECK_LIMIT(4);
|
||||||
lval = va_arg(ap, long);
|
lval = va_arg(ap, long);
|
||||||
PUTLONG(lval, p);
|
PUTLONG(lval, p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
/* get domain-name answer arg and store it in RDATA field */
|
/* get domain-name answer arg and store it in RDATA field */
|
||||||
if (offset)
|
if (offset)
|
||||||
*offset = p - (unsigned char *)header;
|
*offset = p - (unsigned char *)header;
|
||||||
p = do_rfc1035_name(p, va_arg(ap, char *));
|
p = do_rfc1035_name(p, va_arg(ap, char *), limit);
|
||||||
*p++ = 0;
|
if (!p)
|
||||||
|
{
|
||||||
|
va_end(ap);
|
||||||
|
goto truncated;
|
||||||
|
}
|
||||||
|
CHECK_LIMIT(1);
|
||||||
|
*p++ = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
usval = va_arg(ap, int);
|
usval = va_arg(ap, int);
|
||||||
|
CHECK_LIMIT(usval);
|
||||||
sval = va_arg(ap, char *);
|
sval = va_arg(ap, char *);
|
||||||
if (usval != 0)
|
if (usval != 0)
|
||||||
memcpy(p, sval, usval);
|
memcpy(p, sval, usval);
|
||||||
@@ -1154,20 +1187,24 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp, int
|
|||||||
usval = sval ? strlen(sval) : 0;
|
usval = sval ? strlen(sval) : 0;
|
||||||
if (usval > 255)
|
if (usval > 255)
|
||||||
usval = 255;
|
usval = 255;
|
||||||
|
CHECK_LIMIT(usval + 1);
|
||||||
*p++ = (unsigned char)usval;
|
*p++ = (unsigned char)usval;
|
||||||
memcpy(p, sval, usval);
|
memcpy(p, sval, usval);
|
||||||
p += usval;
|
p += usval;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef CHECK_LIMIT
|
||||||
va_end(ap); /* clean up variable argument pointer */
|
va_end(ap); /* clean up variable argument pointer */
|
||||||
|
|
||||||
j = p - sav - 2;
|
j = p - sav - 2;
|
||||||
PUTSHORT(j, sav); /* Now, store real RDLength */
|
/* this has already been checked against limit before */
|
||||||
|
PUTSHORT(j, sav); /* Now, store real RDLength */
|
||||||
|
|
||||||
/* check for overflow of buffer */
|
/* check for overflow of buffer */
|
||||||
if (limit && ((unsigned char *)limit - p) < 0)
|
if (limit && ((unsigned char *)limit - p) < 0)
|
||||||
{
|
{
|
||||||
|
truncated:
|
||||||
if (truncp)
|
if (truncp)
|
||||||
*truncp = 1;
|
*truncp = 1;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1223,11 +1260,6 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
struct mx_srv_record *rec;
|
struct mx_srv_record *rec;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
/* Clear buffer beyond request to avoid risk of
|
|
||||||
information disclosure. */
|
|
||||||
memset(((char *)header) + qlen, 0,
|
|
||||||
(limit - ((char *)header)) - qlen);
|
|
||||||
|
|
||||||
if (ntohs(header->ancount) != 0 ||
|
if (ntohs(header->ancount) != 0 ||
|
||||||
ntohs(header->nscount) != 0 ||
|
ntohs(header->nscount) != 0 ||
|
||||||
ntohs(header->qdcount) == 0 ||
|
ntohs(header->qdcount) == 0 ||
|
||||||
|
|||||||
+8
-10
@@ -32,7 +32,7 @@ static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, in
|
|||||||
static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
|
static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
|
||||||
int opt, char *string, int null_term);
|
int opt, char *string, int null_term);
|
||||||
static struct in_addr option_addr(unsigned char *opt);
|
static struct in_addr option_addr(unsigned char *opt);
|
||||||
static unsigned int option_uint(unsigned char *opt, int i, int size);
|
static unsigned int option_uint(unsigned char *opt, int offset, int size);
|
||||||
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);
|
||||||
static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
|
static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
|
||||||
@@ -42,14 +42,14 @@ static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
|
|||||||
static int in_list(unsigned char *list, int opt);
|
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 *end,
|
||||||
unsigned char *req_options,
|
unsigned char *req_options,
|
||||||
char *hostname,
|
char *hostname,
|
||||||
char *config_domain,
|
char *domain,
|
||||||
struct dhcp_netid *netid,
|
struct dhcp_netid *netid,
|
||||||
struct in_addr subnet_addr,
|
struct in_addr subnet_addr,
|
||||||
unsigned char fqdn_flags,
|
unsigned char fqdn_flags,
|
||||||
int null_term, int pxearch,
|
int null_term, int pxe_arch,
|
||||||
unsigned char *uuid,
|
unsigned char *uuid,
|
||||||
int vendor_class_len,
|
int vendor_class_len,
|
||||||
time_t now,
|
time_t now,
|
||||||
@@ -58,7 +58,7 @@ static void do_options(struct dhcp_context *context,
|
|||||||
|
|
||||||
|
|
||||||
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
|
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
|
||||||
static int do_encap_opts(struct dhcp_opt *opts, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
|
static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
|
||||||
static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid);
|
static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid);
|
||||||
static int prune_vendor_opts(struct dhcp_netid *netid);
|
static int prune_vendor_opts(struct dhcp_netid *netid);
|
||||||
static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now);
|
static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now);
|
||||||
@@ -157,7 +157,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
for (offset = 0; offset < (len - 5); offset += elen + 5)
|
for (offset = 0; offset < (len - 5); offset += elen + 5)
|
||||||
{
|
{
|
||||||
elen = option_uint(opt, offset + 4 , 1);
|
elen = option_uint(opt, offset + 4 , 1);
|
||||||
if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA)
|
if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA && offset + elen + 5 <= len)
|
||||||
{
|
{
|
||||||
unsigned char *x = option_ptr(opt, offset + 5);
|
unsigned char *x = option_ptr(opt, offset + 5);
|
||||||
unsigned char *y = option_ptr(opt, offset + elen + 5);
|
unsigned char *y = option_ptr(opt, offset + elen + 5);
|
||||||
@@ -1040,8 +1040,6 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
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"), addrs);
|
||||||
else if ((!lease || lease->addr.s_addr != config->addr.s_addr) && !do_icmp_ping(now, config->addr, 0, loopback))
|
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by another host"), addrs);
|
|
||||||
else
|
else
|
||||||
conf = config->addr;
|
conf = config->addr;
|
||||||
}
|
}
|
||||||
@@ -2454,10 +2452,10 @@ static void do_options(struct dhcp_context *context,
|
|||||||
|
|
||||||
if (fqdn_flags & 0x04)
|
if (fqdn_flags & 0x04)
|
||||||
{
|
{
|
||||||
p = do_rfc1035_name(p, hostname);
|
p = do_rfc1035_name(p, hostname, NULL);
|
||||||
if (domain)
|
if (domain)
|
||||||
{
|
{
|
||||||
p = do_rfc1035_name(p, domain);
|
p = do_rfc1035_name(p, domain, NULL);
|
||||||
*p++ = 0;
|
*p++ = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-2
@@ -206,6 +206,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
|||||||
/* RFC-6939 */
|
/* RFC-6939 */
|
||||||
if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3)))
|
if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3)))
|
||||||
{
|
{
|
||||||
|
if (opt6_len(opt) - 2 > DHCP_CHADDR_MAX) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
state->mac_type = opt6_uint(opt, 0, 2);
|
state->mac_type = opt6_uint(opt, 0, 2);
|
||||||
state->mac_len = opt6_len(opt) - 2;
|
state->mac_len = opt6_len(opt) - 2;
|
||||||
memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);
|
memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);
|
||||||
@@ -213,6 +216,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
|||||||
|
|
||||||
for (opt = opts; opt; opt = opt6_next(opt, end))
|
for (opt = opts; opt; opt = opt6_next(opt, end))
|
||||||
{
|
{
|
||||||
|
if (opt6_ptr(opt, 0) + opt6_len(opt) >= end) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
int o = new_opt6(opt6_type(opt));
|
int o = new_opt6(opt6_type(opt));
|
||||||
if (opt6_type(opt) == OPTION6_RELAY_MSG)
|
if (opt6_type(opt) == OPTION6_RELAY_MSG)
|
||||||
{
|
{
|
||||||
@@ -1479,10 +1485,10 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
|
|||||||
if ((p = expand(len + 2)))
|
if ((p = expand(len + 2)))
|
||||||
{
|
{
|
||||||
*(p++) = state->fqdn_flags;
|
*(p++) = state->fqdn_flags;
|
||||||
p = do_rfc1035_name(p, state->hostname);
|
p = do_rfc1035_name(p, state->hostname, NULL);
|
||||||
if (state->send_domain)
|
if (state->send_domain)
|
||||||
{
|
{
|
||||||
p = do_rfc1035_name(p, state->send_domain);
|
p = do_rfc1035_name(p, state->send_domain, NULL);
|
||||||
*p = 0;
|
*p = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
|
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
|
||||||
static void free_transfer(struct tftp_transfer *transfer);
|
static void free_transfer(struct tftp_transfer *transfer);
|
||||||
static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
|
static ssize_t tftp_err(int err, char *packet, char *message, char *file);
|
||||||
static ssize_t tftp_err_oops(char *packet, char *file);
|
static ssize_t tftp_err_oops(char *packet, char *file);
|
||||||
static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
|
static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
|
||||||
static char *next(char **p, char *end);
|
static char *next(char **p, char *end);
|
||||||
@@ -734,7 +734,7 @@ static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
|
|||||||
if (transfer->opt_blocksize)
|
if (transfer->opt_blocksize)
|
||||||
{
|
{
|
||||||
p += (sprintf(p, "blksize") + 1);
|
p += (sprintf(p, "blksize") + 1);
|
||||||
p += (sprintf(p, "%d", transfer->blocksize) + 1);
|
p += (sprintf(p, "%u", transfer->blocksize) + 1);
|
||||||
}
|
}
|
||||||
if (transfer->opt_transize)
|
if (transfer->opt_transize)
|
||||||
{
|
{
|
||||||
|
|||||||
+47
-29
@@ -111,6 +111,7 @@ u64 rand64(void)
|
|||||||
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
|
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* returns 2 if names is OK but contains one or more underscores */
|
||||||
static int check_name(char *in)
|
static int check_name(char *in)
|
||||||
{
|
{
|
||||||
/* remove trailing .
|
/* remove trailing .
|
||||||
@@ -118,6 +119,7 @@ static int check_name(char *in)
|
|||||||
size_t dotgap = 0, l = strlen(in);
|
size_t dotgap = 0, l = strlen(in);
|
||||||
char c;
|
char c;
|
||||||
int nowhite = 0;
|
int nowhite = 0;
|
||||||
|
int hasuscore = 0;
|
||||||
|
|
||||||
if (l == 0 || l > MAXDNAME) return 0;
|
if (l == 0 || l > MAXDNAME) return 0;
|
||||||
|
|
||||||
@@ -141,13 +143,17 @@ static int check_name(char *in)
|
|||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
else if (c != ' ')
|
else if (c != ' ')
|
||||||
nowhite = 1;
|
{
|
||||||
|
nowhite = 1;
|
||||||
|
if (c == '_')
|
||||||
|
hasuscore = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nowhite)
|
if (!nowhite)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return hasuscore ? 2 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hostnames have a more limited valid charset than domain names
|
/* Hostnames have a more limited valid charset than domain names
|
||||||
@@ -186,56 +192,68 @@ int legal_hostname(char *name)
|
|||||||
char *canonicalise(char *in, int *nomem)
|
char *canonicalise(char *in, int *nomem)
|
||||||
{
|
{
|
||||||
char *ret = NULL;
|
char *ret = NULL;
|
||||||
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2)
|
|
||||||
int rc;
|
int rc;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (nomem)
|
if (nomem)
|
||||||
*nomem = 0;
|
*nomem = 0;
|
||||||
|
|
||||||
if (!check_name(in))
|
if (!(rc = check_name(in)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2)
|
#if defined(HAVE_LIBIDN2) && (!defined(IDN2_VERSION_NUMBER) || IDN2_VERSION_NUMBER < 0x02000003)
|
||||||
#ifdef HAVE_LIBIDN2
|
/* older libidn2 strips underscores, so don't do IDN processing
|
||||||
rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
|
if the name has an underscore (check_name() returned 2) */
|
||||||
if (rc == IDN2_DISALLOWED)
|
if (rc != 2)
|
||||||
rc = idn2_to_ascii_lz(in, &ret, IDN2_TRANSITIONAL);
|
|
||||||
#else
|
|
||||||
rc = idna_to_ascii_lz(in, &ret, 0);
|
|
||||||
#endif
|
#endif
|
||||||
if (rc != IDNA_SUCCESS)
|
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2)
|
||||||
{
|
{
|
||||||
if (ret)
|
# ifdef HAVE_LIBIDN2
|
||||||
free(ret);
|
rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
|
||||||
|
if (rc == IDN2_DISALLOWED)
|
||||||
if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
|
rc = idn2_to_ascii_lz(in, &ret, IDN2_TRANSITIONAL);
|
||||||
|
# else
|
||||||
|
rc = idna_to_ascii_lz(in, &ret, 0);
|
||||||
|
# endif
|
||||||
|
if (rc != IDNA_SUCCESS)
|
||||||
{
|
{
|
||||||
my_syslog(LOG_ERR, _("failed to allocate memory"));
|
if (ret)
|
||||||
*nomem = 1;
|
free(ret);
|
||||||
|
|
||||||
|
if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("failed to allocate memory"));
|
||||||
|
*nomem = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return ret;
|
||||||
}
|
}
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
if ((ret = whine_malloc(strlen(in)+1)))
|
if ((ret = whine_malloc(strlen(in)+1)))
|
||||||
strcpy(ret, in);
|
strcpy(ret, in);
|
||||||
else if (nomem)
|
else if (nomem)
|
||||||
*nomem = 1;
|
*nomem = 1;
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
|
unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
while (sval && *sval)
|
while (sval && *sval)
|
||||||
{
|
{
|
||||||
|
if (limit && p + 1 > (unsigned char*)limit)
|
||||||
|
return p;
|
||||||
|
|
||||||
unsigned char *cp = p++;
|
unsigned char *cp = p++;
|
||||||
for (j = 0; *sval && (*sval != '.'); sval++, j++)
|
for (j = 0; *sval && (*sval != '.'); sval++, j++)
|
||||||
{
|
{
|
||||||
|
if (limit && p + 1 > (unsigned char*)limit)
|
||||||
|
return p;
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
|
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
|
||||||
*p++ = (*(++sval))-1;
|
*p++ = (*(++sval))-1;
|
||||||
@@ -448,13 +466,13 @@ void prettyprint_time(char *buf, unsigned int t)
|
|||||||
{
|
{
|
||||||
unsigned int x, p = 0;
|
unsigned int x, p = 0;
|
||||||
if ((x = t/86400))
|
if ((x = t/86400))
|
||||||
p += sprintf(&buf[p], "%dd", x);
|
p += sprintf(&buf[p], "%ud", x);
|
||||||
if ((x = (t/3600)%24))
|
if ((x = (t/3600)%24))
|
||||||
p += sprintf(&buf[p], "%dh", x);
|
p += sprintf(&buf[p], "%uh", x);
|
||||||
if ((x = (t/60)%60))
|
if ((x = (t/60)%60))
|
||||||
p += sprintf(&buf[p], "%dm", x);
|
p += sprintf(&buf[p], "%um", x);
|
||||||
if ((x = t%60))
|
if ((x = t%60))
|
||||||
p += sprintf(&buf[p], "%ds", x);
|
p += sprintf(&buf[p], "%us", x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user