From 7e4584dc55c9f46ede7613c54046ace96cdbf978 Mon Sep 17 00:00:00 2001 From: Kevin Darbyshire-Bryant Date: Mon, 22 Apr 2013 20:20:11 +0100 Subject: [PATCH] dnsmasq 2.67test2 - a couple of optimisations & corner case bugs (not used in tomato) Simon Kelley the developer is very active at the moment. --- release/src/router/dnsmasq/CHANGELOG | 6 +++++ release/src/router/dnsmasq/VERSION | 2 +- release/src/router/dnsmasq/debian/changelog | 6 +++++ release/src/router/dnsmasq/src/dhcp-common.c | 6 ++--- release/src/router/dnsmasq/src/dnsmasq.h | 4 +-- release/src/router/dnsmasq/src/forward.c | 37 ++++++++++++---------------- release/src/router/dnsmasq/src/option.c | 33 +++++++++++++++---------- 7 files changed, 54 insertions(+), 40 deletions(-) diff --git a/release/src/router/dnsmasq/CHANGELOG b/release/src/router/dnsmasq/CHANGELOG index 93aaf1878e..6cb1b516ce 100644 --- a/release/src/router/dnsmasq/CHANGELOG +++ b/release/src/router/dnsmasq/CHANGELOG @@ -1,3 +1,9 @@ +version 2.67 + Fix crash if upstream server returns SERVFAIL when + --conntrack in use. Thanks to Giacomo Tazzari for finding + this and supplying the patch. + + version 2.66 Add the ability to act as an authoritative DNS server. Dnsmasq can now answer queries from the wider 'net diff --git a/release/src/router/dnsmasq/VERSION b/release/src/router/dnsmasq/VERSION index 6006bcf734..6f229d2daf 100644 --- a/release/src/router/dnsmasq/VERSION +++ b/release/src/router/dnsmasq/VERSION @@ -1 +1 @@ -2.66tomatofinalbf1 +v2.67test2tomato diff --git a/release/src/router/dnsmasq/debian/changelog b/release/src/router/dnsmasq/debian/changelog index 71cc5d81e2..cd09af0592 100644 --- a/release/src/router/dnsmasq/debian/changelog +++ b/release/src/router/dnsmasq/debian/changelog @@ -1,3 +1,9 @@ +dnsmasq (2.67-1) unstable; urgency=low + + * New upstream. + + -- Simon Kelley Fri, 19 Apr 2013 10:23:31 +0000 + dnsmasq (2.66-1) unstable; urgency=low * New upstream. diff --git a/release/src/router/dnsmasq/src/dhcp-common.c b/release/src/router/dnsmasq/src/dhcp-common.c index f4fd0889bc..8de426854e 100644 --- a/release/src/router/dnsmasq/src/dhcp-common.c +++ b/release/src/router/dnsmasq/src/dhcp-common.c @@ -512,7 +512,7 @@ void display_opts6(void) } #endif -u16 lookup_dhcp_opt(int prot, char *name) +int lookup_dhcp_opt(int prot, char *name) { const struct opttab_t *t; int i; @@ -528,10 +528,10 @@ u16 lookup_dhcp_opt(int prot, char *name) if (strcasecmp(t[i].name, name) == 0) return t[i].val; - return 0; + return -1; } -u16 lookup_dhcp_len(int prot, u16 val) +int lookup_dhcp_len(int prot, int val) { const struct opttab_t *t; int i; diff --git a/release/src/router/dnsmasq/src/dnsmasq.h b/release/src/router/dnsmasq/src/dnsmasq.h index 58a3d3323c..0109024ee5 100644 --- a/release/src/router/dnsmasq/src/dnsmasq.h +++ b/release/src/router/dnsmasq/src/dnsmasq.h @@ -1223,8 +1223,8 @@ void log_tags(struct dhcp_netid *netid, u32 xid); int match_bytes(struct dhcp_opt *o, unsigned char *p, int len); void dhcp_update_configs(struct dhcp_config *configs); void display_opts(void); -u16 lookup_dhcp_opt(int prot, char *name); -u16 lookup_dhcp_len(int prot, u16 val); +int lookup_dhcp_opt(int prot, char *name); +int lookup_dhcp_len(int prot, int val); char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len, char *buf, int buf_len); #ifdef HAVE_LINUX_NETWORK diff --git a/release/src/router/dnsmasq/src/forward.c b/release/src/router/dnsmasq/src/forward.c index 1ea25ddc7a..78495ca0b8 100644 --- a/release/src/router/dnsmasq/src/forward.c +++ b/release/src/router/dnsmasq/src/forward.c @@ -328,8 +328,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, struct server *firstsentto = start; int forwarded = 0; - if (udpaddr && option_bool(OPT_ADD_MAC)) - plen = add_mac(header, plen, ((char *) header) + PACKETSZ, udpaddr); + if (option_bool(OPT_ADD_MAC)) + plen = add_mac(header, plen, ((char *) header) + PACKETSZ, &forward->source); while (1) { @@ -372,7 +372,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, if (option_bool(OPT_CONNTRACK)) { unsigned int mark; - if (get_incoming_mark(udpaddr, dst_addr, 0, &mark)) + if (get_incoming_mark(&forward->source, &forward->dest, 0, &mark)) setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int)); } #endif @@ -880,9 +880,12 @@ unsigned char *tcp_request(int confd, time_t now, unsigned short qtype; unsigned int gotname; unsigned char c1, c2; - /* Max TCP packet + slop */ - unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ); - struct dns_header *header; + /* Max TCP packet + slop + size */ + unsigned char *packet = whine_malloc(65536 + MAXDNAME + RRFIXEDSZ + sizeof(u16)); + unsigned char *payload = &packet[2]; + /* largest field in header is 16-bits, so this is still sufficiently aligned */ + struct dns_header *header = (struct dns_header *)payload; + u16 *length = (u16 *)packet; struct server *last_server; struct in_addr dst_addr_4; union mysockaddr peer_addr; @@ -896,14 +899,12 @@ unsigned char *tcp_request(int confd, time_t now, if (!packet || !read_write(confd, &c1, 1, 1) || !read_write(confd, &c2, 1, 1) || !(size = c1 << 8 | c2) || - !read_write(confd, packet, size, 1)) + !read_write(confd, payload, size, 1)) return packet; if (size < (int)sizeof(struct dns_header)) continue; - header = (struct dns_header *)packet; - /* save state of "cd" flag in query */ checking_disabled = header->hb4 & HB4_CD; @@ -1020,12 +1021,9 @@ unsigned char *tcp_request(int confd, time_t now, #endif } - c1 = size >> 8; - c2 = size; + *length = htons(size); - if (!read_write(last_server->tcpfd, &c1, 1, 0) || - !read_write(last_server->tcpfd, &c2, 1, 0) || - !read_write(last_server->tcpfd, packet, size, 0) || + if (!read_write(last_server->tcpfd, packet, size + sizeof(u16), 0) || !read_write(last_server->tcpfd, &c1, 1, 1) || !read_write(last_server->tcpfd, &c2, 1, 1)) { @@ -1035,7 +1033,7 @@ unsigned char *tcp_request(int confd, time_t now, } m = (c1 << 8) | c2; - if (!read_write(last_server->tcpfd, packet, m, 1)) + if (!read_write(last_server->tcpfd, payload, m, 1)) return packet; if (!gotname) @@ -1071,12 +1069,9 @@ unsigned char *tcp_request(int confd, time_t now, check_log_writer(NULL); - c1 = m>>8; - c2 = m; - if (m == 0 || - !read_write(confd, &c1, 1, 0) || - !read_write(confd, &c2, 1, 0) || - !read_write(confd, packet, m, 0)) + *length = htons(m); + + if (m == 0 || !read_write(confd, packet, m + sizeof(u16), 0)) return packet; } } diff --git a/release/src/router/dnsmasq/src/option.c b/release/src/router/dnsmasq/src/option.c index e501b26d99..5f3b58f494 100644 --- a/release/src/router/dnsmasq/src/option.c +++ b/release/src/router/dnsmasq/src/option.c @@ -762,6 +762,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) struct dhcp_netid *np = NULL; u16 opt_len = 0; int is6 = 0; + int option_ok = 0; new->len = 0; new->flags = flags; @@ -781,16 +782,19 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) { new->opt = atoi(arg); opt_len = 0; + option_ok = 1; break; } if (strstr(arg, "option:") == arg) { - new->opt = lookup_dhcp_opt(AF_INET, arg+7); - opt_len = lookup_dhcp_len(AF_INET, new->opt); - /* option: must follow tag and vendor string. */ - if ((opt_len & OT_INTERNAL) && flags != DHOPT_MATCH) - new->opt = 0; + if ((new->opt = lookup_dhcp_opt(AF_INET, arg+7)) != -1) + { + opt_len = lookup_dhcp_len(AF_INET, new->opt); + /* option: must follow tag and vendor string. */ + if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH) + option_ok = 1; + } break; } #ifdef HAVE_DHCP6 @@ -804,13 +808,16 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) { new->opt = atoi(arg+8); opt_len = 0; + option_ok = 1; } else { - new->opt = lookup_dhcp_opt(AF_INET6, arg+8); - opt_len = lookup_dhcp_len(AF_INET6, new->opt); - if ((opt_len & OT_INTERNAL) && flags != DHOPT_MATCH) - new->opt = 0; + if ((new->opt = lookup_dhcp_opt(AF_INET6, arg+8)) != -1) + { + opt_len = lookup_dhcp_len(AF_INET6, new->opt); + if (!(opt_len & OT_INTERNAL) || flags == DHOPT_MATCH) + option_ok = 1; + } } /* option6:| must follow tag and vendor string. */ is6 = 1; @@ -833,7 +840,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) new->flags |= DHOPT_RFC3925; if (flags == DHOPT_MATCH) { - new->opt = 1; /* avoid error below */ + option_ok = 1; break; } } @@ -860,16 +867,16 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags) if (opt_len == 0 && !(new->flags & DHOPT_RFC3925)) - opt_len = lookup_dhcp_len(AF_INET6 ,new->opt); + opt_len = lookup_dhcp_len(AF_INET6, new->opt); } else #endif if (opt_len == 0 && !(new->flags & (DHOPT_VENDOR | DHOPT_ENCAPSULATE | DHOPT_RFC3925))) - opt_len = lookup_dhcp_len(AF_INET ,new->opt); + opt_len = lookup_dhcp_len(AF_INET, new->opt); /* option may be missing with rfc3925 match */ - if (new->opt == 0) + if (!option_ok) ret_err(_("bad dhcp-option")); if (comma) -- 2.11.4.GIT