mirror of
https://github.com/pi-hole/FTL.git
synced 2024-10-26 16:52:18 +02:00
Merge pull request #1281 from pi-hole/update/dnsmasq
Update embedded dnsmasq to v2.87test8
This commit is contained in:
+1
-1
@@ -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)
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+30
-16
@@ -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
|
||||
@@ -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 Source");
|
||||
my_syslog(LOG_INFO, "------------------------------ ---------------------------------------- ---------- ------------------------ ------------");
|
||||
|
||||
for (i=0; i<hash_size; i++)
|
||||
for (cache = hash_table[i]; cache; cache = cache->hash_next)
|
||||
@@ -1855,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" : " ",
|
||||
@@ -1863,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);
|
||||
}
|
||||
}
|
||||
@@ -1994,6 +2000,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 #<portnum> */
|
||||
|
||||
FTL_hook(flags, name, addr, arg, daemon->log_display_id, type, file, line);
|
||||
|
||||
@@ -2001,7 +2008,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 +2044,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;
|
||||
}
|
||||
@@ -2090,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";
|
||||
@@ -2100,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";
|
||||
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+8
-1
@@ -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
|
||||
@@ -52,6 +52,9 @@ const char* introspection_xml_template =
|
||||
" <method name=\"SetFilterWin2KOption\">\n"
|
||||
" <arg name=\"filterwin2k\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetLocaliseQueriesOption\">\n"
|
||||
" <arg name=\"localise-queries\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetBogusPrivOption\">\n"
|
||||
" <arg name=\"boguspriv\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\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");
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+118
-83
@@ -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
|
||||
@@ -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)
|
||||
@@ -177,11 +175,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)
|
||||
@@ -302,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))
|
||||
@@ -329,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;
|
||||
@@ -455,6 +457,17 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
#elif defined(HAVE_BSD_NETWORK)
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_DUMPFILE
|
||||
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
|
||||
|
||||
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)));
|
||||
|
||||
@@ -613,14 +631,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;
|
||||
}
|
||||
|
||||
@@ -1061,74 +1074,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;
|
||||
}
|
||||
for (; relay; relay = relay->next)
|
||||
if (relay->iface_index != 0 && relay->iface_index == iface_index)
|
||||
{
|
||||
union mysockaddr to;
|
||||
union all_addr from;
|
||||
|
||||
if ((mess->hops++) > 20)
|
||||
return 1;
|
||||
mess->hops = hops;
|
||||
mess->giaddr = giaddr;
|
||||
|
||||
if ((mess->hops++) > 20)
|
||||
continue;
|
||||
|
||||
/* source address == relay address */
|
||||
from.addr4 = relay->local.addr4;
|
||||
|
||||
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)
|
||||
/* 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
|
||||
{
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+50
-42
@@ -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
|
||||
@@ -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;
|
||||
@@ -119,6 +118,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 +141,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 +153,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;
|
||||
@@ -154,14 +163,12 @@ 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);
|
||||
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 +206,25 @@ 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;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
|
||||
@@ -217,23 +236,10 @@ 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;
|
||||
|
||||
|
||||
lease_prune(NULL, now); /* lose any expired leases */
|
||||
|
||||
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
|
||||
@@ -246,11 +252,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);
|
||||
@@ -311,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 */
|
||||
|
||||
@@ -332,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
|
||||
@@ -404,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+14
-22
@@ -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
|
||||
@@ -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);
|
||||
|
||||
+24
-18
@@ -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. */
|
||||
@@ -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) )
|
||||
@@ -700,14 +702,18 @@ 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_RA 0x4000
|
||||
#define DUMP_TFTP 0x8000
|
||||
|
||||
/* DNSSEC status values. */
|
||||
#define STAT_SECURE 0x10000
|
||||
@@ -734,7 +740,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
|
||||
@@ -743,7 +749,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 */
|
||||
|
||||
@@ -1096,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 {
|
||||
@@ -1717,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);
|
||||
@@ -1750,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);
|
||||
@@ -1823,7 +1828,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 */
|
||||
@@ -1833,7 +1838,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, int port);
|
||||
#endif
|
||||
|
||||
/* domain-match.c */
|
||||
|
||||
+32
-32
@@ -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 <targetidx; j++)
|
||||
if ((p2 = targets[j]))
|
||||
{
|
||||
if (neganswer)
|
||||
*neganswer = 1;
|
||||
|
||||
if (!extract_name(header, plen, &p2, name, 1, 10))
|
||||
return STAT_BOGUS; /* bad packet */
|
||||
|
||||
/* NXDOMAIN or NODATA reply, unanswered question is (name, qclass, qtype) */
|
||||
|
||||
/* For anything other than a DS record, this situation is OK if either
|
||||
the answer is in an unsigned zone, or there's a NSEC records. */
|
||||
if (!prove_non_existence(header, plen, keyname, name, qtype, qclass, NULL, nons, nsec_ttl))
|
||||
{
|
||||
/* Empty DS without NSECS */
|
||||
if (qtype == T_DS)
|
||||
return STAT_BOGUS | DNSSEC_FAIL_NONSEC;
|
||||
|
||||
if (STAT_ISEQUAL((rc = zone_status(name, qclass, keyname, now)), STAT_SECURE))
|
||||
{
|
||||
if (class)
|
||||
*class = qclass; /* Class for NEED_DS or NEED_KEY */
|
||||
return rc;
|
||||
}
|
||||
|
||||
return STAT_BOGUS | DNSSEC_FAIL_NONSEC; /* signed zone, no NSECs */
|
||||
}
|
||||
}
|
||||
for (j = 0; j <targetidx; j++)
|
||||
if ((p2 = targets[j]))
|
||||
{
|
||||
if (neganswer)
|
||||
*neganswer = 1;
|
||||
|
||||
if (!extract_name(header, plen, &p2, name, 1, 10))
|
||||
return STAT_BOGUS; /* bad packet */
|
||||
|
||||
/* NXDOMAIN or NODATA reply, unanswered question is (name, qclass, qtype) */
|
||||
|
||||
/* For anything other than a DS record, this situation is OK if either
|
||||
the answer is in an unsigned zone, or there's a NSEC records. */
|
||||
if (!prove_non_existence(header, plen, keyname, name, qtype, qclass, NULL, nons, nsec_ttl))
|
||||
{
|
||||
/* Empty DS without NSECS */
|
||||
if (qtype == T_DS)
|
||||
return STAT_BOGUS | DNSSEC_FAIL_NONSEC;
|
||||
|
||||
if (!STAT_ISEQUAL((rc = zone_status(name, qclass, keyname, now)), STAT_SECURE))
|
||||
{
|
||||
if (class)
|
||||
*class = qclass; /* Class for NEED_DS or NEED_KEY */
|
||||
return rc;
|
||||
}
|
||||
|
||||
return STAT_BOGUS | DNSSEC_FAIL_NONSEC; /* signed zone, no NSECs */
|
||||
}
|
||||
}
|
||||
|
||||
return secure;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+73
-24
@@ -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
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
static u32 packet_count;
|
||||
|
||||
/* https://wiki.wireshark.org/Development/LibpcapFileFormat */
|
||||
@@ -79,7 +81,9 @@ void dump_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst)
|
||||
/* port == -1 ->ICMPv6 */
|
||||
void dump_packet(int mask, void *packet, size_t len,
|
||||
union mysockaddr *src, union mysockaddr *dst, int port)
|
||||
{
|
||||
struct ip ip;
|
||||
struct ip6_hdr ip6;
|
||||
@@ -101,7 +105,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;
|
||||
@@ -115,10 +119,19 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
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);
|
||||
@@ -134,9 +147,8 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
/* 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
|
||||
@@ -147,9 +159,18 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -180,31 +201,59 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+61
-37
@@ -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
|
||||
@@ -264,44 +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)
|
||||
{
|
||||
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, 0);
|
||||
if (option_bool(OPT_STRIP_MAC))
|
||||
replace = 1;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -378,15 +396,29 @@ 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)
|
||||
/* 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)
|
||||
{
|
||||
/* 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);
|
||||
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, 0);
|
||||
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);
|
||||
}
|
||||
|
||||
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)
|
||||
@@ -493,16 +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;
|
||||
|
||||
if (option_bool(OPT_ADD_MAC))
|
||||
plen = add_mac(header, plen, limit, source, now, cacheable);
|
||||
|
||||
if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX))
|
||||
plen = add_dns_client(header, plen, limit, source, now, cacheable);
|
||||
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,
|
||||
@@ -511,11 +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);
|
||||
|
||||
if (option_bool(OPT_CLIENT_SUBNET))
|
||||
{
|
||||
plen = add_source_addr(header, plen, limit, source, cacheable);
|
||||
*check_subnet = 1;
|
||||
}
|
||||
|
||||
plen = add_source_addr(header, plen, limit, source, cacheable);
|
||||
|
||||
return plen;
|
||||
}
|
||||
|
||||
+206
-145
@@ -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
|
||||
@@ -20,6 +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);
|
||||
@@ -125,9 +128,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,
|
||||
@@ -138,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;
|
||||
@@ -189,7 +184,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;
|
||||
@@ -280,6 +275,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
|
||||
@@ -435,10 +439,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;
|
||||
@@ -519,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 */
|
||||
@@ -616,7 +617,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;
|
||||
@@ -643,7 +644,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;
|
||||
@@ -861,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
|
||||
}
|
||||
|
||||
@@ -870,106 +871,127 @@ 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;
|
||||
hash = hash_questions(header, nn, daemon->namebuff);
|
||||
unsigned int flags = STAT_ISEQUAL(status, STAT_NEED_KEY) ? FREC_DNSKEY_QUERY : FREC_DS_QUERY;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
#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);
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
return;
|
||||
free_rfds(&rfds); /* error unwind */
|
||||
}
|
||||
|
||||
blockdata_free(stash); /* don't leak this on failure. */
|
||||
}
|
||||
|
||||
/* sending DNSSEC query failed. */
|
||||
/* sending DNSSEC query failed or loop detected. */
|
||||
status = STAT_ABANDONED;
|
||||
}
|
||||
|
||||
|
||||
/* Validated original answer, all done. */
|
||||
if (!forward->dependent)
|
||||
return_reply(now, forward, header, plen, status);
|
||||
@@ -1047,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
|
||||
@@ -1226,7 +1248,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;
|
||||
@@ -1251,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))
|
||||
{
|
||||
@@ -1455,7 +1478,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;
|
||||
@@ -1577,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
|
||||
@@ -1667,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);
|
||||
@@ -1683,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)
|
||||
@@ -1739,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))
|
||||
@@ -1767,13 +1791,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 +1881,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;
|
||||
@@ -1923,8 +1950,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);
|
||||
|
||||
@@ -1958,7 +1985,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;
|
||||
@@ -2027,7 +2054,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;
|
||||
}
|
||||
}
|
||||
@@ -2213,7 +2241,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))
|
||||
@@ -2291,7 +2319,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 ************/
|
||||
@@ -2660,28 +2688,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,15 +2719,47 @@ 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;
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Send query packet again, if we can. */
|
||||
void resend_query()
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+19
-6
@@ -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
|
||||
@@ -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__)
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+3
-10
@@ -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
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
+36
-26
@@ -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
|
||||
@@ -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;
|
||||
@@ -1763,6 +1762,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 +1772,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 +1788,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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+80
-22
@@ -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
|
||||
@@ -181,6 +181,10 @@ 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
|
||||
#define LOPT_CONF_OPT 373
|
||||
#define LOPT_CONF_SCRIPT 374
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static const struct option opts[] =
|
||||
@@ -227,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' },
|
||||
@@ -318,7 +323,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 },
|
||||
@@ -467,6 +474,7 @@ static struct {
|
||||
{ LOPT_SCRIPTUSR, ARG_ONE, "<username>", 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, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
|
||||
{ LOPT_CONF_SCRIPT, ARG_DUP, "<path>", gettext_noop("Execute file and read configuration from stdin."), NULL },
|
||||
{ '8', ARG_ONE, "<facility>|<file>", 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, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
|
||||
@@ -505,7 +513,9 @@ static struct {
|
||||
{ LOPT_PXE_SERV, ARG_DUP, "<service>", 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, "<v4 pref>[,<v6 pref>]", 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, "<text>", 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 },
|
||||
@@ -1808,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;
|
||||
@@ -2535,13 +2556,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);
|
||||
@@ -2553,13 +2574,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;
|
||||
}
|
||||
@@ -4964,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)
|
||||
{
|
||||
@@ -5082,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
|
||||
@@ -5091,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)
|
||||
@@ -5111,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;
|
||||
@@ -5119,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)
|
||||
@@ -5139,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;
|
||||
@@ -5153,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. */
|
||||
@@ -5172,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;
|
||||
}
|
||||
|
||||
@@ -5313,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);
|
||||
}
|
||||
@@ -5544,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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+31
-11
@@ -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
|
||||
@@ -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,24 +191,36 @@ 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;
|
||||
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);
|
||||
|
||||
@@ -543,6 +559,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))));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+87
-72
@@ -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
|
||||
@@ -2100,98 +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;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
-4
@@ -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
|
||||
@@ -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);
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+25
-21
@@ -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 unsigned int flags, 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);
|
||||
@@ -115,8 +115,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);
|
||||
@@ -130,19 +130,19 @@ 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
else if(flags & F_AUTH)
|
||||
; // Ignored
|
||||
@@ -1619,7 +1619,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
|
||||
|
||||
@@ -1637,19 +1637,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,9 +85,9 @@ src/dnsmasq/forward.c
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user