From 18a48b3690f179808f546e30bb96eed8f514fa0d Mon Sep 17 00:00:00 2001 From: Daniel Collins Date: Thu, 6 Jan 2022 00:20:05 +0000 Subject: [PATCH 01/33] Implements a SetLocaliseQueriesOption D-Bus method. For setting the state of the -y/--localise-queries option. Signed-off-by: DL6ER --- src/dnsmasq/dbus.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/dnsmasq/dbus.c b/src/dnsmasq/dbus.c index d746b9a6..4eae7899 100644 --- a/src/dnsmasq/dbus.c +++ b/src/dnsmasq/dbus.c @@ -52,6 +52,9 @@ const char* introspection_xml_template = " \n" " \n" " \n" +" \n" +" \n" +" \n" " \n" " \n" " \n" @@ -694,6 +697,10 @@ DBusHandlerResult message_handler(DBusConnection *connection, { reply = dbus_set_bool(message, OPT_FILTER, "filterwin2k"); } + else if (strcmp(method, "SetLocaliseQueriesOption") == 0) + { + reply = dbus_set_bool(message, OPT_LOCALISE, "localise-queries"); + } else if (strcmp(method, "SetBogusPrivOption") == 0) { reply = dbus_set_bool(message, OPT_BOGUSPRIV, "bogus-priv"); From e3d57af89318a82babc01591d567cfa87e36e1a4 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Sun, 9 Jan 2022 23:21:55 +0000 Subject: [PATCH 02/33] Handle malformed query packets sensibly. Previously, hash_questions() would return a random hash if the packet was malformed, and probably the hash of a previous query. Now handle this as an error. Signed-off-by: Your Name Signed-off-by: DL6ER --- src/dnsmasq/forward.c | 74 ++++++++++++++++++++++-------------- src/dnsmasq/hash-questions.c | 8 ++-- 2 files changed, 49 insertions(+), 33 deletions(-) diff --git a/src/dnsmasq/forward.c b/src/dnsmasq/forward.c index e1061ecd..4b2eb122 100644 --- a/src/dnsmasq/forward.c +++ b/src/dnsmasq/forward.c @@ -280,6 +280,15 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, /* new query */ if (!forward) { + /* If the query is malformed, we can't forward it because + we can't get a reliable hash to recognise the answer. */ + if (!hash) + { + flags = 0; + ede = EDE_INVALID_DATA; + goto reply; + } + if (lookup_domain(daemon->namebuff, gotname, &first, &last)) flags = is_local_answer(now, first, daemon->namebuff); else @@ -889,8 +898,10 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header, STAT_ISEQUAL(status, STAT_NEED_KEY) ? T_DNSKEY : T_DS, server->edns_pktsz); flags = STAT_ISEQUAL(status, STAT_NEED_KEY) ? FREC_DNSKEY_QUERY : FREC_DS_QUERY; - hash = hash_questions(header, nn, daemon->namebuff); + if (!(hash = hash_questions(header, nn, daemon->namebuff))) + return; + if ((new = lookup_frec_by_query(hash, flags, FREC_DNSKEY_QUERY | FREC_DS_QUERY))) { forward->next_dependent = new->dependent; @@ -1767,13 +1778,16 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet, unsigned char *payload = &packet[2]; struct dns_header *header = (struct dns_header *)payload; unsigned char c1, c2; - unsigned char hash[HASH_SIZE]; + unsigned char hash[HASH_SIZE], *hashp; unsigned int rsize; (void)mark; (void)have_mark; - memcpy(hash, hash_questions(header, (unsigned int)qsize, daemon->namebuff), HASH_SIZE); + if (!(hashp = hash_questions(header, (unsigned int)qsize, daemon->namebuff))) + return 0; + + memcpy(hash, hashp, HASH_SIZE); while (1) { @@ -1854,7 +1868,7 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet, someone might be attempting to insert bogus values into the cache by sending replies containing questions and bogus answers. Try another server, or give up */ - if (memcmp(hash, hash_questions(header, rsize, daemon->namebuff), HASH_SIZE) != 0) + if (!(hashp = hash_questions(header, rsize, daemon->namebuff)) || memcmp(hash, hashp, HASH_SIZE) != 0) continue; serv->flags |= SERV_GOT_TCP; @@ -2660,28 +2674,29 @@ static struct frec *lookup_frec(unsigned short id, int fd, void *hash, int *firs struct server *s; int first, last; struct randfd_list *fdl; - - for(f = daemon->frec_list; f; f = f->next) - if (f->sentto && f->new_id == id && - (memcmp(hash, f->hash, HASH_SIZE) == 0)) - { - filter_servers(f->sentto->arrayposn, F_SERVER, firstp, lastp); - /* sent from random port */ - for (fdl = f->rfds; fdl; fdl = fdl->next) - if (fdl->rfd->fd == fd) - return f; - - /* Sent to upstream from socket associated with a server. - Note we have to iterate over all the possible servers, since they may - have different bound sockets. */ - for (first = *firstp, last = *lastp; first != last; first++) - { - s = daemon->serverarray[first]; - if (s->sfd && s->sfd->fd == fd) + if (hash) + for (f = daemon->frec_list; f; f = f->next) + if (f->sentto && f->new_id == id && + (memcmp(hash, f->hash, HASH_SIZE) == 0)) + { + filter_servers(f->sentto->arrayposn, F_SERVER, firstp, lastp); + + /* sent from random port */ + for (fdl = f->rfds; fdl; fdl = fdl->next) + if (fdl->rfd->fd == fd) return f; - } - } + + /* Sent to upstream from socket associated with a server. + Note we have to iterate over all the possible servers, since they may + have different bound sockets. */ + for (first = *firstp, last = *lastp; first != last; first++) + { + s = daemon->serverarray[first]; + if (s->sfd && s->sfd->fd == fd) + return f; + } + } return NULL; } @@ -2690,11 +2705,12 @@ static struct frec *lookup_frec_by_query(void *hash, unsigned int flags, unsigne { struct frec *f; - for(f = daemon->frec_list; f; f = f->next) - if (f->sentto && - (f->flags & flagmask) == flags && - memcmp(hash, f->hash, HASH_SIZE) == 0) - return f; + if (hash) + for(f = daemon->frec_list; f; f = f->next) + if (f->sentto && + (f->flags & flagmask) == flags && + memcmp(hash, f->hash, HASH_SIZE) == 0) + return f; return NULL; } diff --git a/src/dnsmasq/hash-questions.c b/src/dnsmasq/hash-questions.c index f41023b6..4b1dd919 100644 --- a/src/dnsmasq/hash-questions.c +++ b/src/dnsmasq/hash-questions.c @@ -55,7 +55,7 @@ unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name char *cp, c; if (!extract_name(header, plen, &p, name, 1, 4)) - break; /* bad packet */ + return NULL; /* bad packet */ for (cp = name; (c = *cp); cp++) if (c >= 'A' && c <= 'Z') @@ -67,7 +67,7 @@ unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name p += 4; if (!CHECK_LEN(header, p, plen, 0)) - break; /* bad packet */ + return NULL; /* bad packet */ } hash->digest(ctx, hash->digest_size, digest); @@ -109,7 +109,7 @@ unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name char *cp, c; if (!extract_name(header, plen, &p, name, 1, 4)) - break; /* bad packet */ + return NULL; /* bad packet */ for (cp = name; (c = *cp); cp++) if (c >= 'A' && c <= 'Z') @@ -121,7 +121,7 @@ unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name p += 4; if (!CHECK_LEN(header, p, plen, 0)) - break; /* bad packet */ + return NULL; /* bad packet */ } sha256_final(&ctx, digest); From 408dd1365277a16f7d728b8e4c0c64443009b9df Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Tue, 11 Jan 2022 00:09:15 +0000 Subject: [PATCH 03/33] Overhaul code which sends DNSSEC queries. There are two functional changes in this commit. 1) When searching for an in-flight DNSSEC query to use (rather than starting a new one), compare the already sent query (stored in the frec "stash" field, rather than using the hash of the query. This is probably faster (no hash calculation) and eliminates having to worry about the consequences of a hash collision. 2) Check for dependency loops in DNSSEC validation, say validating A requires DS B and validating DS B requires DNSKEY C and validating DNSKEY C requires DS B. This should never happen in correctly signed records, but it's likely the case that sufficiently broken ones can cause our validation code requests to exhibit cycles. The result is that the ->blocking_query list can form a cycle, and under certain circumstances that can lock us in an infinite loop. Instead we transform the situation into an ABANDONED state. Signed-off-by: Your Name Signed-off-by: DL6ER --- src/dnsmasq/forward.c | 196 ++++++++++++++++++++++++++---------------- 1 file changed, 122 insertions(+), 74 deletions(-) diff --git a/src/dnsmasq/forward.c b/src/dnsmasq/forward.c index 4b2eb122..b30b775d 100644 --- a/src/dnsmasq/forward.c +++ b/src/dnsmasq/forward.c @@ -20,6 +20,7 @@ static struct frec *get_new_frec(time_t now, struct server *serv, int force); static struct frec *lookup_frec(unsigned short id, int fd, void *hash, int *firstp, int *lastp); static struct frec *lookup_frec_by_query(void *hash, unsigned int flags, unsigned int flagmask); +static struct frec *lookup_frec_dnssec(char *target, int class, int flags, struct dns_header *header); static unsigned short get_id(void); static void free_frec(struct frec *f); @@ -879,90 +880,104 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header, if (STAT_ISEQUAL(status, STAT_NEED_DS) || STAT_ISEQUAL(status, STAT_NEED_KEY)) { struct frec *new = NULL; - int serverind; struct blockdata *stash; /* Now save reply pending receipt of key data */ - if ((serverind = dnssec_server(forward->sentto, daemon->keyname, NULL, NULL)) != -1 && - (stash = blockdata_alloc((char *)header, plen))) + if ((stash = blockdata_alloc((char *)header, plen))) { - struct server *server = daemon->serverarray[serverind]; - struct frec *orig; - unsigned int flags; - void *hash; - size_t nn; - /* validate routines leave name of required record in daemon->keyname */ - nn = dnssec_generate_query(header, ((unsigned char *) header) + server->edns_pktsz, - daemon->keyname, forward->class, - STAT_ISEQUAL(status, STAT_NEED_KEY) ? T_DNSKEY : T_DS, server->edns_pktsz); - - flags = STAT_ISEQUAL(status, STAT_NEED_KEY) ? FREC_DNSKEY_QUERY : FREC_DS_QUERY; + unsigned int flags = STAT_ISEQUAL(status, STAT_NEED_KEY) ? FREC_DNSKEY_QUERY : FREC_DS_QUERY; - if (!(hash = hash_questions(header, nn, daemon->namebuff))) - return; - - if ((new = lookup_frec_by_query(hash, flags, FREC_DNSKEY_QUERY | FREC_DS_QUERY))) + if ((new = lookup_frec_dnssec(daemon->keyname, forward->class, flags, header))) { - forward->next_dependent = new->dependent; - new->dependent = forward; - /* Make consistent, only replace query copy with unvalidated answer - when we set ->blocking_query. */ - if (forward->stash) - blockdata_free(forward->stash); - forward->blocking_query = new; - forward->stash_len = plen; - forward->stash = stash; - return; + /* This is tricky; it detects loops in the dependency + graph for DNSSEC validation, say validating A requires DS B + and validating DS B requires DNSKEY C and validating DNSKEY C requires DS B. + This should never happen in correctly signed records, but it's + likely the case that sufficiently broken ones can cause our validation + code requests to exhibit cycles. The result is that the ->blocking_query list + can form a cycle, and under certain circumstances that can lock us in + an infinite loop. Here we transform the situation into ABANDONED. */ + struct frec *f; + for (f = new; f; f = f->blocking_query) + if (f == forward) + break; + + if (!f) + { + forward->next_dependent = new->dependent; + new->dependent = forward; + /* Make consistent, only replace query copy with unvalidated answer + when we set ->blocking_query. */ + if (forward->stash) + blockdata_free(forward->stash); + forward->blocking_query = new; + forward->stash_len = plen; + forward->stash = stash; + return; + } + + my_syslog(LOG_WARNING, _("detected DNSSEC dependency loop involving %s"), daemon->keyname); } - - /* Find the original query that started it all.... */ - for (orig = forward; orig->dependent; orig = orig->dependent); - - /* Make sure we don't expire and free the orig frec during the - allocation of a new one: third arg of get_new_frec() does that. */ - if (--orig->work_counter == 0 || !(new = get_new_frec(now, server, 1))) - blockdata_free(stash); /* don't leak this on failure. */ else { - int fd; - struct frec *next = new->next; - - *new = *forward; /* copy everything, then overwrite */ - new->next = next; - new->blocking_query = NULL; + struct server *server; + struct frec *orig; + void *hash; + size_t nn; + int serverind, fd; + struct randfd_list *rfds = NULL; - new->frec_src.log_id = daemon->log_display_id = ++daemon->log_id; - new->sentto = server; - new->rfds = NULL; - new->frec_src.next = NULL; - new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA); - new->flags |= flags; - new->forwardall = 0; + /* Find the original query that started it all.... */ + for (orig = forward; orig->dependent; orig = orig->dependent); - forward->next_dependent = NULL; - new->dependent = forward; /* to find query awaiting new one. */ - - /* Make consistent, only replace query copy with unvalidated answer - when we set ->blocking_query. */ - forward->blocking_query = new; - if (forward->stash) - blockdata_free(forward->stash); - forward->stash_len = plen; - forward->stash = stash; - - memcpy(new->hash, hash, HASH_SIZE); - new->new_id = get_id(); - header->id = htons(new->new_id); - /* Save query for retransmission */ - new->stash = blockdata_alloc((char *)header, nn); - new->stash_len = nn; - - /* Don't resend this. */ - daemon->srv_save = NULL; - - if ((fd = allocate_rfd(&new->rfds, server)) != -1) + /* Make sure we don't expire and free the orig frec during the + allocation of a new one: third arg of get_new_frec() does that. */ + if ((serverind = dnssec_server(forward->sentto, daemon->keyname, NULL, NULL)) != -1 && + (server = daemon->serverarray[serverind]) && + (nn = dnssec_generate_query(header, ((unsigned char *) header) + server->edns_pktsz, + daemon->keyname, forward->class, + STAT_ISEQUAL(status, STAT_NEED_KEY) ? T_DNSKEY : T_DS, server->edns_pktsz)) && + (hash = hash_questions(header, nn, daemon->namebuff)) && + --orig->work_counter != 0 && + (fd = allocate_rfd(&rfds, server)) != -1 && + (new = get_new_frec(now, server, 1))) { + struct frec *next = new->next; + + *new = *forward; /* copy everything, then overwrite */ + new->next = next; + new->blocking_query = NULL; + + new->frec_src.log_id = daemon->log_display_id = ++daemon->log_id; + new->sentto = server; + new->rfds = rfds; + new->frec_src.next = NULL; + new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA); + new->flags |= flags; + new->forwardall = 0; + + forward->next_dependent = NULL; + new->dependent = forward; /* to find query awaiting new one. */ + + /* Make consistent, only replace query copy with unvalidated answer + when we set ->blocking_query. */ + forward->blocking_query = new; + if (forward->stash) + blockdata_free(forward->stash); + forward->stash_len = plen; + forward->stash = stash; + + memcpy(new->hash, hash, HASH_SIZE); + new->new_id = get_id(); + header->id = htons(new->new_id); + /* Save query for retransmission and de-dup */ + new->stash = blockdata_alloc((char *)header, nn); + new->stash_len = nn; + + /* Don't resend this. */ + daemon->srv_save = NULL; + #ifdef HAVE_CONNTRACK if (option_bool(OPT_CONNTRACK)) set_outgoing_mark(orig, fd); @@ -971,16 +986,19 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header, F_NOEXTRA | F_DNSSEC, daemon->keyname, "dnssec-query", STAT_ISEQUAL(status, STAT_NEED_KEY) ? T_DNSKEY : T_DS); server->queries++; + return; } - return; + free_rfds(&rfds); /* error unwind */ } + + blockdata_free(stash); /* don't leak this on failure. */ } /* sending DNSSEC query failed. */ status = STAT_ABANDONED; } - + /* Validated original answer, all done. */ if (!forward->dependent) return_reply(now, forward, header, plen, status); @@ -2706,7 +2724,7 @@ static struct frec *lookup_frec_by_query(void *hash, unsigned int flags, unsigne struct frec *f; if (hash) - for(f = daemon->frec_list; f; f = f->next) + for (f = daemon->frec_list; f; f = f->next) if (f->sentto && (f->flags & flagmask) == flags && memcmp(hash, f->hash, HASH_SIZE) == 0) @@ -2715,6 +2733,36 @@ static struct frec *lookup_frec_by_query(void *hash, unsigned int flags, unsigne return NULL; } +/* DNSSEC frecs have the complete query in the block stash. + Search for an existing query using that. */ +static struct frec *lookup_frec_dnssec(char *target, int class, int flags, struct dns_header *header) +{ + struct frec *f; + + for (f = daemon->frec_list; f; f = f->next) + if (f->sentto && + (f->flags & flags) && + blockdata_retrieve(f->stash, f->stash_len, (void *)header)) + { + unsigned char *p = (unsigned char *)(header+1); + int hclass; + + if (extract_name(header, f->stash_len, &p, target, 0, 4) != 1) + continue; + + p += 2; /* type, known from flags */ + GETSHORT(hclass, p); + + if (class != hclass) + continue; + + return f; + } + + return NULL; +} + + /* Send query packet again, if we can. */ void resend_query() { From 2d65d55df0ec00613bfa6ea8e7cd22e3858befd6 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Tue, 11 Jan 2022 21:56:40 +0000 Subject: [PATCH 04/33] Log port numbers in server addresses when non-standard ports in use. Signed-off-by: Your Name Signed-off-by: DL6ER --- src/dnsmasq/cache.c | 14 +++++++++++--- src/dnsmasq/forward.c | 20 ++++++++++++++------ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/dnsmasq/cache.c b/src/dnsmasq/cache.c index 449c884f..29ed7590 100644 --- a/src/dnsmasq/cache.c +++ b/src/dnsmasq/cache.c @@ -1994,6 +1994,7 @@ void _log_query(unsigned int flags, char *name, union all_addr *addr, char *arg, char *source, *dest = arg; char *verb = "is"; char *extra = ""; + char portstring[7]; /* space for # */ FTL_hook(flags, name, addr, arg, daemon->log_display_id, type, file, line); @@ -2001,7 +2002,7 @@ void _log_query(unsigned int flags, char *name, union all_addr *addr, char *arg, return; /* build query type string if requested */ - if(type > 0) + if (!(flags & (F_SERVER | F_IPSET)) && type > 0) arg = querystr(arg, type); #ifdef HAVE_DNSSEC @@ -2037,8 +2038,15 @@ void _log_query(unsigned int flags, char *name, union all_addr *addr, char *arg, } } else if (flags & (F_IPV4 | F_IPV6)) - inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6, - addr, daemon->addrbuff, ADDRSTRLEN); + { + inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6, + addr, daemon->addrbuff, ADDRSTRLEN); + if ((flags & F_SERVER) && type != NAMESERVER_PORT) + { + extra = portstring; + sprintf(portstring, "#%u", type); + } + } else dest = arg; } diff --git a/src/dnsmasq/forward.c b/src/dnsmasq/forward.c index b30b775d..4d80d256 100644 --- a/src/dnsmasq/forward.c +++ b/src/dnsmasq/forward.c @@ -126,9 +126,17 @@ static void set_outgoing_mark(struct frec *forward, int fd) static void _log_query_mysockaddr(unsigned int flags, char *name, union mysockaddr *addr, char *arg, unsigned short type, const int line) { if (addr->sa.sa_family == AF_INET) - _log_query(flags | F_IPV4, name, (union all_addr *)&addr->in.sin_addr, arg, type, __FILE__, line); + { + if (flags & F_SERVER) + type = ntohs(addr->in.sin_port); + _log_query(flags | F_IPV4, name, (union all_addr *)&addr->in.sin_addr, arg, type, __FILE__, line); + } else - _log_query(flags | F_IPV6, name, (union all_addr *)&addr->in6.sin6_addr, arg, type, __FILE__, line); + { + if (flags & F_SERVER) + type = ntohs(addr->in6.sin6_port); + _log_query(flags | F_IPV6, name, (union all_addr *)&addr->in6.sin6_addr, arg, type, __FILE__, line); + } } static void server_send(struct server *server, int fd, @@ -983,8 +991,8 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header, set_outgoing_mark(orig, fd); #endif server_send_log(server, fd, header, nn, DUMP_SEC_QUERY, - F_NOEXTRA | F_DNSSEC, daemon->keyname, - "dnssec-query", STAT_ISEQUAL(status, STAT_NEED_KEY) ? T_DNSKEY : T_DS); + F_NOEXTRA | F_DNSSEC | F_SERVER, daemon->keyname, + STAT_ISEQUAL(status, STAT_NEED_KEY) ? "dnssec-query[DNSKEY]" : "dnssec-query[DS]", 0); server->queries++; return; } @@ -1955,8 +1963,8 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si log_save = daemon->log_display_id; daemon->log_display_id = ++daemon->log_id; - log_query_mysockaddr(F_NOEXTRA | F_DNSSEC, keyname, &server->addr, - "dnssec-query", STAT_ISEQUAL(new_status, STAT_NEED_KEY) ? T_DNSKEY : T_DS); + log_query_mysockaddr(F_NOEXTRA | F_DNSSEC | F_SERVER, keyname, &server->addr, + STAT_ISEQUAL(status, STAT_NEED_KEY) ? "dnssec-query[DNSKEY]" : "dnssec-query[DS]", 0); new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount); From 0eacb4096e8c10af6e3bf3e4b9209b29565b3ebd Mon Sep 17 00:00:00 2001 From: Dominik Derigs Date: Sat, 18 Dec 2021 10:08:01 +0100 Subject: [PATCH 05/33] Fix header of cache dump. The width of the host and address fields are 30 and 40 characters, respectively. Signed-off-by: DL6ER Signed-off-by: Your Name Signed-off-by: DL6ER --- src/dnsmasq/cache.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dnsmasq/cache.c b/src/dnsmasq/cache.c index 29ed7590..8aae6b33 100644 --- a/src/dnsmasq/cache.c +++ b/src/dnsmasq/cache.c @@ -1797,7 +1797,8 @@ void dump_cache(time_t now) { struct crec *cache ; int i; - my_syslog(LOG_INFO, "Host Address Flags Expires"); + my_syslog(LOG_INFO, "Host Address Flags Expires"); + my_syslog(LOG_INFO, "------------------------------ ---------------------------------------- --------- ------------------------"); for (i=0; ihash_next) From 44611db613222cf87048aeea0af9aca03eb84db8 Mon Sep 17 00:00:00 2001 From: Dominik Derigs Date: Thu, 30 Dec 2021 10:53:24 +0100 Subject: [PATCH 06/33] Extend cache dump: "!" as type for non-terminals, new flag "C" for config-provided and log source when applicable. Signed-off-by: DL6ER Signed-off-by: Your Name Signed-off-by: DL6ER --- src/dnsmasq/cache.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/dnsmasq/cache.c b/src/dnsmasq/cache.c index 8aae6b33..7f6e03ab 100644 --- a/src/dnsmasq/cache.c +++ b/src/dnsmasq/cache.c @@ -1797,8 +1797,8 @@ void dump_cache(time_t now) { struct crec *cache ; int i; - my_syslog(LOG_INFO, "Host Address Flags Expires"); - my_syslog(LOG_INFO, "------------------------------ ---------------------------------------- --------- ------------------------"); + my_syslog(LOG_INFO, "Host Address Flags Expires Source"); + my_syslog(LOG_INFO, "------------------------------ ---------------------------------------- ---------- ------------------------ ------------"); for (i=0; ihash_next) @@ -1856,7 +1856,10 @@ void dump_cache(time_t now) else if (cache->flags & F_DNSKEY) t = "K"; #endif - p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s ", a, t, + else /* non-terminal */ + t = "!"; + + p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s%s ", a, t, cache->flags & F_FORWARD ? "F" : " ", cache->flags & F_REVERSE ? "R" : " ", cache->flags & F_IMMORTAL ? "I" : " ", @@ -1864,14 +1867,16 @@ void dump_cache(time_t now) cache->flags & F_NEG ? "N" : " ", cache->flags & F_NXDOMAIN ? "X" : " ", cache->flags & F_HOSTS ? "H" : " ", + cache->flags & F_CONFIG ? "C" : " ", cache->flags & F_DNSSECOK ? "V" : " "); #ifdef HAVE_BROKEN_RTC - p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now)); + p += sprintf(p, "%-24lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now)); #else - p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd))); - /* ctime includes trailing \n - eat it */ - *(p-1) = 0; + p += sprintf(p, "%-24.24s", cache->flags & F_IMMORTAL ? "" : ctime(&(cache->ttd))); #endif + if(cache->flags & (F_HOSTS | F_CONFIG) && cache->uid > 0) + p += sprintf(p, " %s", record_source(cache->uid)); + my_syslog(LOG_INFO, "%s", daemon->namebuff); } } From 5850a536258404f39113e518254bf5bddac34426 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Tue, 11 Jan 2022 22:36:01 +0000 Subject: [PATCH 07/33] Log source of ignored query when local-service is used. Thanks to Dominik Derigs for the initial patch. Signed-off-by: Your Name Signed-off-by: DL6ER --- src/dnsmasq/forward.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/dnsmasq/forward.c b/src/dnsmasq/forward.c index 4d80d256..276cdd13 100644 --- a/src/dnsmasq/forward.c +++ b/src/dnsmasq/forward.c @@ -1492,7 +1492,8 @@ void receive_query(struct listener *listen, time_t now) static int warned = 0; if (!warned) { - my_syslog(LOG_WARNING, _("Ignoring query from non-local network")); + prettyprint_addr(&source_addr, daemon->addrbuff); + my_syslog(LOG_WARNING, _("ignoring query from non-local network %s (logged only once)"), daemon->addrbuff); warned = 1; } return; @@ -2067,7 +2068,8 @@ unsigned char *tcp_request(int confd, time_t now, } if (!addr) { - my_syslog(LOG_WARNING, _("Ignoring query from non-local network")); + prettyprint_addr(&peer_addr, daemon->addrbuff); + my_syslog(LOG_WARNING, _("ignoring query from non-local network %s"), daemon->addrbuff); return packet; } } From 9522a51ccd23b08357603267e04206934d7d4eca Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Tue, 11 Jan 2022 22:48:14 +0000 Subject: [PATCH 08/33] Fix FTBFS when HAVE_DNSSEC not defined. Signed-off-by: Your Name Signed-off-by: DL6ER --- src/dnsmasq/forward.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/dnsmasq/forward.c b/src/dnsmasq/forward.c index 276cdd13..5589722b 100644 --- a/src/dnsmasq/forward.c +++ b/src/dnsmasq/forward.c @@ -20,7 +20,9 @@ static struct frec *get_new_frec(time_t now, struct server *serv, int force); static struct frec *lookup_frec(unsigned short id, int fd, void *hash, int *firstp, int *lastp); static struct frec *lookup_frec_by_query(void *hash, unsigned int flags, unsigned int flagmask); +#ifdef HAVE_DNSSEC static struct frec *lookup_frec_dnssec(char *target, int class, int flags, struct dns_header *header); +#endif static unsigned short get_id(void); static void free_frec(struct frec *f); @@ -2743,6 +2745,7 @@ static struct frec *lookup_frec_by_query(void *hash, unsigned int flags, unsigne return NULL; } +#ifdef HAVE_DNSSEC /* DNSSEC frecs have the complete query in the block stash. Search for an existing query using that. */ static struct frec *lookup_frec_dnssec(char *target, int class, int flags, struct dns_header *header) @@ -2771,7 +2774,7 @@ static struct frec *lookup_frec_dnssec(char *target, int class, int flags, struc return NULL; } - +#endif /* Send query packet again, if we can. */ void resend_query() From 9f2e225b0e72c1c131a57c21f5dc292943083cb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= Date: Mon, 10 Jan 2022 12:34:42 +0100 Subject: [PATCH 09/33] Add root group writeable flag to log file Some systems strips even root process capability of writing to different users file. That include systemd under Fedora. When log-facility=/var/log/dnsmasq.log is used, log file with mode 0640 is created. But restart then fails, because such log file can be used only when created new. Existing file cannot be opened by root when starting, causing fatal error. Avoid that by adding root group writeable flag. Ensure group is always root when granting write access. If it is anything else, administrator has to configure correct rights. Signed-off-by: Your Name Signed-off-by: DL6ER --- src/dnsmasq/log.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/dnsmasq/log.c b/src/dnsmasq/log.c index 83f9ee5b..8963841e 100644 --- a/src/dnsmasq/log.c +++ b/src/dnsmasq/log.c @@ -101,10 +101,23 @@ int log_start(struct passwd *ent_pw, int errfd) /* If we're running as root and going to change uid later, change the ownership here so that the file is always owned by the dnsmasq user. Then logrotate can just copy the owner. - Failure of the chown call is OK, (for instance when started as non-root) */ - if (log_to_file && !log_stderr && ent_pw && ent_pw->pw_uid != 0 && - fchown(log_fd, ent_pw->pw_uid, -1) != 0) - ret = errno; + Failure of the chown call is OK, (for instance when started as non-root). + + If we've created a file with group-id root, we also make + the file group-writable. This gives processes in the root group + write access to the file and avoids the problem that on some systems, + once the file is owned by the dnsmasq user, it can't be written + whilst dnsmasq is running as root during startup. + */ + if (log_to_file && !log_stderr && ent_pw && ent_pw->pw_uid != 0) + { + struct stat ls; + if (getgid() == 0 && fstat(log_fd, &ls) == 0 && ls.st_gid == 0 && + (ls.st_mode & S_IWGRP) == 0) + (void)fchmod(log_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP); + if (fchown(log_fd, ent_pw->pw_uid, -1) != 0) + ret = errno; + } return ret; } @@ -119,7 +132,7 @@ int log_reopen(char *log_file) /* NOTE: umask is set to 022 by the time this gets called */ if (log_file) - log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP); + log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP); else { #if defined(HAVE_SOLARIS_NETWORK) || defined(__ANDROID__) From e96987d8233a044af87da23d7a25e18fa4988ad4 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 12 Jan 2022 20:43:48 +0100 Subject: [PATCH 10/33] Use upstream destination port as reported by dnsmasq instead of reverse-engineering it ourselves from the sockaddr Signed-off-by: DL6ER --- src/dnsmasq_interface.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/src/dnsmasq_interface.c b/src/dnsmasq_interface.c index e19f1304..1cb410e1 100644 --- a/src/dnsmasq_interface.c +++ b/src/dnsmasq_interface.c @@ -60,7 +60,7 @@ static bool _FTL_check_blocking(int queryID, int domainID, int clientID, const c static unsigned long converttimeval(const struct timeval time) __attribute__((const)); static enum query_status detect_blocked_IP(const unsigned short flags, const union all_addr *addr, const queriesData *query, const domainsData *domain); static void query_blocked(queriesData* query, domainsData* domain, clientsData* client, const unsigned char new_status); -static void FTL_forwarded(const unsigned int flags, const char *name, const union all_addr *addr, const int id, const char* file, const int line); +static void FTL_forwarded(const unsigned int flags, const char *name, const union all_addr *addr, unsigned short port, const int id, const char* file, const int line); static void FTL_reply(const unsigned int flags, const char *name, const union all_addr *addr, const char* arg, const int id, const char* file, const int line); static void FTL_upstream_error(const union all_addr *addr, const int id, const char* file, const int line); static void FTL_dnssec(const char *result, const union all_addr *addr, const int id, const char* file, const int line); @@ -116,8 +116,8 @@ void FTL_hook(unsigned int flags, char *name, union all_addr *addr, char *arg, i if((flags & F_QUERY) && (flags & F_FORWARD)) ; // New query, handled by FTL_new_query via separate call else if(flags & F_FORWARD && flags & F_SERVER) - // forwarded upstream - FTL_forwarded(flags, name, addr, id, path, line); + // forwarded upstream (type is used to store the upstream port) + FTL_forwarded(flags, name, addr, type, id, path, line); else if(flags == F_SECSTAT) // DNSSEC validation result FTL_dnssec(arg, addr, id, path, line); @@ -131,19 +131,9 @@ void FTL_hook(unsigned int flags, char *name, union all_addr *addr, char *arg, i return; const ednsData edns = { 0 }; - union mysockaddr saddr = {{ 0 }}; - if(flags & F_IPV4) - { - saddr.in.sin_addr = addr->addr4; - saddr.sa.sa_family = AF_INET; - } - else - { - memcpy(&saddr.in6.sin6_addr, &addr->addr6, sizeof(addr->addr6)); - saddr.sa.sa_family = AF_INET; - } _FTL_new_query(flags, name, NULL, arg, type, id, &edns, INTERNAL, file, line); - FTL_forwarded(flags, name, addr, id, path, line); + // forwarded upstream (type is used to store the upstream port) + FTL_forwarded(flags, name, addr, type, id, path, line); } else if(flags & F_AUTH) ; // Ignored @@ -1639,7 +1629,7 @@ bool _FTL_CNAME(const char *domain, const struct crec *cpp, const int id, const } static void FTL_forwarded(const unsigned int flags, const char *name, const union all_addr *addr, - const int id, const char* file, const int line) + unsigned short port, const int id, const char* file, const int line) { // Save that this query got forwarded to an upstream server @@ -1657,19 +1647,23 @@ static void FTL_forwarded(const unsigned int flags, const char *name, const unio { inet_ntop(AF_INET, addr, dest, ADDRSTRLEN); // Reverse-engineer port from underlying sockaddr_in structure - const in_port_t *port = (in_port_t*)((void*)addr + const in_port_t *rport = (in_port_t*)((void*)addr - offsetof(struct sockaddr_in, sin_addr) + offsetof(struct sockaddr_in, sin_port)); - upstreamPort = ntohs(*port); + upstreamPort = ntohs(*rport); + if(upstreamPort != port) + logg("ERR: Port mismatch for %s: we derived %d, dnsmasq told us %d", dest, upstreamPort, port); } else { inet_ntop(AF_INET6, addr, dest, ADDRSTRLEN); // Reverse-engineer port from underlying sockaddr_in6 structure - const in_port_t *port = (in_port_t*)((void*)addr + const in_port_t *rport = (in_port_t*)((void*)addr - offsetof(struct sockaddr_in6, sin6_addr) + offsetof(struct sockaddr_in6, sin6_port)); - upstreamPort = ntohs(*port); + upstreamPort = ntohs(*rport); + if(upstreamPort != port) + logg("ERR: Port mismatch for %s: we derived %d, dnsmasq told us %d", dest, upstreamPort, port); } } From 380eaab4eda623506c6f62e188f896a9694b2257 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 12 Jan 2022 21:11:17 +0100 Subject: [PATCH 11/33] Tests: Adjust expected dnsmasq warnings Signed-off-by: DL6ER --- test/dnsmasq_warnings | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/dnsmasq_warnings b/test/dnsmasq_warnings index 0ccef1a5..8ad51608 100644 --- a/test/dnsmasq_warnings +++ b/test/dnsmasq_warnings @@ -82,12 +82,14 @@ src/dnsmasq/forward.c my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff); src/dnsmasq/forward.c my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff); +src/dnsmasq/forward.c + my_syslog(LOG_WARNING, _("detected DNSSEC dependency loop involving %s"), daemon->keyname); src/dnsmasq/forward.c my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ); src/dnsmasq/forward.c - my_syslog(LOG_WARNING, _("Ignoring query from non-local network")); + my_syslog(LOG_WARNING, _("ignoring query from non-local network %s (logged only once)"), daemon->addrbuff); src/dnsmasq/forward.c - my_syslog(LOG_WARNING, _("Ignoring query from non-local network")); + my_syslog(LOG_WARNING, _("ignoring query from non-local network %s"), daemon->addrbuff); src/dnsmasq/forward.c my_syslog(LOG_WARNING, _("Maximum number of concurrent DNS queries reached (max: %d)"), daemon->ftabsize); src/dnsmasq/forward.c From d7c2043744f0fd45dd87172e76504b4cb5437422 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Wed, 12 Jan 2022 21:47:26 +0100 Subject: [PATCH 12/33] Query type is overloaded with port since 2d65d55, so we have to derive the real query type from the arg string Signed-off-by: DL6ER --- src/dnsmasq_interface.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/dnsmasq_interface.c b/src/dnsmasq_interface.c index 1cb410e1..63080120 100644 --- a/src/dnsmasq_interface.c +++ b/src/dnsmasq_interface.c @@ -131,7 +131,17 @@ void FTL_hook(unsigned int flags, char *name, union all_addr *addr, char *arg, i return; const ednsData edns = { 0 }; - _FTL_new_query(flags, name, NULL, arg, type, id, &edns, INTERNAL, file, line); + + // Type is overloaded with port since 2d65d55, so we have to + // derive the real query type from the arg string + unsigned short qtype = type; + if(strcmp(arg, "dnssec-query[DNSKEY]") == 0) + qtype = T_DNSKEY; + else if(strcmp(arg, "dnssec-query[DS]") == 0) + qtype = T_DS; + arg = (char*)"dnssec-query"; + + _FTL_new_query(flags, name, NULL, arg, qtype, id, &edns, INTERNAL, file, line); // forwarded upstream (type is used to store the upstream port) FTL_forwarded(flags, name, addr, type, id, path, line); } From 0965995f0fc28f91adcdf146a0fdb34b396a36b9 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Wed, 12 Jan 2022 23:00:16 +0000 Subject: [PATCH 13/33] Small fix to ff43d35aeef6178f7471c6f37e91845c9a72bd2f Signed-off-by: DL6ER --- src/dnsmasq/cache.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/dnsmasq/cache.c b/src/dnsmasq/cache.c index 7f6e03ab..62a03e4b 100644 --- a/src/dnsmasq/cache.c +++ b/src/dnsmasq/cache.c @@ -2104,7 +2104,12 @@ void _log_query(unsigned int flags, char *name, union all_addr *addr, char *arg, } else if (flags & F_AUTH) source = "auth"; - else if (flags & F_SERVER) + else if (flags & F_DNSSEC) + { + source = arg; + verb = "to"; + } + else if (flags & F_SERVER) { source = "forwarded"; verb = "to"; @@ -2114,11 +2119,6 @@ void _log_query(unsigned int flags, char *name, union all_addr *addr, char *arg, source = arg; verb = "from"; } - else if (flags & F_DNSSEC) - { - source = arg; - verb = "to"; - } else if (flags & F_IPSET) { source = type ? "ipset add" : "nftset add"; From c037cc0e700012275d2f83ba43f1b7aeb5bf1a6e Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Wed, 12 Jan 2022 23:05:25 +0000 Subject: [PATCH 14/33] Fix error introduced in 11c52d032be7a111094419194fc8cb03802d0edf Signed-off-by: DL6ER --- src/dnsmasq/dnssec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dnsmasq/dnssec.c b/src/dnsmasq/dnssec.c index 84ad48fc..028a317c 100644 --- a/src/dnsmasq/dnssec.c +++ b/src/dnsmasq/dnssec.c @@ -2101,7 +2101,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch if (qtype == T_DS) return STAT_BOGUS | DNSSEC_FAIL_NONSEC; - if (STAT_ISEQUAL((rc = zone_status(name, qclass, keyname, now)), STAT_SECURE)) + if (!STAT_ISEQUAL((rc = zone_status(name, qclass, keyname, now)), STAT_SECURE)) { if (class) *class = qclass; /* Class for NEED_DS or NEED_KEY */ From 97ba9c3c62e5b2f361a5c7709194d7fec88fbcab Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Thu, 13 Jan 2022 00:12:07 +0000 Subject: [PATCH 15/33] Fix DNSSEC failure to validate unsigned NoDATA replies. A reply with an empty answer section would not always be checked for either suitable NSEC records or proof of non-existence of the relevant DS record. Signed-off-by: DL6ER --- src/dnsmasq/dnssec.c | 64 ++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/dnsmasq/dnssec.c b/src/dnsmasq/dnssec.c index 028a317c..9965eea3 100644 --- a/src/dnsmasq/dnssec.c +++ b/src/dnsmasq/dnssec.c @@ -1867,7 +1867,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch int type1, class1, rdlen1 = 0, type2, class2, rdlen2, qclass, qtype, targetidx; int i, j, rc = STAT_INSECURE; int secure = STAT_SECURE; - + /* extend rr_status if necessary */ if (daemon->rr_status_sz < ntohs(header->ancount) + ntohs(header->nscount)) { @@ -1989,7 +1989,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch { /* NSEC and NSEC3 records must be signed. We make this assumption elsewhere. */ if (type1 == T_NSEC || type1 == T_NSEC3) - rc = STAT_INSECURE; + return STAT_BOGUS | DNSSEC_FAIL_NOSIG; else if (nons && i >= ntohs(header->ancount)) /* If we're validating a DS reply, rather than looking for the value of AD bit, we only care that NSEC and NSEC3 RRs in the auth section are signed. @@ -2003,6 +2003,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch rc = zone_status(name, class1, keyname, now); if (STAT_ISEQUAL(rc, STAT_SECURE)) rc = STAT_BOGUS | DNSSEC_FAIL_NOSIG; + if (class) *class = class1; /* Class for NEED_DS or NEED_KEY */ } @@ -2081,36 +2082,35 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch } /* OK, all the RRsets validate, now see if we have a missing answer or CNAME target. */ - if (STAT_ISEQUAL(secure, STAT_SECURE)) - for (j = 0; j Date: Tue, 28 Dec 2021 11:03:40 +0100 Subject: [PATCH 16/33] Minimum safe size is recommended to be 1232. See https://dnsflagday.net/2020/ Signed-off-by: DL6ER --- src/dnsmasq/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dnsmasq/config.h b/src/dnsmasq/config.h index 2959ea45..37a063e7 100644 --- a/src/dnsmasq/config.h +++ b/src/dnsmasq/config.h @@ -20,7 +20,7 @@ #define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */ #define TCP_BACKLOG 32 /* kernel backlog limit for TCP connections */ #define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */ -#define SAFE_PKTSZ 1280 /* "go anywhere" UDP packet size */ +#define SAFE_PKTSZ 1232 /* "go anywhere" UDP packet size, see https://dnsflagday.net/2020/ */ #define KEYBLOCK_LEN 40 /* choose to minimise fragmentation when storing DNSSEC keys */ #define DNSSEC_WORK 50 /* Max number of queries to validate one question */ #define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */ From 08ccfeb76d1057c32f6462e07975f4038eb05dc8 Mon Sep 17 00:00:00 2001 From: Dominik Derigs Date: Fri, 7 Jan 2022 06:11:53 +0100 Subject: [PATCH 17/33] Strip EDNS(0) Client Subnet / MAC information if --strip-subnet or --strip-mac is set. If both the add and strip options are set, incoming EDNS0 options are replaced. This ensures we do not unintentionally forward client information somewhere upstream when ECS is used in lower DNS layers in our local network. Signed-off-by: DL6ER --- src/dnsmasq/dnsmasq.h | 4 +++- src/dnsmasq/edns0.c | 33 ++++++++++++++++++++++++++------- src/dnsmasq/option.c | 6 ++++++ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/dnsmasq/dnsmasq.h b/src/dnsmasq/dnsmasq.h index a281c990..2df32991 100644 --- a/src/dnsmasq/dnsmasq.h +++ b/src/dnsmasq/dnsmasq.h @@ -284,7 +284,9 @@ struct event_desc { #define OPT_QUIET_TFTP 66 #define OPT_FILTER_A 67 #define OPT_FILTER_AAAA 68 -#define OPT_LAST 69 +#define OPT_STRIP_ECS 69 +#define OPT_STRIP_MAC 70 +#define OPT_LAST 71 #define OPTION_BITS (sizeof(unsigned int)*8) #define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) ) diff --git a/src/dnsmasq/edns0.c b/src/dnsmasq/edns0.c index 5de6cb22..15990404 100644 --- a/src/dnsmasq/edns0.c +++ b/src/dnsmasq/edns0.c @@ -291,7 +291,7 @@ static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned ch static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit, - union mysockaddr *l3, time_t now, int *cacheablep) + union mysockaddr *l3, time_t now, int *cacheablep, const int replace) { int maclen; unsigned char mac[DHCP_CHADDR_MAX]; @@ -299,8 +299,13 @@ static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *lim if ((maclen = find_mac(l3, mac, 1, now)) != 0) { *cacheablep = 0; - plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, 0); + plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, replace); } + else if(replace > 0) + { + /* Asked to replace MAC address but it is not available here. We just remove whatever might be there */ + plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_MAC, NULL, 0, 0, 2); + } return plen; } @@ -378,7 +383,8 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source, return len + 4; } -static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *source, int *cacheable) +static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit, + union mysockaddr *source, int *cacheable, const int replace) { /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */ @@ -386,7 +392,7 @@ static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned c struct subnet_opt opt; len = calc_subnet_opt(&opt, source, cacheable); - return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, 0); + return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, replace); } int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer) @@ -498,11 +504,19 @@ size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *l *check_subnet = 0; *cacheable = 1; + /* OPT_ADD_MAC = MAC is added (if available) + OPT_ADD_MAC + OPT_STRIP_MAC = MAC is replaced, if not available, it is only removed + OPT_STRIP_MAC = MAC is removed */ if (option_bool(OPT_ADD_MAC)) - plen = add_mac(header, plen, limit, source, now, cacheable); - + plen = add_mac(header, plen, limit, source, now, cacheable, option_bool(OPT_STRIP_MAC) ? 1 : 0); + else if (option_bool(OPT_STRIP_MAC)) + plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_MAC, NULL, 0, 0, 2); + + /* Use --strip-mac also for --add-mac=hex and --add-mac=text */ if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX)) plen = add_dns_client(header, plen, limit, source, now, cacheable); + else if (option_bool(OPT_STRIP_MAC)) + plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_NOMDEVICEID, NULL, 0, 0, 2); if (daemon->dns_client_id) plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID, @@ -511,11 +525,16 @@ size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *l if (option_bool(OPT_UMBRELLA)) plen = add_umbrella_opt(header, plen, limit, source, cacheable); + /* OPT_CLIENT_SUBNET = client subnet is added + OPT_CLIENT_SUBNET + OPT_STRIP_ECS = client subnet is replaced + OPT_STRIP_ECS = client subnet is removed */ if (option_bool(OPT_CLIENT_SUBNET)) { - plen = add_source_addr(header, plen, limit, source, cacheable); + plen = add_source_addr(header, plen, limit, source, cacheable, option_bool(OPT_STRIP_ECS) ? 1 : 0); *check_subnet = 1; } + else if (option_bool(OPT_STRIP_ECS)) + plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_CLIENT_SUBNET, NULL, 0, 0, 2); return plen; } diff --git a/src/dnsmasq/option.c b/src/dnsmasq/option.c index b0611a52..794f95fe 100644 --- a/src/dnsmasq/option.c +++ b/src/dnsmasq/option.c @@ -181,6 +181,8 @@ struct myoption { #define LOPT_NFTSET 368 #define LOPT_FILTER_A 369 #define LOPT_FILTER_AAAA 370 +#define LOPT_STRIP_SBNET 371 +#define LOPT_STRIP_MAC 372 #ifdef HAVE_GETOPT_LONG static const struct option opts[] = @@ -318,7 +320,9 @@ static const struct myoption opts[] = { "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES }, { "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND }, { "add-mac", 2, 0, LOPT_ADD_MAC }, + { "strip-mac", 0, 0, LOPT_STRIP_MAC }, { "add-subnet", 2, 0, LOPT_ADD_SBNET }, + { "strip-subnet", 0, 0, LOPT_STRIP_SBNET }, { "add-cpe-id", 1, 0 , LOPT_CPE_ID }, { "proxy-dnssec", 0, 0, LOPT_DNSSEC }, { "dhcp-sequential-ip", 0, 0, LOPT_INCR_ADDR }, @@ -505,7 +509,9 @@ static struct { { LOPT_PXE_SERV, ARG_DUP, "", gettext_noop("Boot service for PXE menu."), NULL }, { LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL }, { LOPT_ADD_MAC, ARG_DUP, "[=base64|text]", gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL }, + { LOPT_STRIP_MAC, OPT_STRIP_MAC, NULL, gettext_noop("Strip MAC information from queries."), NULL }, { LOPT_ADD_SBNET, ARG_ONE, "[,]", gettext_noop("Add specified IP subnet to forwarded DNS queries."), NULL }, + { LOPT_STRIP_SBNET, OPT_STRIP_ECS, NULL, gettext_noop("Strip ECS information from queries."), NULL }, { LOPT_CPE_ID, ARG_ONE, "", gettext_noop("Add client identification to forwarded DNS queries."), NULL }, { LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL }, { LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL }, From 563b45d993f16e265d6246d9702ce9c12f7a1e4c Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Sat, 15 Jan 2022 17:57:57 +0000 Subject: [PATCH 18/33] Tidy previous commit and add manpage entries for new options. Signed-off-by: DL6ER --- src/dnsmasq/dnsmasq.h | 5 +- src/dnsmasq/edns0.c | 113 ++++++++++++++++++++++-------------------- src/dnsmasq/forward.c | 19 +++---- 3 files changed, 69 insertions(+), 68 deletions(-) diff --git a/src/dnsmasq/dnsmasq.h b/src/dnsmasq/dnsmasq.h index 2df32991..cdb0abe6 100644 --- a/src/dnsmasq/dnsmasq.h +++ b/src/dnsmasq/dnsmasq.h @@ -736,7 +736,7 @@ struct hostsfile { #define FREC_NOREBIND 1 #define FREC_CHECKING_DISABLED 2 -#define FREC_HAS_SUBNET 4 +#define FREC_NO_CACHE 4 #define FREC_DNSKEY_QUERY 8 #define FREC_DS_QUERY 16 #define FREC_AD_QUESTION 32 @@ -745,7 +745,6 @@ struct hostsfile { #define FREC_TEST_PKTSZ 256 #define FREC_HAS_EXTRADATA 512 #define FREC_HAS_PHEADER 1024 -#define FREC_NO_CACHE 2048 #define HASH_SIZE 32 /* SHA-256 digest size */ @@ -1825,7 +1824,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace); size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char *limit); size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit, - union mysockaddr *source, time_t now, int *check_subnet, int *cacheable); + union mysockaddr *source, time_t now, int *cacheable); int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer); /* arp.c */ diff --git a/src/dnsmasq/edns0.c b/src/dnsmasq/edns0.c index 15990404..7591b78a 100644 --- a/src/dnsmasq/edns0.c +++ b/src/dnsmasq/edns0.c @@ -264,49 +264,62 @@ static void encoder(unsigned char *in, char *out) out[3] = char64(in[2]); } +/* OPT_ADD_MAC = MAC is added (if available) + OPT_ADD_MAC + OPT_STRIP_MAC = MAC is replaced, if not available, it is only removed + OPT_STRIP_MAC = MAC is removed */ static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *l3, time_t now, int *cacheablep) { - int maclen, replace = 2; /* can't get mac address, just delete any incoming. */ + int replace = 0, maclen = 0; unsigned char mac[DHCP_CHADDR_MAX]; - char encode[18]; /* handle 6 byte MACs */ + char encode[18]; /* handle 6 byte MACs ONLY */ - if ((maclen = find_mac(l3, mac, 1, now)) == 6) + if ((option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX)) && (maclen = find_mac(l3, mac, 1, now)) == 6) { - replace = 1; - *cacheablep = 0; - - if (option_bool(OPT_MAC_HEX)) - print_mac(encode, mac, maclen); - else - { - encoder(mac, encode); - encoder(mac+3, encode+4); - encode[8] = 0; - } + if (option_bool(OPT_STRIP_MAC)) + replace = 1; + *cacheablep = 0; + + if (option_bool(OPT_MAC_HEX)) + print_mac(encode, mac, maclen); + else + { + encoder(mac, encode); + encoder(mac+3, encode+4); + encode[8] = 0; + } } + else if (option_bool(OPT_STRIP_MAC)) + replace = 2; - return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace); + if (replace != 0 || maclen == 6) + plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace); + + return plen; } +/* OPT_ADD_MAC = MAC is added (if available) + OPT_ADD_MAC + OPT_STRIP_MAC = MAC is replaced, if not available, it is only removed + OPT_STRIP_MAC = MAC is removed */ static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit, - union mysockaddr *l3, time_t now, int *cacheablep, const int replace) + union mysockaddr *l3, time_t now, int *cacheablep) { - int maclen; + int maclen = 0, replace = 0; unsigned char mac[DHCP_CHADDR_MAX]; - - if ((maclen = find_mac(l3, mac, 1, now)) != 0) + + if (option_bool(OPT_ADD_MAC) && (maclen = find_mac(l3, mac, 1, now)) != 0) { *cacheablep = 0; - plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, replace); + if (option_bool(OPT_STRIP_MAC)) + replace = 1; } - else if(replace > 0) - { - /* Asked to replace MAC address but it is not available here. We just remove whatever might be there */ - plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_MAC, NULL, 0, 0, 2); - } + else if (option_bool(OPT_STRIP_MAC)) + replace = 2; + if (replace != 0 || maclen != 0) + plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, replace); + return plen; } @@ -383,15 +396,28 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source, return len + 4; } +/* OPT_CLIENT_SUBNET = client subnet is added + OPT_CLIENT_SUBNET + OPT_STRIP_ECS = client subnet is replaced + OPT_STRIP_ECS = client subnet is removed */ static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit, - union mysockaddr *source, int *cacheable, const int replace) + union mysockaddr *source, int *cacheable) { /* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */ - int len; + int replace = 0, len = 0; struct subnet_opt opt; - len = calc_subnet_opt(&opt, source, cacheable); + if (option_bool(OPT_CLIENT_SUBNET)) + { + if (option_bool(OPT_STRIP_ECS)) + replace = 1; + len = calc_subnet_opt(&opt, source, cacheable); + } + else if (option_bool(OPT_STRIP_ECS)) + replace = 2; + else + return plen; + return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, replace); } @@ -499,24 +525,12 @@ static size_t add_umbrella_opt(struct dns_header *header, size_t plen, unsigned in the reply. Set *cacheable to zero if we add an option which the answer may depend on. */ size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit, - union mysockaddr *source, time_t now, int *check_subnet, int *cacheable) + union mysockaddr *source, time_t now, int *cacheable) { - *check_subnet = 0; *cacheable = 1; - /* OPT_ADD_MAC = MAC is added (if available) - OPT_ADD_MAC + OPT_STRIP_MAC = MAC is replaced, if not available, it is only removed - OPT_STRIP_MAC = MAC is removed */ - if (option_bool(OPT_ADD_MAC)) - plen = add_mac(header, plen, limit, source, now, cacheable, option_bool(OPT_STRIP_MAC) ? 1 : 0); - else if (option_bool(OPT_STRIP_MAC)) - plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_MAC, NULL, 0, 0, 2); - - /* Use --strip-mac also for --add-mac=hex and --add-mac=text */ - if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX)) - plen = add_dns_client(header, plen, limit, source, now, cacheable); - else if (option_bool(OPT_STRIP_MAC)) - plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_NOMDEVICEID, NULL, 0, 0, 2); + plen = add_mac(header, plen, limit, source, now, cacheable); + plen = add_dns_client(header, plen, limit, source, now, cacheable); if (daemon->dns_client_id) plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID, @@ -525,16 +539,7 @@ size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *l if (option_bool(OPT_UMBRELLA)) plen = add_umbrella_opt(header, plen, limit, source, cacheable); - /* OPT_CLIENT_SUBNET = client subnet is added - OPT_CLIENT_SUBNET + OPT_STRIP_ECS = client subnet is replaced - OPT_STRIP_ECS = client subnet is removed */ - if (option_bool(OPT_CLIENT_SUBNET)) - { - plen = add_source_addr(header, plen, limit, source, cacheable, option_bool(OPT_STRIP_ECS) ? 1 : 0); - *check_subnet = 1; - } - else if (option_bool(OPT_STRIP_ECS)) - plen = add_pseudoheader(header, plen, (unsigned char *)limit, daemon->edns_pktsz, EDNS0_OPTION_CLIENT_SUBNET, NULL, 0, 0, 2); - + plen = add_source_addr(header, plen, limit, source, cacheable); + return plen; } diff --git a/src/dnsmasq/forward.c b/src/dnsmasq/forward.c index 5589722b..f043abfb 100644 --- a/src/dnsmasq/forward.c +++ b/src/dnsmasq/forward.c @@ -200,7 +200,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL); int old_src = 0, old_reply = 0; int first, last, start = 0; - int subnet, cacheable, forwarded = 0; + int cacheable, forwarded = 0; size_t edns0_len; unsigned char *pheader; int ede = EDE_UNSET; @@ -455,10 +455,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, { header->id = htons(forward->new_id); - plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->frec_src.source, now, &subnet, &cacheable); - - if (subnet) - forward->flags |= FREC_HAS_SUBNET; + plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->frec_src.source, now, &cacheable); if (!cacheable) forward->flags |= FREC_NO_CACHE; @@ -636,7 +633,7 @@ static struct ipsets *domain_find_sets(struct ipsets *setlist, const char *domai static size_t process_reply(struct dns_header *header, time_t now, struct server *server, size_t n, int check_rebind, int no_cache, int cache_secure, int bogusanswer, int ad_reqd, int do_bit, int added_pheader, - int check_subnet, union mysockaddr *query_source, unsigned char *limit, int ede) + union mysockaddr *query_source, unsigned char *limit, int ede) { unsigned char *pheader, *sizep; struct ipsets *ipsets = NULL, *nftsets = NULL; @@ -663,7 +660,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server /* Get extended RCODE. */ rcode |= sizep[2] << 4; - if (check_subnet && !check_source(header, plen, pheader, query_source)) + if (option_bool(OPT_CLIENT_SUBNET) && !check_source(header, plen, pheader, query_source)) { my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch")); return 0; @@ -1265,7 +1262,7 @@ static void return_reply(time_t now, struct frec *forward, struct dns_header *he if ((nn = process_reply(header, now, forward->sentto, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer, forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION, - forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->frec_src.source, + forward->flags & FREC_ADDED_PHEADER, &forward->frec_src.source, ((unsigned char *)header) + daemon->edns_pktsz, ede))) { struct frec_src *src; @@ -2001,7 +1998,7 @@ unsigned char *tcp_request(int confd, time_t now, int local_auth = 0; #endif int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0; - int check_subnet, cacheable, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0; + int cacheable, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0; size_t m; unsigned short qtype; unsigned int gotname; @@ -2257,7 +2254,7 @@ unsigned char *tcp_request(int confd, time_t now, else start = master->last_server; - size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet, &cacheable); + size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &cacheable); #ifdef HAVE_DNSSEC if (option_bool(OPT_DNSSEC_VALID) && (master->flags & SERV_DO_DNSSEC)) @@ -2335,7 +2332,7 @@ unsigned char *tcp_request(int confd, time_t now, m = process_reply(header, now, serv, (unsigned int)m, option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer, - ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr, ((unsigned char *)header) + 65536, ede); + ad_reqd, do_bit, added_pheader, &peer_addr, ((unsigned char *)header) + 65536, ede); } } /************ Pi-hole modification ************/ From e7974aed9f08cabfcceec94c68dc5f95562d9128 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Mon, 17 Jan 2022 23:54:58 +0000 Subject: [PATCH 19/33] Remove temporary debugging message and close related Debian bug. Signed-off-by: DL6ER --- src/dnsmasq/forward.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/dnsmasq/forward.c b/src/dnsmasq/forward.c index f043abfb..a906205d 100644 --- a/src/dnsmasq/forward.c +++ b/src/dnsmasq/forward.c @@ -923,8 +923,6 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header, forward->stash = stash; return; } - - my_syslog(LOG_WARNING, _("detected DNSSEC dependency loop involving %s"), daemon->keyname); } else { @@ -1002,7 +1000,7 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header, blockdata_free(stash); /* don't leak this on failure. */ } - /* sending DNSSEC query failed. */ + /* sending DNSSEC query failed or loop detected. */ status = STAT_ABANDONED; } From a20aec1fa6e69e6eafd458e07a37b1cacab05401 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Tue, 18 Jan 2022 00:55:13 +0000 Subject: [PATCH 20/33] Fix crash in PXE code with bad config. Signed-off-by: DL6ER --- src/dnsmasq/rfc2131.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dnsmasq/rfc2131.c b/src/dnsmasq/rfc2131.c index c902eb70..a99bb899 100644 --- a/src/dnsmasq/rfc2131.c +++ b/src/dnsmasq/rfc2131.c @@ -2200,8 +2200,9 @@ static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dh inet_ntop(AF_INET, &mess->siaddr, (char *)mess->sname, INET_ADDRSTRLEN); } - snprintf((char *)mess->file, sizeof(mess->file), - strchr(found->basename, '.') ? "%s" : "%s.0", found->basename); + if (found->basename) + snprintf((char *)mess->file, sizeof(mess->file), + strchr(found->basename, '.') ? "%s" : "%s.0", found->basename); return 1; } From c365593522c856e5604d2bc37d21b8c7ed8622f8 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Fri, 21 Jan 2022 12:07:42 +0000 Subject: [PATCH 21/33] Fix indentation in Umbrella option code. Signed-off-by: DL6ER --- src/dnsmasq/option.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/dnsmasq/option.c b/src/dnsmasq/option.c index 794f95fe..0a07e9f9 100644 --- a/src/dnsmasq/option.c +++ b/src/dnsmasq/option.c @@ -2541,13 +2541,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma arg += 9; if (strlen(arg) != 16) ret_err(gen_err); - + for (p = arg; *p; p++) if (!isxdigit((int)*p)) ret_err(gen_err); - + set_option_bool(OPT_UMBRELLA_DEVID); - + for (i = 0; i < (int)sizeof(daemon->umbrella_device); i++, arg+=2) { memcpy(word, &(arg[0]), 2); @@ -2559,13 +2559,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma if (!strtoul_check(arg+6, &daemon->umbrella_org)) ret_err(gen_err); } - else if (strstr(arg, "assetid:")) - { - if (!strtoul_check(arg+8, &daemon->umbrella_asset)) - ret_err(gen_err); - } - else - ret_err(gen_err); + else if (strstr(arg, "assetid:")) + { + if (!strtoul_check(arg+8, &daemon->umbrella_asset)) + ret_err(gen_err); + } + else + ret_err(gen_err); arg = comma; } From d74eed5463bdac7eeb746b223dfc91fb184f8c65 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Mon, 24 Jan 2022 15:19:00 +0000 Subject: [PATCH 22/33] Bump copyright to 2022. Signed-off-by: DL6ER --- src/dnsmasq/arp.c | 2 +- src/dnsmasq/auth.c | 2 +- src/dnsmasq/blockdata.c | 2 +- src/dnsmasq/bpf.c | 2 +- src/dnsmasq/cache.c | 2 +- src/dnsmasq/config.h | 2 +- src/dnsmasq/conntrack.c | 2 +- src/dnsmasq/crypto.c | 2 +- src/dnsmasq/dbus.c | 2 +- src/dnsmasq/dhcp-common.c | 2 +- src/dnsmasq/dhcp-protocol.h | 2 +- src/dnsmasq/dhcp.c | 2 +- src/dnsmasq/dhcp6-protocol.h | 2 +- src/dnsmasq/dhcp6.c | 2 +- src/dnsmasq/dns-protocol.h | 2 +- src/dnsmasq/dnsmasq.c | 2 +- src/dnsmasq/dnsmasq.h | 4 ++-- src/dnsmasq/domain-match.c | 2 +- src/dnsmasq/domain.c | 2 +- src/dnsmasq/dump.c | 2 +- src/dnsmasq/edns0.c | 2 +- src/dnsmasq/forward.c | 2 +- src/dnsmasq/helper.c | 2 +- src/dnsmasq/inotify.c | 2 +- src/dnsmasq/ip6addr.h | 2 +- src/dnsmasq/lease.c | 2 +- src/dnsmasq/log.c | 2 +- src/dnsmasq/loop.c | 2 +- src/dnsmasq/metrics.c | 2 +- src/dnsmasq/metrics.h | 2 +- src/dnsmasq/netlink.c | 2 +- src/dnsmasq/network.c | 2 +- src/dnsmasq/nftset.c | 2 +- src/dnsmasq/option.c | 2 +- src/dnsmasq/outpacket.c | 2 +- src/dnsmasq/pattern.c | 2 +- src/dnsmasq/poll.c | 2 +- src/dnsmasq/radv-protocol.h | 2 +- src/dnsmasq/radv.c | 2 +- src/dnsmasq/rfc1035.c | 2 +- src/dnsmasq/rfc2131.c | 2 +- src/dnsmasq/rfc3315.c | 2 +- src/dnsmasq/rrfilter.c | 2 +- src/dnsmasq/slaac.c | 2 +- src/dnsmasq/tftp.c | 2 +- src/dnsmasq/ubus.c | 2 +- src/dnsmasq/util.c | 2 +- 47 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/dnsmasq/arp.c b/src/dnsmasq/arp.c index 1e4aad29..eda165f6 100644 --- a/src/dnsmasq/arp.c +++ b/src/dnsmasq/arp.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/auth.c b/src/dnsmasq/auth.c index aa2403b9..7088d677 100644 --- a/src/dnsmasq/auth.c +++ b/src/dnsmasq/auth.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/blockdata.c b/src/dnsmasq/blockdata.c index 0986285d..4c26155f 100644 --- a/src/dnsmasq/blockdata.c +++ b/src/dnsmasq/blockdata.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/bpf.c b/src/dnsmasq/bpf.c index 15c42fc3..4dd97c0e 100644 --- a/src/dnsmasq/bpf.c +++ b/src/dnsmasq/bpf.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/cache.c b/src/dnsmasq/cache.c index 62a03e4b..cbec10de 100644 --- a/src/dnsmasq/cache.c +++ b/src/dnsmasq/cache.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/config.h b/src/dnsmasq/config.h index 37a063e7..18429bf3 100644 --- a/src/dnsmasq/config.h +++ b/src/dnsmasq/config.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/conntrack.c b/src/dnsmasq/conntrack.c index 745a2a3f..fe48f2b1 100644 --- a/src/dnsmasq/conntrack.c +++ b/src/dnsmasq/conntrack.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/crypto.c b/src/dnsmasq/crypto.c index 4009569a..060e27ff 100644 --- a/src/dnsmasq/crypto.c +++ b/src/dnsmasq/crypto.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/dbus.c b/src/dnsmasq/dbus.c index 4eae7899..0c55ea5e 100644 --- a/src/dnsmasq/dbus.c +++ b/src/dnsmasq/dbus.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/dhcp-common.c b/src/dnsmasq/dhcp-common.c index 80c1538e..4e2667f8 100644 --- a/src/dnsmasq/dhcp-common.c +++ b/src/dnsmasq/dhcp-common.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/dhcp-protocol.h b/src/dnsmasq/dhcp-protocol.h index 6ff3ffa2..75c9cd3c 100644 --- a/src/dnsmasq/dhcp-protocol.h +++ b/src/dnsmasq/dhcp-protocol.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/dhcp.c b/src/dnsmasq/dhcp.c index 2c1272f5..cdea79e1 100644 --- a/src/dnsmasq/dhcp.c +++ b/src/dnsmasq/dhcp.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/dhcp6-protocol.h b/src/dnsmasq/dhcp6-protocol.h index f1d09914..332d5364 100644 --- a/src/dnsmasq/dhcp6-protocol.h +++ b/src/dnsmasq/dhcp6-protocol.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/dhcp6.c b/src/dnsmasq/dhcp6.c index c061879c..98312553 100644 --- a/src/dnsmasq/dhcp6.c +++ b/src/dnsmasq/dhcp6.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/dns-protocol.h b/src/dnsmasq/dns-protocol.h index 496a4bba..8558c33b 100644 --- a/src/dnsmasq/dns-protocol.h +++ b/src/dnsmasq/dns-protocol.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/dnsmasq.c b/src/dnsmasq/dnsmasq.c index f9204930..61b1ad8a 100644 --- a/src/dnsmasq/dnsmasq.c +++ b/src/dnsmasq/dnsmasq.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/dnsmasq.h b/src/dnsmasq/dnsmasq.h index cdb0abe6..e103ca8b 100644 --- a/src/dnsmasq/dnsmasq.h +++ b/src/dnsmasq/dnsmasq.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,7 +21,7 @@ #define HAVE_LUASCRIPT /***********************/ -#define COPYRIGHT "Copyright (c) 2000-2021 Simon Kelley" +#define COPYRIGHT "Copyright (c) 2000-2022 Simon Kelley" /* We do defines that influence behavior of stdio.h, so complain if included too early. */ diff --git a/src/dnsmasq/domain-match.c b/src/dnsmasq/domain-match.c index 4e010920..3ec49b80 100644 --- a/src/dnsmasq/domain-match.c +++ b/src/dnsmasq/domain-match.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/domain.c b/src/dnsmasq/domain.c index 91e0f22c..71664334 100644 --- a/src/dnsmasq/domain.c +++ b/src/dnsmasq/domain.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/dump.c b/src/dnsmasq/dump.c index c131953a..14365d80 100644 --- a/src/dnsmasq/dump.c +++ b/src/dnsmasq/dump.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/edns0.c b/src/dnsmasq/edns0.c index 7591b78a..c498eb12 100644 --- a/src/dnsmasq/edns0.c +++ b/src/dnsmasq/edns0.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/forward.c b/src/dnsmasq/forward.c index a906205d..7945d460 100644 --- a/src/dnsmasq/forward.c +++ b/src/dnsmasq/forward.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/helper.c b/src/dnsmasq/helper.c index aba66389..a6a9b28d 100644 --- a/src/dnsmasq/helper.c +++ b/src/dnsmasq/helper.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/inotify.c b/src/dnsmasq/inotify.c index 3a8e375b..5687e37c 100644 --- a/src/dnsmasq/inotify.c +++ b/src/dnsmasq/inotify.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/ip6addr.h b/src/dnsmasq/ip6addr.h index 6388c7d9..977e6840 100644 --- a/src/dnsmasq/ip6addr.h +++ b/src/dnsmasq/ip6addr.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/lease.c b/src/dnsmasq/lease.c index 1a9f1c6e..81477d54 100644 --- a/src/dnsmasq/lease.c +++ b/src/dnsmasq/lease.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/log.c b/src/dnsmasq/log.c index 8963841e..c38ed445 100644 --- a/src/dnsmasq/log.c +++ b/src/dnsmasq/log.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/loop.c b/src/dnsmasq/loop.c index 01f0c289..cd4855e2 100644 --- a/src/dnsmasq/loop.c +++ b/src/dnsmasq/loop.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/metrics.c b/src/dnsmasq/metrics.c index fac5b005..68735293 100644 --- a/src/dnsmasq/metrics.c +++ b/src/dnsmasq/metrics.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/metrics.h b/src/dnsmasq/metrics.h index cecf8c83..df72ec68 100644 --- a/src/dnsmasq/metrics.h +++ b/src/dnsmasq/metrics.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/netlink.c b/src/dnsmasq/netlink.c index 7840ef95..ae1426c7 100644 --- a/src/dnsmasq/netlink.c +++ b/src/dnsmasq/netlink.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/network.c b/src/dnsmasq/network.c index 5e5c3b91..26032553 100644 --- a/src/dnsmasq/network.c +++ b/src/dnsmasq/network.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/nftset.c b/src/dnsmasq/nftset.c index 5373a1c7..4e152dc1 100644 --- a/src/dnsmasq/nftset.c +++ b/src/dnsmasq/nftset.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/option.c b/src/dnsmasq/option.c index 0a07e9f9..fd07010e 100644 --- a/src/dnsmasq/option.c +++ b/src/dnsmasq/option.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/outpacket.c b/src/dnsmasq/outpacket.c index da6f73cb..abb3a3a4 100644 --- a/src/dnsmasq/outpacket.c +++ b/src/dnsmasq/outpacket.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/pattern.c b/src/dnsmasq/pattern.c index 928d2593..e56e4956 100644 --- a/src/dnsmasq/pattern.c +++ b/src/dnsmasq/pattern.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/poll.c b/src/dnsmasq/poll.c index f4146905..29b33a0c 100644 --- a/src/dnsmasq/poll.c +++ b/src/dnsmasq/poll.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/radv-protocol.h b/src/dnsmasq/radv-protocol.h index 8314e8a8..7fb6bd82 100644 --- a/src/dnsmasq/radv-protocol.h +++ b/src/dnsmasq/radv-protocol.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/radv.c b/src/dnsmasq/radv.c index 6d6fa32d..2b6d9442 100644 --- a/src/dnsmasq/radv.c +++ b/src/dnsmasq/radv.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/rfc1035.c b/src/dnsmasq/rfc1035.c index b34bc0a5..6d7490d3 100644 --- a/src/dnsmasq/rfc1035.c +++ b/src/dnsmasq/rfc1035.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/rfc2131.c b/src/dnsmasq/rfc2131.c index a99bb899..ecda2d3e 100644 --- a/src/dnsmasq/rfc2131.c +++ b/src/dnsmasq/rfc2131.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/rfc3315.c b/src/dnsmasq/rfc3315.c index 236df47b..a286395d 100644 --- a/src/dnsmasq/rfc3315.c +++ b/src/dnsmasq/rfc3315.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/rrfilter.c b/src/dnsmasq/rrfilter.c index ef276c0f..f02f5a5e 100644 --- a/src/dnsmasq/rrfilter.c +++ b/src/dnsmasq/rrfilter.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/slaac.c b/src/dnsmasq/slaac.c index 9b100630..7d3fce48 100644 --- a/src/dnsmasq/slaac.c +++ b/src/dnsmasq/slaac.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/tftp.c b/src/dnsmasq/tftp.c index e8474d9a..b82d89d9 100644 --- a/src/dnsmasq/tftp.c +++ b/src/dnsmasq/tftp.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/ubus.c b/src/dnsmasq/ubus.c index 0c502ad5..09071cfc 100644 --- a/src/dnsmasq/ubus.c +++ b/src/dnsmasq/ubus.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq/util.c b/src/dnsmasq/util.c index f2adac15..ae514d29 100644 --- a/src/dnsmasq/util.c +++ b/src/dnsmasq/util.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From c74158c4b85e6c270f1f8cf6b285295820440f3b Mon Sep 17 00:00:00 2001 From: DL6ER Date: Thu, 3 Feb 2022 19:10:52 +0100 Subject: [PATCH 23/33] Extend packet-dump system to DHCP and TFTP. Signed-off-by: DL6ER --- src/dnsmasq/dhcp.c | 35 ++++++++++++++++++++++++++++++++--- src/dnsmasq/dhcp6.c | 33 ++++++++++++++++++++++++--------- src/dnsmasq/dnsmasq.h | 22 +++++++++++++--------- src/dnsmasq/dump.c | 5 +++-- src/dnsmasq/forward.c | 43 ++++++++++++++++--------------------------- src/dnsmasq/rfc3315.c | 12 ++++++++++++ src/dnsmasq/tftp.c | 23 ++++++++++++++++++++--- 7 files changed, 120 insertions(+), 53 deletions(-) diff --git a/src/dnsmasq/dhcp.c b/src/dnsmasq/dhcp.c index cdea79e1..de766c10 100644 --- a/src/dnsmasq/dhcp.c +++ b/src/dnsmasq/dhcp.c @@ -177,11 +177,16 @@ void dhcp_packet(time_t now, int pxe_fd) if ((sz = recv_dhcp_packet(fd, &msg)) == -1 || (sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))) return; - - #if defined (HAVE_LINUX_NETWORK) + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_DHCP, (void *)daemon->dhcp_packet.iov_base, sz, (union mysockaddr *)&dest, NULL, + pxe_fd ? PXE_PORT : daemon->dhcp_server_port); +#endif + +#if defined (HAVE_LINUX_NETWORK) if (ioctl(fd, SIOCGSTAMP, &tv) == 0) recvtime = tv.tv_sec; - + if (msg.msg_controllen >= sizeof(struct cmsghdr)) for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO) @@ -455,6 +460,14 @@ void dhcp_packet(time_t now, int pxe_fd) #elif defined(HAVE_BSD_NETWORK) else { +#ifdef HAVE_DUMPFILE + dest.sin_addr.s_addr = (ntohs(mess->flags) & 0x8000) ? INADDR_BROADCAST : mess->yiaddr; + dest.sin_port = htons(daemon->dhcp_client_port); + + dump_packet(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL, + (union mysockaddr *)&dest, daemon->dhcp_server_port); +#endif + send_via_bpf(mess, iov.iov_len, iface_addr, &ifr); return; } @@ -463,6 +476,11 @@ void dhcp_packet(time_t now, int pxe_fd) #ifdef HAVE_SOLARIS_NETWORK setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index)); #endif + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL, + (union mysockaddr *)&dest, daemon->dhcp_server_port); +#endif while(retry_send(sendmsg(fd, &msg, 0))); @@ -1114,6 +1132,17 @@ static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, to.in.sin_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; } +#ifdef HAVE_DUMPFILE + { + union mysockaddr fromsock; + fromsock.in.sin_port = htons(daemon->dhcp_server_port); + fromsock.in.sin_addr = from.addr4; + fromsock.sa.sa_family = AF_INET; + + dump_packet(DUMP_DHCP, (void *)mess, sz, &fromsock, &to, 0); + } +#endif + send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0); if (option_bool(OPT_LOG_OPTS)) diff --git a/src/dnsmasq/dhcp6.c b/src/dnsmasq/dhcp6.c index 98312553..a3437402 100644 --- a/src/dnsmasq/dhcp6.c +++ b/src/dnsmasq/dhcp6.c @@ -119,6 +119,11 @@ void dhcp6_packet(time_t now) if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1) return; +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz, + (union mysockaddr *)&from, NULL, DHCPV6_SERVER_PORT); +#endif + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo) { @@ -137,6 +142,11 @@ void dhcp6_packet(time_t now) if (relay_reply6(&from, sz, ifr.ifr_name)) { +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL, + (union mysockaddr *)&from, DHCPV6_SERVER_PORT); +#endif + while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, save_counter(-1), 0, (struct sockaddr *)&from, sizeof(from)))); @@ -144,7 +154,7 @@ void dhcp6_packet(time_t now) else { struct dhcp_bridge *bridge, *alias; - + for (tmp = daemon->if_except; tmp; tmp = tmp->next) if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name)) return; @@ -161,7 +171,7 @@ void dhcp6_packet(time_t now) memset(&parm.fallback, 0, IN6ADDRSZ); memset(&parm.ll_addr, 0, IN6ADDRSZ); memset(&parm.ula_addr, 0, IN6ADDRSZ); - + /* If the interface on which the DHCPv6 request was received is an alias of some other interface (as specified by the --bridge-interface option), change parm.ind so that we look @@ -199,13 +209,13 @@ void dhcp6_packet(time_t now) context->current = context; memset(&context->local6, 0, IN6ADDRSZ); } - + for (relay = daemon->relay6; relay; relay = relay->next) relay->current = relay; if (!iface_enumerate(AF_INET6, &parm, complete_context6)) return; - + if (daemon->if_names || daemon->if_addrs) { @@ -233,7 +243,7 @@ void dhcp6_packet(time_t now) /* May have configured relay, but not DHCP server */ if (!daemon->doing_dhcp6) return; - + lease_prune(NULL, now); /* lose any expired leases */ port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback, @@ -246,11 +256,16 @@ void dhcp6_packet(time_t now) if (port != 0) { from.sin6_port = htons(port); - while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, - save_counter(-1), 0, (struct sockaddr *)&from, - sizeof(from)))); + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), + NULL, (union mysockaddr *)&from, DHCPV6_SERVER_PORT); +#endif + + while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, + save_counter(-1), 0, (struct sockaddr *)&from, sizeof(from)))); } - + /* These need to be called _after_ we send DHCPv6 packet, since lease_update_file() may trigger sending an RA packet, which overwrites our buffer. */ lease_update_file(now); diff --git a/src/dnsmasq/dnsmasq.h b/src/dnsmasq/dnsmasq.h index e103ca8b..dfba7eaa 100644 --- a/src/dnsmasq/dnsmasq.h +++ b/src/dnsmasq/dnsmasq.h @@ -702,14 +702,17 @@ struct hostsfile { }; /* packet-dump flags */ -#define DUMP_QUERY 0x0001 -#define DUMP_REPLY 0x0002 -#define DUMP_UP_QUERY 0x0004 -#define DUMP_UP_REPLY 0x0008 -#define DUMP_SEC_QUERY 0x0010 -#define DUMP_SEC_REPLY 0x0020 -#define DUMP_BOGUS 0x0040 -#define DUMP_SEC_BOGUS 0x0080 +#define DUMP_QUERY 0x0001 +#define DUMP_REPLY 0x0002 +#define DUMP_UP_QUERY 0x0004 +#define DUMP_UP_REPLY 0x0008 +#define DUMP_SEC_QUERY 0x0010 +#define DUMP_SEC_REPLY 0x0020 +#define DUMP_BOGUS 0x0040 +#define DUMP_SEC_BOGUS 0x0080 +#define DUMP_DHCP 0x1000 +#define DUMP_DHCPV6 0x2000 +#define DUMP_TFTP 0x8000 /* DNSSEC status values. */ #define STAT_SECURE 0x10000 @@ -1834,7 +1837,8 @@ int do_arp_script_run(void); /* dump.c */ #ifdef HAVE_DUMPFILE void dump_init(void); -void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst); +void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, + union mysockaddr *dst, unsigned short port); #endif /* domain-match.c */ diff --git a/src/dnsmasq/dump.c b/src/dnsmasq/dump.c index 14365d80..4aae0087 100644 --- a/src/dnsmasq/dump.c +++ b/src/dnsmasq/dump.c @@ -79,7 +79,8 @@ void dump_init(void) } } -void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst) +void dump_packet(int mask, void *packet, size_t len, + union mysockaddr *src, union mysockaddr *dst, unsigned short port) { struct ip ip; struct ip6_hdr ip6; @@ -101,7 +102,7 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio return; /* So wireshark can Id the packet. */ - udp.uh_sport = udp.uh_dport = htons(NAMESERVER_PORT); + udp.uh_sport = udp.uh_dport = htons(port); if (src) family = src->sa.sa_family; diff --git a/src/dnsmasq/forward.c b/src/dnsmasq/forward.c index 7945d460..4c061227 100644 --- a/src/dnsmasq/forward.c +++ b/src/dnsmasq/forward.c @@ -149,22 +149,6 @@ static void server_send(struct server *server, int fd, sa_len(&server->addr)))); } -#ifdef HAVE_DNSSEC -// Pi-hole modified -#define server_send_log(server, fd, header, plen, dumpflags, logflags, name, arg, type) _server_send_log(server, fd, header, plen, dumpflags, logflags, name, arg, type, __LINE__) -static void _server_send_log(struct server *server, int fd, - const void *header, size_t plen, int dumpflags, - unsigned int logflags, char *name, char *arg, - unsigned short type, const int line) -{ -#ifdef HAVE_DUMPFILE - dump_packet(dumpflags, (void *)header, (size_t)plen, NULL, &server->addr); -#endif - _log_query_mysockaddr(logflags, name, &server->addr, arg, type, line); - server_send(server, fd, header, plen, 0); -} -#endif - static int domain_no_rebind(char *domain) { struct rebind_domain *rbd; @@ -536,7 +520,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr, if (errno == 0) { #ifdef HAVE_DUMPFILE - dump_packet(DUMP_UP_QUERY, (void *)header, plen, NULL, &srv->addr); + dump_packet(DUMP_UP_QUERY, (void *)header, plen, NULL, &srv->addr, daemon->port); #endif /* Keep info in case we want to re-send this packet */ @@ -878,7 +862,7 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header, #ifdef HAVE_DUMPFILE if (STAT_ISEQUAL(status, STAT_BOGUS)) dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_BOGUS : DUMP_BOGUS, - header, (size_t)plen, &forward->sentto->addr, NULL); + header, (size_t)plen, &forward->sentto->addr, NULL, daemon->port); #endif } @@ -987,9 +971,13 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header, if (option_bool(OPT_CONNTRACK)) set_outgoing_mark(orig, fd); #endif - server_send_log(server, fd, header, nn, DUMP_SEC_QUERY, - F_NOEXTRA | F_DNSSEC | F_SERVER, daemon->keyname, - STAT_ISEQUAL(status, STAT_NEED_KEY) ? "dnssec-query[DNSKEY]" : "dnssec-query[DS]", 0); + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)nn, NULL, &server->addr, daemon->port); +#endif + log_query_mysockaddr(F_NOEXTRA | F_DNSSEC | F_SERVER, daemon->keyname, &server->addr, + STAT_ISEQUAL(status, STAT_NEED_KEY) ? "dnssec-query[DNSKEY]" : "dnssec-query[DS]", 0); + server_send(server, fd, header, nn, 0); server->queries++; return; } @@ -1081,7 +1069,7 @@ void reply_query(int fd, time_t now) #ifdef HAVE_DUMPFILE dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY, - (void *)header, n, &serveraddr, NULL); + (void *)header, n, &serveraddr, NULL, daemon->port); #endif /* log_query gets called indirectly all over the place, so @@ -1285,8 +1273,9 @@ static void return_reply(time_t now, struct frec *forward, struct dns_header *he header->id = htons(src->orig_id); #ifdef HAVE_DUMPFILE - dump_packet(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &src->source); + dump_packet(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &src->source, daemon->port); #endif + #if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS) if (option_bool(OPT_CMARK_ALST_EN)) { @@ -1612,7 +1601,7 @@ void receive_query(struct listener *listen, time_t now) daemon->log_source_addr = &source_addr; #ifdef HAVE_DUMPFILE - dump_packet(DUMP_QUERY, daemon->packet, (size_t)n, &source_addr, NULL); + dump_packet(DUMP_QUERY, daemon->packet, (size_t)n, &source_addr, NULL, daemon->port); #endif #ifdef HAVE_CONNTRACK @@ -1702,7 +1691,7 @@ void receive_query(struct listener *listen, time_t now) if (m >= 1) { #ifdef HAVE_DUMPFILE - dump_packet(DUMP_REPLY, daemon->packet, m, NULL, &source_addr); + dump_packet(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, daemon->port); #endif send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND), (char *)header, m, &source_addr, &dst_addr, if_index); @@ -1718,7 +1707,7 @@ void receive_query(struct listener *listen, time_t now) if (m >= 1) { #ifdef HAVE_DUMPFILE - dump_packet(DUMP_REPLY, daemon->packet, m, NULL, &source_addr); + dump_packet(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, daemon->port); #endif #if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS) if (local_auth) @@ -1774,7 +1763,7 @@ void receive_query(struct listener *listen, time_t now) if (m >= 1) { #ifdef HAVE_DUMPFILE - dump_packet(DUMP_REPLY, daemon->packet, m, NULL, &source_addr); + dump_packet(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, daemon->port); #endif #if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS) if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask)) diff --git a/src/dnsmasq/rfc3315.c b/src/dnsmasq/rfc3315.c index a286395d..6c55672f 100644 --- a/src/dnsmasq/rfc3315.c +++ b/src/dnsmasq/rfc3315.c @@ -2176,6 +2176,18 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, } } +#ifdef HAVE_DUMPFILE + { + union mysockaddr fromsock; + fromsock.in6.sin6_port = htons(DHCPV6_SERVER_PORT); + fromsock.in6.sin6_addr = from.addr6; + fromsock.sa.sa_family = AF_INET6; + fromsock.in6.sin6_flowinfo = 0; + fromsock.in6.sin6_scope_id = 0; + + dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), &fromsock, &to, 0); + } +#endif send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(-1), &to, &from, 0); if (option_bool(OPT_LOG_OPTS)) diff --git a/src/dnsmasq/tftp.c b/src/dnsmasq/tftp.c index b82d89d9..bdf37a38 100644 --- a/src/dnsmasq/tftp.c +++ b/src/dnsmasq/tftp.c @@ -95,6 +95,10 @@ void tftp_request(struct listener *listen, time_t now) if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2) return; + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_TFTP, (void *)packet, len, (union mysockaddr *)&peer, NULL, TFTP_PORT); +#endif /* Can always get recvd interface for IPv6 */ if (!check_dest) @@ -482,6 +486,10 @@ void tftp_request(struct listener *listen, time_t now) } send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), packet, len, &peer, &addra, if_index); + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_TFTP, (void *)packet, len, NULL, (union mysockaddr *)&peer, TFTP_PORT); +#endif if (is_err) free_transfer(transfer); @@ -600,6 +608,10 @@ void check_tftp_listeners(time_t now) prettyprint_addr(&peer, daemon->addrbuff); len = tftp_err(ERR_TID, daemon->packet, _("ignoring packet from %s (TID mismatch)"), daemon->addrbuff, NULL); while(retry_send(sendto(transfer->sockfd, daemon->packet, len, 0, &peer.sa, sa_len(&peer)))); + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_TFTP, (void *)daemon->packet, len, NULL, (union mysockaddr *)&peer, TFTP_PORT); +#endif } } } @@ -634,9 +646,14 @@ void check_tftp_listeners(time_t now) } if (len != 0) - send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), daemon->packet, len, - &transfer->peer, &transfer->source, transfer->if_index); - + { + send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), daemon->packet, len, + &transfer->peer, &transfer->source, transfer->if_index); +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_TFTP, (void *)daemon->packet, len, NULL, (union mysockaddr *)&transfer->peer, TFTP_PORT); +#endif + } + if (endcon || len == 0) { strcpy(daemon->namebuff, transfer->file->filename); From 172c60fdd01ec88981099b1eff1a5f405d486e85 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Sat, 29 Jan 2022 22:52:21 +0000 Subject: [PATCH 24/33] Extend packet dump system to RA. Signed-off-by: DL6ER --- src/dnsmasq/dnsmasq.h | 3 +- src/dnsmasq/dump.c | 88 +++++++++++++++++++++++++++++++++---------- src/dnsmasq/radv.c | 18 +++++++-- 3 files changed, 85 insertions(+), 24 deletions(-) diff --git a/src/dnsmasq/dnsmasq.h b/src/dnsmasq/dnsmasq.h index dfba7eaa..acec23d7 100644 --- a/src/dnsmasq/dnsmasq.h +++ b/src/dnsmasq/dnsmasq.h @@ -712,6 +712,7 @@ struct hostsfile { #define DUMP_SEC_BOGUS 0x0080 #define DUMP_DHCP 0x1000 #define DUMP_DHCPV6 0x2000 +#define DUMP_RA 0x4000 #define DUMP_TFTP 0x8000 /* DNSSEC status values. */ @@ -1838,7 +1839,7 @@ int do_arp_script_run(void); #ifdef HAVE_DUMPFILE void dump_init(void); void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, - union mysockaddr *dst, unsigned short port); + union mysockaddr *dst, int port); #endif /* domain-match.c */ diff --git a/src/dnsmasq/dump.c b/src/dnsmasq/dump.c index 4aae0087..3d9ef1fc 100644 --- a/src/dnsmasq/dump.c +++ b/src/dnsmasq/dump.c @@ -18,6 +18,8 @@ #ifdef HAVE_DUMPFILE +#include + static u32 packet_count; /* https://wiki.wireshark.org/Development/LibpcapFileFormat */ @@ -79,8 +81,9 @@ void dump_init(void) } } +/* port == -1 ->ICMPv6 */ void dump_packet(int mask, void *packet, size_t len, - union mysockaddr *src, union mysockaddr *dst, unsigned short port) + union mysockaddr *src, union mysockaddr *dst, int port) { struct ip ip; struct ip6_hdr ip6; @@ -116,10 +119,19 @@ void dump_packet(int mask, void *packet, size_t len, memset(&ip6, 0, sizeof(ip6)); ip6.ip6_vfc = 6 << 4; - ip6.ip6_plen = htons(sizeof(struct udphdr) + len); - ip6.ip6_nxt = IPPROTO_UDP; ip6.ip6_hops = 64; + if (port == -1) + { + ip6.ip6_plen = htons(len); + ip6.ip6_nxt = IPPROTO_ICMPV6; + } + else + { + ip6.ip6_plen = htons(sizeof(struct udphdr) + len); + ip6.ip6_nxt = IPPROTO_UDP; + } + if (src) { memcpy(&ip6.ip6_src, &src->in6.sin6_addr, IN6ADDRSZ); @@ -137,7 +149,6 @@ void dump_packet(int mask, void *packet, size_t len, { sum += ip6.ip6_src.s6_addr[i] + (ip6.ip6_src.s6_addr[i+1] << 8) ; sum += ip6.ip6_dst.s6_addr[i] + (ip6.ip6_dst.s6_addr[i+1] << 8) ; - } } else @@ -148,9 +159,18 @@ void dump_packet(int mask, void *packet, size_t len, ip.ip_v = IPVERSION; ip.ip_hl = sizeof(struct ip) / 4; - ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len); ip.ip_ttl = IPDEFTTL; - ip.ip_p = IPPROTO_UDP; + + if (port == -1) + { + ip.ip_len = htons(sizeof(struct ip) + len); + ip.ip_p = IPPROTO_ICMP; + } + else + { + ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len); + ip.ip_p = IPPROTO_UDP; + } if (src) { @@ -181,31 +201,59 @@ void dump_packet(int mask, void *packet, size_t len, if (len & 1) ((unsigned char *)packet)[len] = 0; /* for checksum, in case length is odd. */ - udp.uh_sum = 0; - udp.uh_ulen = htons(sizeof(struct udphdr) + len); - sum += htons(IPPROTO_UDP); - sum += htons(sizeof(struct udphdr) + len); - for (i = 0; i < sizeof(struct udphdr)/2; i++) - sum += ((u16 *)&udp)[i]; - for (i = 0; i < (len + 1) / 2; i++) - sum += ((u16 *)packet)[i]; - while (sum >> 16) - sum = (sum & 0xffff) + (sum >> 16); - udp.uh_sum = (sum == 0xffff) ? sum : ~sum; + if (port == -1) + { + /* ICMP - ICMPv6 packet is a superset of ICMP */ + struct icmp6_hdr *icmp = packet; + + /* See comment in UDP code below. */ + sum += htons(family == AF_INET6 ? IPPROTO_ICMPV6 : IPPROTO_ICMP); + sum += htons(len); + + icmp->icmp6_cksum = 0; + for (i = 0; i < (len + 1) / 2; i++) + sum += ((u16 *)packet)[i]; + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + icmp->icmp6_cksum = (sum == 0xffff) ? sum : ~sum; + pcap_header.incl_len = pcap_header.orig_len = ipsz + len; + } + else + { + /* Add Remaining part of the pseudoheader. Note that though the + IPv6 pseudoheader is very different to the IPv4 one, the + net result of this calculation is correct as long as the + packet length is less than 65536, which is fine for us. */ + sum += htons(IPPROTO_UDP); + sum += htons(sizeof(struct udphdr) + len); + + udp.uh_sum = 0; + udp.uh_ulen = htons(sizeof(struct udphdr) + len); + + for (i = 0; i < sizeof(struct udphdr)/2; i++) + sum += ((u16 *)&udp)[i]; + for (i = 0; i < (len + 1) / 2; i++) + sum += ((u16 *)packet)[i]; + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + udp.uh_sum = (sum == 0xffff) ? sum : ~sum; + + pcap_header.incl_len = pcap_header.orig_len = ipsz + sizeof(udp) + len; + } + rc = gettimeofday(&time, NULL); pcap_header.ts_sec = time.tv_sec; pcap_header.ts_usec = time.tv_usec; - pcap_header.incl_len = pcap_header.orig_len = ipsz + sizeof(udp) + len; if (rc == -1 || !read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 0) || !read_write(daemon->dumpfd, iphdr, ipsz, 0) || - !read_write(daemon->dumpfd, (void *)&udp, sizeof(udp), 0) || + (port != -1 && !read_write(daemon->dumpfd, (void *)&udp, sizeof(udp), 0)) || !read_write(daemon->dumpfd, (void *)packet, len, 0)) my_syslog(LOG_ERR, _("failed to write packet dump")); else - my_syslog(LOG_INFO, _("dumping UDP packet %u mask 0x%04x"), ++packet_count, mask); + my_syslog(LOG_INFO, _("dumping packet %u mask 0x%04x"), ++packet_count, mask); } diff --git a/src/dnsmasq/radv.c b/src/dnsmasq/radv.c index 2b6d9442..021c62ad 100644 --- a/src/dnsmasq/radv.c +++ b/src/dnsmasq/radv.c @@ -123,7 +123,11 @@ void ra_start_unsolicited(time_t now, struct dhcp_context *context) and pick up new interfaces */ if (context) - context->ra_short_period_start = context->ra_time = now; + { + context->ra_short_period_start = now; + /* start after 1 second to get logging right at startup. */ + context->ra_time = now + 1; + } else for (context = daemon->dhcp6; context; context = context->next) if (!(context->flags & CONTEXT_TEMPLATE)) @@ -162,7 +166,7 @@ void icmp6_packet(time_t now) return; packet = (unsigned char *)daemon->outpacket.iov_base; - + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo) { @@ -187,13 +191,17 @@ void icmp6_packet(time_t now) if (packet[1] != 0) return; - + if (packet[0] == ICMP6_ECHO_REPLY) lease_ping_reply(&from.sin6_addr, packet, interface); else if (packet[0] == ND_ROUTER_SOLICIT) { char *mac = ""; struct dhcp_bridge *bridge, *alias; + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_RA, (void *)packet, sz, (union mysockaddr *)&from, NULL, -1); +#endif /* look for link-layer address option for logging */ if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz) @@ -543,6 +551,10 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &send_iface, sizeof(send_iface)); } +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_RA, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL, (union mysockaddr *)&addr, -1); +#endif + while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(-1), 0, (struct sockaddr *)&addr, sizeof(addr)))); From e0d0daf8e74fab5bfd5cda90f40c3b9d3ce78c73 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Sat, 29 Jan 2022 23:22:52 +0000 Subject: [PATCH 25/33] Handle options other than source link-layer address in router solicitations. RFC 4861 para 4.1 is a MUST. Signed-off-by: DL6ER --- src/dnsmasq/radv.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/dnsmasq/radv.c b/src/dnsmasq/radv.c index 021c62ad..2b4326c0 100644 --- a/src/dnsmasq/radv.c +++ b/src/dnsmasq/radv.c @@ -198,21 +198,29 @@ void icmp6_packet(time_t now) { char *mac = ""; struct dhcp_bridge *bridge, *alias; - + ssize_t rem; + unsigned char *p; + int opt_sz; + #ifdef HAVE_DUMPFILE dump_packet(DUMP_RA, (void *)packet, sz, (union mysockaddr *)&from, NULL, -1); #endif /* look for link-layer address option for logging */ - if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz) + for (rem = sz - 8, p = &packet[8]; rem >= 2; rem -= opt_sz, p += opt_sz) { - if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) { - return; - } - print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2); - mac = daemon->namebuff; + opt_sz = p[1] * 8; + + if (opt_sz == 0 || opt_sz > rem) + return; /* Bad packet */ + + if (p[0] == ICMP6_OPT_SOURCE_MAC && ((opt_sz - 2) * 3 - 1 < MAXDNAME)) + { + print_mac(daemon->namebuff, &p[2], opt_sz - 2); + mac = daemon->namebuff; + } } - + if (!option_bool(OPT_QUIET_RA)) my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac); From ea5086969c893bd3591ff3fb7f9fe5d01fda3763 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Sun, 30 Jan 2022 00:42:46 +0000 Subject: [PATCH 26/33] Dump.c Fix IPv6 checksum on big-endian. Signed-off-by: DL6ER --- src/dnsmasq/dump.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dnsmasq/dump.c b/src/dnsmasq/dump.c index 3d9ef1fc..7b15945c 100644 --- a/src/dnsmasq/dump.c +++ b/src/dnsmasq/dump.c @@ -147,8 +147,8 @@ void dump_packet(int mask, void *packet, size_t len, /* start UDP checksum */ for (sum = 0, i = 0; i < IN6ADDRSZ; i+=2) { - sum += ip6.ip6_src.s6_addr[i] + (ip6.ip6_src.s6_addr[i+1] << 8) ; - sum += ip6.ip6_dst.s6_addr[i] + (ip6.ip6_dst.s6_addr[i+1] << 8) ; + sum += ntohs((ip6.ip6_src.s6_addr[i] << 8) + (ip6.ip6_src.s6_addr[i+1])) ; + sum += ntohs((ip6.ip6_dst.s6_addr[i] << 8) + (ip6.ip6_dst.s6_addr[i+1])) ; } } else @@ -207,7 +207,7 @@ void dump_packet(int mask, void *packet, size_t len, struct icmp6_hdr *icmp = packet; /* See comment in UDP code below. */ - sum += htons(family == AF_INET6 ? IPPROTO_ICMPV6 : IPPROTO_ICMP); + sum += htons((family == AF_INET6) ? IPPROTO_ICMPV6 : IPPROTO_ICMP); sum += htons(len); icmp->icmp6_cksum = 0; From 82ac2ee9a581472193e29789d98973431ea6b0c3 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Tue, 1 Feb 2022 00:18:44 +0000 Subject: [PATCH 27/33] Improve the performance of DHCP relay. On machines with many interfaces, enumerating them via netlink on each packet reciept is slow, and unneccesary. All we need is the local address->interface mapping, which can be cached in the relay structures. Signed-off-by: DL6ER --- src/dnsmasq/dhcp.c | 183 +++++++++++++++++++++--------------------- src/dnsmasq/dhcp6.c | 57 ++++++------- src/dnsmasq/dnsmasq.h | 4 +- src/dnsmasq/network.c | 11 +++ src/dnsmasq/rfc3315.c | 169 +++++++++++++++++++------------------- 5 files changed, 217 insertions(+), 207 deletions(-) diff --git a/src/dnsmasq/dhcp.c b/src/dnsmasq/dhcp.c index de766c10..a71ddf0c 100644 --- a/src/dnsmasq/dhcp.c +++ b/src/dnsmasq/dhcp.c @@ -20,8 +20,6 @@ struct iface_param { struct dhcp_context *current; - struct dhcp_relay *relay; - struct in_addr relay_local; int ind; }; @@ -34,7 +32,7 @@ static int complete_context(struct in_addr local, int if_index, char *label, struct in_addr netmask, struct in_addr broadcast, void *vparam); static int check_listen_addrs(struct in_addr local, int if_index, char *label, struct in_addr netmask, struct in_addr broadcast, void *vparam); -static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index); +static int relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz); static struct dhcp_relay *relay_reply4(struct dhcp_packet *mess, char *arrival_interface); static int make_fd(int port) @@ -307,12 +305,7 @@ void dhcp_packet(time_t now, int pxe_fd) for (context = daemon->dhcp; context; context = context->next) context->current = context; - for (relay = daemon->relay4; relay; relay = relay->next) - relay->current = relay; - parm.current = NULL; - parm.relay = NULL; - parm.relay_local.s_addr = 0; parm.ind = iface_index; if (!iface_check(AF_INET, (union all_addr *)&iface_addr, ifr.ifr_name, NULL)) @@ -334,15 +327,19 @@ void dhcp_packet(time_t now, int pxe_fd) there is more than one address on the interface in the same subnet */ complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm); } + + if (relay_upstream4(iface_index, mess, (size_t)sz)) + return; if (!iface_enumerate(AF_INET, &parm, complete_context)) return; - /* We're relaying this request */ - if (parm.relay_local.s_addr != 0 && - relay_upstream4(parm.relay, mess, (size_t)sz, iface_index)) + /* Check for a relay again after iface_enumerate/complete_context has had + chance to fill in relay->iface_index fields. This handles first time through + and any changes in interface config. */ + if (relay_upstream4(iface_index, mess, (size_t)sz)) return; - + /* May have configured relay, but not DHCP server */ if (!daemon->dhcp) return; @@ -631,14 +628,9 @@ static int complete_context(struct in_addr local, int if_index, char *label, } for (relay = daemon->relay4; relay; relay = relay->next) - if (if_index == param->ind && relay->local.addr4.s_addr == local.s_addr && relay->current == relay && - (param->relay_local.s_addr == 0 || param->relay_local.s_addr == local.s_addr)) - { - relay->current = param->relay; - param->relay = relay; - param->relay_local = local; - } - + if (relay->local.addr4.s_addr == local.s_addr) + relay->iface_index = if_index; + return 1; } @@ -1079,85 +1071,96 @@ char *host_from_dns(struct in_addr addr) return NULL; } -static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index) +static int relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz) { - /* ->local is same value for all relays on ->current chain */ - union all_addr from; - + struct in_addr giaddr = mess->giaddr; + u8 hops = mess->hops; + struct dhcp_relay *relay; + if (mess->op != BOOTREQUEST) return 0; - /* source address == relay address */ - from.addr4 = relay->local.addr4; + for (relay = daemon->relay4; relay; relay = relay->next) + if (relay->iface_index != 0 && relay->iface_index == iface_index) + break; + + /* No relay config. */ + if (!relay) + return 0; - /* already gatewayed ? */ - if (mess->giaddr.s_addr) - { - /* if so check if by us, to stomp on loops. */ - if (mess->giaddr.s_addr == relay->local.addr4.s_addr) - return 1; - } - else - { - /* plug in our address */ - mess->giaddr.s_addr = relay->local.addr4.s_addr; - } - - if ((mess->hops++) > 20) - return 1; - - for (; relay; relay = relay->current) - { - union mysockaddr to; - - to.sa.sa_family = AF_INET; - to.in.sin_addr = relay->server.addr4; - to.in.sin_port = htons(daemon->dhcp_server_port); - - /* Broadcasting to server. */ - if (relay->server.addr4.s_addr == 0) - { - struct ifreq ifr; - - if (relay->interface) - safe_strncpy(ifr.ifr_name, relay->interface, IF_NAMESIZE); - - if (!relay->interface || strchr(relay->interface, '*') || - ioctl(daemon->dhcpfd, SIOCGIFBRDADDR, &ifr) == -1) - { - my_syslog(MS_DHCP | LOG_ERR, _("Cannot broadcast DHCP relay via interface %s"), relay->interface); - return 1; - } - - to.in.sin_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; - } - -#ifdef HAVE_DUMPFILE + for (; relay; relay = relay->next) + if (relay->iface_index != 0 && relay->iface_index == iface_index) { - union mysockaddr fromsock; - fromsock.in.sin_port = htons(daemon->dhcp_server_port); - fromsock.in.sin_addr = from.addr4; - fromsock.sa.sa_family = AF_INET; + union mysockaddr to; + union all_addr from; + + mess->hops = hops; + mess->giaddr = giaddr; - dump_packet(DUMP_DHCP, (void *)mess, sz, &fromsock, &to, 0); - } -#endif - - send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0); - - if (option_bool(OPT_LOG_OPTS)) + if ((mess->hops++) > 20) + continue; + + /* source address == relay address */ + from.addr4 = relay->local.addr4; + + /* already gatewayed ? */ + if (giaddr.s_addr) + { + /* if so check if by us, to stomp on loops. */ + if (giaddr.s_addr == relay->local.addr4.s_addr) + continue; + } + else + { + /* plug in our address */ + mess->giaddr.s_addr = relay->local.addr4.s_addr; + } + + to.sa.sa_family = AF_INET; + to.in.sin_addr = relay->server.addr4; + to.in.sin_port = htons(daemon->dhcp_server_port); + + /* Broadcasting to server. */ + if (relay->server.addr4.s_addr == 0) + { + struct ifreq ifr; + + if (relay->interface) + safe_strncpy(ifr.ifr_name, relay->interface, IF_NAMESIZE); + + if (!relay->interface || strchr(relay->interface, '*') || + ioctl(daemon->dhcpfd, SIOCGIFBRDADDR, &ifr) == -1) + { + my_syslog(MS_DHCP | LOG_ERR, _("Cannot broadcast DHCP relay via interface %s"), relay->interface); + continue; + } + + to.in.sin_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; + } + +#ifdef HAVE_DUMPFILE { - inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN); - if (relay->server.addr4.s_addr == 0) - snprintf(daemon->dhcp_buff2, DHCP_BUFF_SZ, _("broadcast via %s"), relay->interface); - else - inet_ntop(AF_INET, &relay->server.addr4, daemon->dhcp_buff2, DHCP_BUFF_SZ); - my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->dhcp_buff2); + union mysockaddr fromsock; + fromsock.in.sin_port = htons(daemon->dhcp_server_port); + fromsock.in.sin_addr = from.addr4; + fromsock.sa.sa_family = AF_INET; + + dump_packet(DUMP_DHCP, (void *)mess, sz, &fromsock, &to, 0); } - - /* Save this for replies */ - relay->iface_index = iface_index; - } +#endif + + send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0); + + if (option_bool(OPT_LOG_OPTS)) + { + inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN); + if (relay->server.addr4.s_addr == 0) + snprintf(daemon->dhcp_buff2, DHCP_BUFF_SZ, _("broadcast via %s"), relay->interface); + else + inet_ntop(AF_INET, &relay->server.addr4, daemon->dhcp_buff2, DHCP_BUFF_SZ); + my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->dhcp_buff2); + } + } return 1; } diff --git a/src/dnsmasq/dhcp6.c b/src/dnsmasq/dhcp6.c index a3437402..edb87a4a 100644 --- a/src/dnsmasq/dhcp6.c +++ b/src/dnsmasq/dhcp6.c @@ -22,8 +22,7 @@ struct iface_param { struct dhcp_context *current; - struct dhcp_relay *relay; - struct in6_addr fallback, relay_local, ll_addr, ula_addr; + struct in6_addr fallback, ll_addr, ula_addr; int ind, addr_match; }; @@ -90,7 +89,6 @@ void dhcp6_init(void) void dhcp6_packet(time_t now) { struct dhcp_context *context; - struct dhcp_relay *relay; struct iface_param parm; struct cmsghdr *cmptr; struct msghdr msg; @@ -105,7 +103,8 @@ void dhcp6_packet(time_t now) struct iname *tmp; unsigned short port; struct in6_addr dst_addr; - + struct in6_addr all_servers; + memset(&dst_addr, 0, sizeof(dst_addr)); msg.msg_control = control_u.control6; @@ -164,8 +163,6 @@ void dhcp6_packet(time_t now) return; parm.current = NULL; - parm.relay = NULL; - memset(&parm.relay_local, 0, IN6ADDRSZ); parm.ind = if_index; parm.addr_match = 0; memset(&parm.fallback, 0, IN6ADDRSZ); @@ -210,12 +207,24 @@ void dhcp6_packet(time_t now) memset(&context->local6, 0, IN6ADDRSZ); } - for (relay = daemon->relay6; relay; relay = relay->next) - relay->current = relay; + /* Ignore requests sent to the ALL_SERVERS multicast address for relay when + we're listening there for DHCPv6 server reasons. */ + inet_pton(AF_INET6, ALL_SERVERS, &all_servers); + + if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) && + relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now)) + return; if (!iface_enumerate(AF_INET6, &parm, complete_context6)) return; + /* Check for a relay again after iface_enumerate/complete_context has had + chance to fill in relay->iface_index fields. This handles first time through + and any changes in interface config. */ + if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) && + relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now)) + return; + if (daemon->if_names || daemon->if_addrs) { @@ -227,19 +236,6 @@ void dhcp6_packet(time_t now) return; } - if (parm.relay) - { - /* Ignore requests sent to the ALL_SERVERS multicast address for relay when - we're listening there for DHCPv6 server reasons. */ - struct in6_addr all_servers; - - inet_pton(AF_INET6, ALL_SERVERS, &all_servers); - - if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers)) - relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id, now); - return; - } - /* May have configured relay, but not DHCP server */ if (!daemon->doing_dhcp6) return; @@ -326,6 +322,7 @@ static int complete_context6(struct in6_addr *local, int prefix, struct dhcp_relay *relay; struct iface_param *param = vparam; struct iname *tmp; + int match = !daemon->if_addrs; (void)scope; /* warning */ @@ -347,7 +344,7 @@ static int complete_context6(struct in6_addr *local, int prefix, for (tmp = daemon->if_addrs; tmp; tmp = tmp->next) if (tmp->addr.sa.sa_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local)) - param->addr_match = 1; + match = param->addr_match = 1; /* Determine a globally address on the arrival interface, even if we have no matching dhcp-context, because we're only @@ -419,16 +416,12 @@ static int complete_context6(struct in6_addr *local, int prefix, } } } - - for (relay = daemon->relay6; relay; relay = relay->next) - if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6) && relay->current == relay && - (IN6_IS_ADDR_UNSPECIFIED(¶m->relay_local) || IN6_ARE_ADDR_EQUAL(local, ¶m->relay_local))) - { - relay->current = param->relay; - param->relay = relay; - param->relay_local = *local; - } - + + if (match) + for (relay = daemon->relay6; relay; relay = relay->next) + if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6)) + relay->iface_index = if_index; + return 1; } diff --git a/src/dnsmasq/dnsmasq.h b/src/dnsmasq/dnsmasq.h index acec23d7..4efbfd98 100644 --- a/src/dnsmasq/dnsmasq.h +++ b/src/dnsmasq/dnsmasq.h @@ -1101,7 +1101,7 @@ struct dhcp_relay { struct snoop_record *next; } *snoop_records; #endif - struct dhcp_relay *current, *next; + struct dhcp_relay *next; }; extern struct daemon { @@ -1722,7 +1722,7 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name, struct in6_addr *fallback, struct in6_addr *ll_addr, struct in6_addr *ula_addr, size_t sz, struct in6_addr *client_addr, time_t now); -void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, +int relay_upstream6(int iface_index, ssize_t sz, struct in6_addr *peer_address, u32 scope_id, time_t now); int relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface); diff --git a/src/dnsmasq/network.c b/src/dnsmasq/network.c index 26032553..3ef0f407 100644 --- a/src/dnsmasq/network.c +++ b/src/dnsmasq/network.c @@ -1763,6 +1763,8 @@ int reload_servers(char *fname) /* Called when addresses are added or deleted from an interface */ void newaddress(time_t now) { + struct dhcp_relay *relay; + (void)now; if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) || @@ -1771,6 +1773,12 @@ void newaddress(time_t now) if (option_bool(OPT_CLEVERBIND)) create_bound_listeners(0); + +#ifdef HAVE_DHCP + /* clear cache of subnet->relay index */ + for (relay = daemon->relay4; relay; relay = relay->next) + relay->iface_index = 0; +#endif #ifdef HAVE_DHCP6 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra) @@ -1781,5 +1789,8 @@ void newaddress(time_t now) if (daemon->doing_dhcp6) lease_find_interfaces(now); + + for (relay = daemon->relay6; relay; relay = relay->next) + relay->iface_index = 0; #endif } diff --git a/src/dnsmasq/rfc3315.c b/src/dnsmasq/rfc3315.c index 6c55672f..cee8382c 100644 --- a/src/dnsmasq/rfc3315.c +++ b/src/dnsmasq/rfc3315.c @@ -2100,110 +2100,113 @@ static unsigned int opt6_uint(unsigned char *opt, int offset, int size) return ret; } -void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, - struct in6_addr *peer_address, u32 scope_id, time_t now) +int relay_upstream6(int iface_index, ssize_t sz, + struct in6_addr *peer_address, u32 scope_id, time_t now) { - /* ->local is same value for all relays on ->current chain */ - - union all_addr from; unsigned char *header; unsigned char *inbuff = daemon->dhcp_packet.iov_base; int msg_type = *inbuff; - int hopcount; + int hopcount, o; struct in6_addr multicast; unsigned int maclen, mactype; unsigned char mac[DHCP_CHADDR_MAX]; + struct dhcp_relay *relay; + + for (relay = daemon->relay6; relay; relay = relay->next) + if (relay->iface_index != 0 && relay->iface_index == iface_index) + break; + /* No relay config. */ + if (!relay) + return 0; + inet_pton(AF_INET6, ALL_SERVERS, &multicast); get_client_mac(peer_address, scope_id, mac, &maclen, &mactype, now); - - /* source address == relay address */ - from.addr6 = relay->local.addr6; - + /* Get hop count from nested relayed message */ if (msg_type == DHCP6RELAYFORW) hopcount = *((unsigned char *)inbuff+1) + 1; else hopcount = 0; - /* RFC 3315 HOP_COUNT_LIMIT */ - if (hopcount > 32) - return; - reset_counter(); - if ((header = put_opt6(NULL, 34))) + /* RFC 3315 HOP_COUNT_LIMIT */ + if (hopcount > 32 || !(header = put_opt6(NULL, 34))) + return 1; + + header[0] = DHCP6RELAYFORW; + header[1] = hopcount; + memcpy(&header[18], peer_address, IN6ADDRSZ); + + /* RFC-6939 */ + if (maclen != 0) { - int o; - - header[0] = DHCP6RELAYFORW; - header[1] = hopcount; - memcpy(&header[2], &relay->local.addr6, IN6ADDRSZ); - memcpy(&header[18], peer_address, IN6ADDRSZ); - - /* RFC-6939 */ - if (maclen != 0) - { - o = new_opt6(OPTION6_CLIENT_MAC); - put_opt6_short(mactype); - put_opt6(mac, maclen); - end_opt6(o); - } - - o = new_opt6(OPTION6_RELAY_MSG); - put_opt6(inbuff, sz); + o = new_opt6(OPTION6_CLIENT_MAC); + put_opt6_short(mactype); + put_opt6(mac, maclen); end_opt6(o); - - for (; relay; relay = relay->current) - { - union mysockaddr to; - - to.sa.sa_family = AF_INET6; - to.in6.sin6_addr = relay->server.addr6; - to.in6.sin6_port = htons(DHCPV6_SERVER_PORT); - to.in6.sin6_flowinfo = 0; - to.in6.sin6_scope_id = 0; - - if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast)) - { - int multicast_iface; - if (!relay->interface || strchr(relay->interface, '*') || - (multicast_iface = if_nametoindex(relay->interface)) == 0 || - setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_iface, sizeof(multicast_iface)) == -1) - { - my_syslog(MS_DHCP | LOG_ERR, _("Cannot multicast DHCP relay via interface %s"), relay->interface); - return; - } - } - -#ifdef HAVE_DUMPFILE - { - union mysockaddr fromsock; - fromsock.in6.sin6_port = htons(DHCPV6_SERVER_PORT); - fromsock.in6.sin6_addr = from.addr6; - fromsock.sa.sa_family = AF_INET6; - fromsock.in6.sin6_flowinfo = 0; - fromsock.in6.sin6_scope_id = 0; - - dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), &fromsock, &to, 0); - } -#endif - send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(-1), &to, &from, 0); - - if (option_bool(OPT_LOG_OPTS)) - { - inet_ntop(AF_INET6, &relay->local, daemon->addrbuff, ADDRSTRLEN); - if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast)) - snprintf(daemon->namebuff, MAXDNAME, _("multicast via %s"), relay->interface); - else - inet_ntop(AF_INET6, &relay->server, daemon->namebuff, ADDRSTRLEN); - my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->namebuff); - } - - /* Save this for replies */ - relay->iface_index = scope_id; - } } + + o = new_opt6(OPTION6_RELAY_MSG); + put_opt6(inbuff, sz); + end_opt6(o); + + for (; relay; relay = relay->next) + if (relay->iface_index != 0 && relay->iface_index == iface_index) + { + union mysockaddr to; + union all_addr from; + + /* source address == relay address */ + from.addr6 = relay->local.addr6; + memcpy(&header[2], &relay->local.addr6, IN6ADDRSZ); + + to.sa.sa_family = AF_INET6; + to.in6.sin6_addr = relay->server.addr6; + to.in6.sin6_port = htons(DHCPV6_SERVER_PORT); + to.in6.sin6_flowinfo = 0; + to.in6.sin6_scope_id = 0; + + if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast)) + { + int multicast_iface; + if (!relay->interface || strchr(relay->interface, '*') || + (multicast_iface = if_nametoindex(relay->interface)) == 0 || + setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_iface, sizeof(multicast_iface)) == -1) + { + my_syslog(MS_DHCP | LOG_ERR, _("Cannot multicast DHCP relay via interface %s"), relay->interface); + continue; + } + } + +#ifdef HAVE_DUMPFILE + { + union mysockaddr fromsock; + fromsock.in6.sin6_port = htons(DHCPV6_SERVER_PORT); + fromsock.in6.sin6_addr = from.addr6; + fromsock.sa.sa_family = AF_INET6; + fromsock.in6.sin6_flowinfo = 0; + fromsock.in6.sin6_scope_id = 0; + + dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), &fromsock, &to, 0); + } +#endif + send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(-1), &to, &from, 0); + + if (option_bool(OPT_LOG_OPTS)) + { + inet_ntop(AF_INET6, &relay->local, daemon->addrbuff, ADDRSTRLEN); + if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast)) + snprintf(daemon->namebuff, MAXDNAME, _("multicast via %s"), relay->interface); + else + inet_ntop(AF_INET6, &relay->server, daemon->namebuff, ADDRSTRLEN); + my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->namebuff); + } + + } + + return 1; } int relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface) From 920000a15ba71321a00f5ac291f86b03b5af27a7 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Thu, 3 Feb 2022 17:12:38 +0000 Subject: [PATCH 28/33] Handle changing interface indexes when binding DHCP sockets. Signed-off-by: DL6ER --- src/dnsmasq/dhcp-common.c | 38 ++++++++++++++++++++++++++++++++++---- src/dnsmasq/dnsmasq.c | 34 +++++++++++++--------------------- src/dnsmasq/dnsmasq.h | 2 +- 3 files changed, 48 insertions(+), 26 deletions(-) diff --git a/src/dnsmasq/dhcp-common.c b/src/dnsmasq/dhcp-common.c index 4e2667f8..b33c5dfc 100644 --- a/src/dnsmasq/dhcp-common.c +++ b/src/dnsmasq/dhcp-common.c @@ -566,12 +566,16 @@ char *whichdevice(void) } if (found) - return found->name; - + { + char *ret = safe_malloc(strlen(found->name)+1); + strcpy(ret, found->name); + return ret; + } + return NULL; } -void bindtodevice(char *device, int fd) +static int bindtodevice(char *device, int fd) { size_t len = strlen(device)+1; if (len > IFNAMSIZ) @@ -579,7 +583,33 @@ void bindtodevice(char *device, int fd) /* only allowed by root. */ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, len) == -1 && errno != EPERM) - die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET); + return 2; + + return 1; +} + +int bind_dhcp_devices(char *bound_device) +{ + int ret = 0; + + if (bound_device) + { + if (daemon->dhcp) + { + if (!daemon->relay4) + ret |= bindtodevice(bound_device, daemon->dhcpfd); + + if (daemon->enable_pxe && daemon->pxefd != -1) + ret |= bindtodevice(bound_device, daemon->pxefd); + } + +#if defined(HAVE_DHCP6) + if (daemon->doing_dhcp6 && !daemon->relay6) + ret |= bindtodevice(bound_device, daemon->dhcp6fd); +#endif + } + + return ret; } #endif diff --git a/src/dnsmasq/dnsmasq.c b/src/dnsmasq/dnsmasq.c index 61b1ad8a..add4dd97 100644 --- a/src/dnsmasq/dnsmasq.c +++ b/src/dnsmasq/dnsmasq.c @@ -394,28 +394,9 @@ int main_dnsmasq (int argc, char **argv) #if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP) /* after enumerate_interfaces() */ bound_device = whichdevice(); - - if (daemon->dhcp) - { - if (!daemon->relay4 && bound_device) - { - bindtodevice(bound_device, daemon->dhcpfd); - did_bind = 1; - } - if (daemon->enable_pxe && bound_device && daemon->pxefd != -1) - { - bindtodevice(bound_device, daemon->pxefd); - did_bind = 1; - } - } -#endif -#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6) - if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device) - { - bindtodevice(bound_device, daemon->dhcp6fd); - did_bind = 1; - } + if ((did_bind = bind_dhcp_devices(bound_device)) & 2) + die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET); #endif } else @@ -1113,6 +1094,17 @@ int main_dnsmasq (int argc, char **argv) #endif #ifdef HAVE_DHCP +# if defined(HAVE_LINUX_NETWORK) + if (bind_dhcp_devices(bound_device) & 2) + { + static int warned = 0; + if (!warned) + { + my_syslog(LOG_ERR, _("error binding DHCP socket to device %s"), bound_device); + warned = 1; + } + } +# endif if (daemon->dhcp || daemon->relay4) { poll_listen(daemon->dhcpfd, POLLIN); diff --git a/src/dnsmasq/dnsmasq.h b/src/dnsmasq/dnsmasq.h index 4efbfd98..ba7f6360 100644 --- a/src/dnsmasq/dnsmasq.h +++ b/src/dnsmasq/dnsmasq.h @@ -1755,7 +1755,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs, int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type); #ifdef HAVE_LINUX_NETWORK char *whichdevice(void); -void bindtodevice(char *device, int fd); +int bind_dhcp_devices(char *bound_device); #endif # ifdef HAVE_DHCP6 void display_opts6(void); From e6c4c2941715d23bc42a2152552a9a3b939361a8 Mon Sep 17 00:00:00 2001 From: "Johnny S. Lee via Dnsmasq-discuss" Date: Thu, 3 Feb 2022 23:42:00 +0000 Subject: [PATCH 29/33] Fix FTBFS on BSD platforms. Bug introduced in fc664d114d6e11ced4912b746f18d543f662066b Signed-off-by: DL6ER --- src/dnsmasq/dhcp.c | 7 +++++-- test/dnsmasq_warnings | 2 -- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/dnsmasq/dhcp.c b/src/dnsmasq/dhcp.c index a71ddf0c..6104c87d 100644 --- a/src/dnsmasq/dhcp.c +++ b/src/dnsmasq/dhcp.c @@ -458,9 +458,12 @@ void dhcp_packet(time_t now, int pxe_fd) else { #ifdef HAVE_DUMPFILE - dest.sin_addr.s_addr = (ntohs(mess->flags) & 0x8000) ? INADDR_BROADCAST : mess->yiaddr; + if (ntohs(mess->flags) & 0x8000) + dest.sin_addr.s_addr = INADDR_BROADCAST; + else + dest.sin_addr = mess->yiaddr; dest.sin_port = htons(daemon->dhcp_client_port); - + dump_packet(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL, (union mysockaddr *)&dest, daemon->dhcp_server_port); #endif diff --git a/test/dnsmasq_warnings b/test/dnsmasq_warnings index 8ad51608..f1256266 100644 --- a/test/dnsmasq_warnings +++ b/test/dnsmasq_warnings @@ -82,8 +82,6 @@ src/dnsmasq/forward.c my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff); src/dnsmasq/forward.c my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff); -src/dnsmasq/forward.c - my_syslog(LOG_WARNING, _("detected DNSSEC dependency loop involving %s"), daemon->keyname); src/dnsmasq/forward.c my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ); src/dnsmasq/forward.c From ec386ccef5c4d60e0110bc53496e883c792d938c Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Fri, 21 Jan 2022 15:41:53 +0000 Subject: [PATCH 30/33] Tidy iface_check(). Signed-off-by: DL6ER --- src/dnsmasq/network.c | 49 +++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/dnsmasq/network.c b/src/dnsmasq/network.c index 3ef0f407..5cae606c 100644 --- a/src/dnsmasq/network.c +++ b/src/dnsmasq/network.c @@ -116,13 +116,8 @@ int iface_check(int family, union all_addr *addr, char *name, int *auth) struct iname *tmp; int ret = 1, match_addr = 0; - /* Note: have to check all and not bail out early, so that we set the - "used" flags. - - May be called with family == AF_LOCALto check interface by name only. */ - - if (auth) - *auth = 0; + /* Note: have to check all and not bail out early, so that we set the "used" flags. + May be called with family == AF_LOCAL to check interface by name only. */ if (daemon->if_names || daemon->if_addrs) { @@ -151,25 +146,29 @@ int iface_check(int family, union all_addr *addr, char *name, int *auth) if (tmp->name && wildcard_match(tmp->name, name)) ret = 0; - - for (tmp = daemon->authinterface; tmp; tmp = tmp->next) - if (tmp->name) - { - if (strcmp(tmp->name, name) == 0 && - (tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family)) - break; - } - else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET && - tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr) - break; - else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 && - IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr6)) - break; - - if (tmp && auth) + if (auth) { - *auth = 1; - ret = 1; + *auth = 0; + + for (tmp = daemon->authinterface; tmp; tmp = tmp->next) + if (tmp->name) + { + if (strcmp(tmp->name, name) == 0 && + (tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family)) + break; + } + else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET && + tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr) + break; + else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 && + IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr6)) + break; + + if (tmp) + { + *auth = 1; + ret = 1; + } } return ret; From 5bd230a4364cbfbd43bb67bd42f8b3c5825d4c27 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Fri, 4 Feb 2022 22:24:00 +0000 Subject: [PATCH 31/33] Ask netlink for new address events unconditionally. The circumstances under which actions occur depending on configuration is now controlled only by newaddress() in network.c Signed-off-by: DL6ER --- src/dnsmasq/netlink.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/dnsmasq/netlink.c b/src/dnsmasq/netlink.c index ae1426c7..da829430 100644 --- a/src/dnsmasq/netlink.c +++ b/src/dnsmasq/netlink.c @@ -66,17 +66,10 @@ char *netlink_init(void) addr.nl_pad = 0; addr.nl_pid = 0; /* autobind */ addr.nl_groups = RTMGRP_IPV4_ROUTE; - if (option_bool(OPT_CLEVERBIND)) - addr.nl_groups |= RTMGRP_IPV4_IFADDR; + addr.nl_groups |= RTMGRP_IPV4_IFADDR; addr.nl_groups |= RTMGRP_IPV6_ROUTE; - if (option_bool(OPT_CLEVERBIND)) - addr.nl_groups |= RTMGRP_IPV6_IFADDR; + addr.nl_groups |= RTMGRP_IPV6_IFADDR; -#ifdef HAVE_DHCP6 - if (daemon->doing_ra || daemon->doing_dhcp6) - addr.nl_groups |= RTMGRP_IPV6_IFADDR; -#endif - /* May not be able to have permission to set multicast groups don't die in that case */ if ((daemon->netlinkfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) != -1) { From 584e752ee4699ae330795fef54add654dd170b78 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Tue, 8 Feb 2022 11:37:06 +0000 Subject: [PATCH 32/33] Add --conf-script Signed-off-by: DL6ER --- src/dnsmasq/option.c | 74 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/src/dnsmasq/option.c b/src/dnsmasq/option.c index fd07010e..eb181ff3 100644 --- a/src/dnsmasq/option.c +++ b/src/dnsmasq/option.c @@ -183,6 +183,8 @@ struct myoption { #define LOPT_FILTER_AAAA 370 #define LOPT_STRIP_SBNET 371 #define LOPT_STRIP_MAC 372 +#define LOPT_CONF_OPT 373 +#define LOPT_CONF_SCRIPT 374 #ifdef HAVE_GETOPT_LONG static const struct option opts[] = @@ -229,6 +231,7 @@ static const struct myoption opts[] = { "local", 1, 0, LOPT_LOCAL }, { "address", 1, 0, 'A' }, { "conf-file", 2, 0, 'C' }, + { "conf-script", 1, 0, LOPT_CONF_SCRIPT }, { "no-resolv", 0, 0, 'R' }, { "expand-hosts", 0, 0, 'E' }, { "localmx", 0, 0, 'L' }, @@ -471,6 +474,7 @@ static struct { { LOPT_SCRIPTUSR, ARG_ONE, "", gettext_noop("Run lease-change scripts as this user."), NULL }, { LOPT_SCRIPT_ARP, OPT_SCRIPT_ARP, NULL, gettext_noop("Call dhcp-script with changes to local ARP table."), NULL }, { '7', ARG_DUP, "", gettext_noop("Read configuration from all the files in this directory."), NULL }, + { LOPT_CONF_SCRIPT, ARG_DUP, "", gettext_noop("Execute file and read configuration from stdin."), NULL }, { '8', ARG_ONE, "|", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL }, { '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL }, { '0', ARG_ONE, "", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" }, @@ -1814,6 +1818,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma break; } + case LOPT_CONF_SCRIPT: /* --conf-script */ + { + char *file = opt_string_alloc(arg); + if (file) + { + one_file(file, LOPT_CONF_SCRIPT); + free(file); + } + break; + } + case '7': /* --conf-dir */ { DIR *dir_stream; @@ -4970,11 +4985,19 @@ static void read_file(char *file, FILE *f, int hard_opt) while (fgets(buff, MAXDNAME, f)) { - int white, i; - volatile int option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt; + int white, i, script = 0; + volatile int option; char *errmess, *p, *arg, *start; size_t len; + if (hard_opt == LOPT_CONF_SCRIPT) + { + hard_opt = 0; + script = 1; + } + + option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt; + /* Memory allocation failure longjmps here if mem_recover == 1 */ if (option != 0 || hard_opt == LOPT_REV_SERV) { @@ -5088,7 +5111,11 @@ static void read_file(char *file, FILE *f, int hard_opt) if (errmess || !one_opt(option, arg, daemon->namebuff, _("error"), 0, hard_opt == LOPT_REV_SERV)) { - sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file); + if (script) + sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" in output from %s"), file); + else + sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file); + if (hard_opt != 0) my_syslog(LOG_ERR, "%s", daemon->namebuff); else @@ -5097,7 +5124,6 @@ static void read_file(char *file, FILE *f, int hard_opt) } mem_recover = 0; - fclose(f); } #if defined(HAVE_DHCP) && defined(HAVE_INOTIFY) @@ -5117,7 +5143,7 @@ int option_read_dynfile(char *file, int flags) static int one_file(char *file, int hard_opt) { FILE *f; - int nofile_ok = 0; + int nofile_ok = 0, do_popen = 0; static int read_stdin = 0; static struct fileread { dev_t dev; @@ -5125,13 +5151,13 @@ static int one_file(char *file, int hard_opt) struct fileread *next; } *filesread = NULL; - if (hard_opt == '7') + if (hard_opt == LOPT_CONF_OPT) { /* default conf-file reading */ hard_opt = 0; nofile_ok = 1; } - + if (hard_opt == 0 && strcmp(file, "-") == 0) { if (read_stdin == 1) @@ -5145,6 +5171,12 @@ static int one_file(char *file, int hard_opt) /* ignore repeated files. */ struct stat statbuf; + if (hard_opt == LOPT_CONF_SCRIPT) + { + hard_opt = 0; + do_popen = 1; + } + if (hard_opt == 0 && stat(file, &statbuf) == 0) { struct fileread *r; @@ -5159,8 +5191,13 @@ static int one_file(char *file, int hard_opt) r->dev = statbuf.st_dev; r->ino = statbuf.st_ino; } - - if (!(f = fopen(file, "r"))) + + if (do_popen) + { + if (!(f = popen(file, "r"))) + die(_("cannot execute %s: %s"), file, EC_FILE); + } + else if (!(f = fopen(file, "r"))) { if (errno == ENOENT && nofile_ok) return 1; /* No conffile, all done. */ @@ -5178,7 +5215,21 @@ static int one_file(char *file, int hard_opt) } } - read_file(file, f, hard_opt); + read_file(file, f, do_popen ? LOPT_CONF_SCRIPT : hard_opt); + + if (do_popen) + { + int rc; + + if ((rc = pclose(f)) == -1) + die(_("error executing %s: %s"), file, EC_MISC); + + if (rc != 0) + die(_("%s returns non-zero error code"), file, rc+10); + } + else + fclose(f); + return 1; } @@ -5319,6 +5370,7 @@ void read_servers_file(void) mark_servers(SERV_FROM_FILE); read_file(daemon->servers_file, f, LOPT_REV_SERV); + fclose(f); cleanup_servers(); check_servers(0); } @@ -5550,7 +5602,7 @@ void read_opts(int argc, char **argv, char *compile_opts) free(conffile); } else - one_file(CONFFILE, '7'); + one_file(CONFFILE, LOPT_CONF_OPT); /* port might not be known when the address is parsed - fill in here */ if (daemon->servers) From 1a9a7aa725c754d82c5ceed6046f641da4b9ad44 Mon Sep 17 00:00:00 2001 From: DL6ER Date: Tue, 8 Feb 2022 20:29:23 +0100 Subject: [PATCH 33/33] Update dnsmasq version Signed-off-by: DL6ER --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ce585519..0e374db5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,6 @@ cmake_minimum_required(VERSION 2.8.12) project(PIHOLE_FTL C) -set(DNSMASQ_VERSION pi-hole-2.87test4-18) +set(DNSMASQ_VERSION pi-hole-2.87test8) add_subdirectory(src)