Compare commits

...

9 Commits

Author SHA1 Message Date
Simon Kelley
c4b9bc63e0 Fix a problem in overload handling.
Sending the same query repeatedly to a dnsmasq instance which
doesn't get replies from upstream will eventually hit the
hard limit on frec_src structures and start gettin REFUSED
replies. This is OK, except that since the queries are no longer
being forwarded, an upstream server coming back doesn't reset the
situation. If there is any other traffic, frec allocation will
eventually delete the timed-out frec and get things moving again,
but that's not guaranteed.

To fix this we explicitly delete the frec once timed out in this case.

Thanks to Filip Jenicek for noticing and characterising this problem.
2022-09-09 12:53:49 +01:00
Simon Kelley
4447d48bb9 Add DHCPv4 option 108 "ipv6-only" to the options table. 2022-09-06 22:40:06 +01:00
Simon Kelley
04cc2ae1a6 Fix logic when a SERVFAIL reply is received after good replt for DNSSEC.
If we get a SERVFAIL or REFUSED answer to a DNSSEC query for which
we already have a good answer, just ignore it.
2022-09-06 18:31:59 +01:00
Simon Kelley
32588c755a Add source address to RA packet dumps. 2022-09-06 18:08:39 +01:00
Simon Kelley
84a6d07cdd Fix DHCPv6 relay to use a more sensble source address.
Tweak things so that packets relayed towards a server
have source address on the server-facing network, not the
client-facing network. Thanks to Luis Thomas for spotting this
and initial patch.
2022-09-06 15:40:42 +01:00
Simon Kelley
d6c69f6bdb Free sockets awaiting upstream DNS replies ASAP.
Once we have a good answer, close the socket so that the fd can
be reused during DNSSEC validation and we don't have to read and
discard more replies from other servers.
2022-09-06 15:35:54 +01:00
Simon Kelley
ce372917fe Tweak packet dump code to make port numbers more accurate.
Also add query-ids with log-queries=extra.
2022-09-05 18:04:35 +01:00
Simon Kelley
09d741f58a Simplify realloc use in poll.c 2022-08-11 17:04:54 +01:00
Petr Menšík
0666ae3d27 Introduce whine_realloc
Move few patters with whine_malloc, if (successful) copy+free, to a new
whine_realloc. It should do the same thing, but with a help from OS it
can avoid unnecessary copy and free if allocation of more data after
current data is possible.

Added few setting remanining space to 0, because realloc does not use
calloc like whine_malloc does. There is no advantage of zeroing what we
will immediately overwrite. Zero only remaining space.
2022-08-11 16:56:58 +01:00
15 changed files with 181 additions and 133 deletions

View File

@@ -79,6 +79,11 @@ version 2.87
This would return <ip> for queries in some.domain, rather than
forwarding the query via the default server.
Tweak DHCPv6 relay code so that packets relayed towards a server
have source address on the server-facing network, not the
client facing network. Thanks to Luis Thomas for spotting this
and initial patch.
version 2.86
Handle DHCPREBIND requests in the DHCPv6 server code.

View File

@@ -1676,10 +1676,8 @@ int cache_make_stat(struct txt_record *t)
{
/* expand buffer if necessary */
newlen = bytes_needed + 1 + bufflen - bytes_avail;
if (!(new = whine_malloc(newlen)))
if (!(new = whine_realloc(buff, newlen)))
return 0;
memcpy(new, buff, bufflen);
free(buff);
p = new + (p - buff);
lenp = p - 1;
buff = new;

View File

@@ -685,6 +685,7 @@ static const struct opttab_t {
{ "client-machine-id", 97, 0 },
{ "posix-timezone", 100, OT_NAME }, /* RFC 4833, Sec. 2 */
{ "tzdb-timezone", 101, OT_NAME }, /* RFC 4833, Sec. 2 */
{ "ipv6-only", 108, 4 | OT_DEC }, /* RFC 8925 */
{ "subnet-select", 118, OT_INTERNAL },
{ "domain-search", 119, OT_RFC1035_NAME },
{ "sip-server", 120, 0 },

View File

@@ -177,8 +177,7 @@ void dhcp_packet(time_t now, int pxe_fd)
return;
#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);
dump_packet_udp(DUMP_DHCP, (void *)daemon->dhcp_packet.iov_base, sz, (union mysockaddr *)&dest, NULL, fd);
#endif
#if defined (HAVE_LINUX_NETWORK)
@@ -464,8 +463,8 @@ void dhcp_packet(time_t now, int pxe_fd)
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);
dump_packet_udp(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
(union mysockaddr *)&dest, fd);
#endif
send_via_bpf(mess, iov.iov_len, iface_addr, &ifr);
@@ -478,8 +477,8 @@ void dhcp_packet(time_t now, int pxe_fd)
#endif
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
(union mysockaddr *)&dest, daemon->dhcp_server_port);
dump_packet_udp(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
(union mysockaddr *)&dest, fd);
#endif
while(retry_send(sendmsg(fd, &msg, 0)));
@@ -1147,8 +1146,8 @@ static int relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz)
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);
dump_packet_udp(DUMP_DHCP, (void *)mess, sz, &fromsock, &to, -1);
}
#endif

View File

@@ -119,8 +119,8 @@ void dhcp6_packet(time_t now)
return;
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz,
(union mysockaddr *)&from, NULL, DHCPV6_SERVER_PORT);
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz,
(union mysockaddr *)&from, NULL, daemon->dhcp6fd);
#endif
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
@@ -142,8 +142,8 @@ 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);
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL,
(union mysockaddr *)&from, daemon->dhcp6fd);
#endif
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
@@ -254,8 +254,8 @@ void dhcp6_packet(time_t now)
from.sin6_port = htons(port);
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1),
NULL, (union mysockaddr *)&from, DHCPV6_SERVER_PORT);
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1),
NULL, (union mysockaddr *)&from, daemon->dhcp6fd);
#endif
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,

View File

@@ -1396,6 +1396,7 @@ void *safe_malloc(size_t size);
void safe_strncpy(char *dest, const char *src, size_t size);
void safe_pipe(int *fd, int read_noblock);
void *whine_malloc(size_t size);
void *whine_realloc(void *ptr, size_t size);
int sa_len(union mysockaddr *addr);
int sockaddr_isequal(const union mysockaddr *s1, const union mysockaddr *s2);
int hostname_order(const char *a, const char *b);
@@ -1802,8 +1803,10 @@ 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, int port);
void dump_packet_udp(int mask, void *packet, size_t len, union mysockaddr *src,
union mysockaddr *dst, int fd);
void dump_packet_icmp(int mask, void *packet, size_t len, union mysockaddr *src,
union mysockaddr *dst);
#endif
/* domain-match.c */

View File

@@ -21,6 +21,8 @@
#include <netinet/icmp6.h>
static u32 packet_count;
static void do_dump_packet(int mask, void *packet, size_t len,
union mysockaddr *src, union mysockaddr *dst, int port, int proto);
/* https://wiki.wireshark.org/Development/LibpcapFileFormat */
struct pcap_hdr_s {
@@ -81,9 +83,45 @@ void dump_init(void)
}
}
/* port == -1 ->ICMPv6 */
void dump_packet(int mask, void *packet, size_t len,
union mysockaddr *src, union mysockaddr *dst, int port)
void dump_packet_udp(int mask, void *packet, size_t len,
union mysockaddr *src, union mysockaddr *dst, int fd)
{
union mysockaddr fd_addr;
socklen_t addr_len = sizeof(fd_addr);
if (daemon->dumpfd != -1 && (mask & daemon->dump_mask))
{
/* if fd is negative it carries a port number (negated)
which we use as a source or destination when not otherwise
specified so wireshark can ID the packet.
If both src and dst are specified, set this to -1 to avoid
a spurious getsockname() call. */
int port = (fd < 0) ? -fd : -1;
/* fd >= 0 is a file descriptor and the address of that file descriptor is used
in place of a NULL src or dst. */
if (fd >= 0 && getsockname(fd, (struct sockaddr *)&fd_addr, &addr_len) != -1)
{
if (!src)
src = &fd_addr;
if (!dst)
dst = &fd_addr;
}
do_dump_packet(mask, packet, len, src, dst, port, IPPROTO_UDP);
}
}
void dump_packet_icmp(int mask, void *packet, size_t len,
union mysockaddr *src, union mysockaddr *dst)
{
if (daemon->dumpfd != -1 && (mask & daemon->dump_mask))
do_dump_packet(mask, packet, len, src, dst, -1, IPPROTO_ICMP);
}
static void do_dump_packet(int mask, void *packet, size_t len,
union mysockaddr *src, union mysockaddr *dst, int port, int proto)
{
struct ip ip;
struct ip6_hdr ip6;
@@ -100,13 +138,14 @@ void dump_packet(int mask, void *packet, size_t len,
void *iphdr;
size_t ipsz;
int rc;
/* if port != -1 it carries a port number
which we use as a source or destination when not otherwise
specified so wireshark can ID the packet.
If both src and dst are specified, set this to -1 to avoid
a spurious getsockname() call. */
udp.uh_sport = udp.uh_dport = htons(port < 0 ? 0 : port);
if (daemon->dumpfd == -1 || !(mask & daemon->dump_mask))
return;
/* So wireshark can Id the packet. */
udp.uh_sport = udp.uh_dport = htons(port);
if (src)
family = src->sa.sa_family;
else
@@ -121,15 +160,12 @@ void dump_packet(int mask, void *packet, size_t len,
ip6.ip6_vfc = 6 << 4;
ip6.ip6_hops = 64;
if (port == -1)
{
ip6.ip6_plen = htons(len);
ip6.ip6_nxt = IPPROTO_ICMPV6;
}
if ((ip6.ip6_nxt = proto) == IPPROTO_UDP)
ip6.ip6_plen = htons(sizeof(struct udphdr) + len);
else
{
ip6.ip6_plen = htons(sizeof(struct udphdr) + len);
ip6.ip6_nxt = IPPROTO_UDP;
proto = ip6.ip6_nxt = IPPROTO_ICMPV6;
ip6.ip6_plen = htons(len);
}
if (src)
@@ -161,15 +197,12 @@ void dump_packet(int mask, void *packet, size_t len,
ip.ip_hl = sizeof(struct ip) / 4;
ip.ip_ttl = IPDEFTTL;
if (port == -1)
{
ip.ip_len = htons(sizeof(struct ip) + len);
ip.ip_p = IPPROTO_ICMP;
}
if ((ip.ip_p = proto) == IPPROTO_UDP)
ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len);
else
{
ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len);
ip.ip_p = IPPROTO_UDP;
ip.ip_len = htons(sizeof(struct ip) + len);
proto = ip.ip_p = IPPROTO_ICMP;
}
if (src)
@@ -191,7 +224,7 @@ void dump_packet(int mask, void *packet, size_t len,
sum = (sum & 0xffff) + (sum >> 16);
ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
/* start UDP checksum */
/* start UDP/ICMP checksum */
sum = ip.ip_src.s_addr & 0xffff;
sum += (ip.ip_src.s_addr >> 16) & 0xffff;
sum += ip.ip_dst.s_addr & 0xffff;
@@ -201,25 +234,7 @@ void dump_packet(int mask, void *packet, size_t len,
if (len & 1)
((unsigned char *)packet)[len] = 0; /* for checksum, in case length is odd. */
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
if (proto == IPPROTO_UDP)
{
/* Add Remaining part of the pseudoheader. Note that though the
IPv6 pseudoheader is very different to the IPv4 one, the
@@ -241,7 +256,25 @@ void dump_packet(int mask, void *packet, size_t len,
pcap_header.incl_len = pcap_header.orig_len = ipsz + sizeof(udp) + len;
}
else
{
/* ICMP - ICMPv6 packet is a superset of ICMP */
struct icmp6_hdr *icmp = packet;
/* See comment in UDP code above. */
sum += htons(proto);
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;
}
rc = gettimeofday(&time, NULL);
pcap_header.ts_sec = time.tv_sec;
pcap_header.ts_usec = time.tv_usec;
@@ -249,9 +282,11 @@ void dump_packet(int mask, void *packet, size_t len,
if (rc == -1 ||
!read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 0) ||
!read_write(daemon->dumpfd, iphdr, ipsz, 0) ||
(port != -1 && !read_write(daemon->dumpfd, (void *)&udp, sizeof(udp), 0)) ||
(proto == IPPROTO_UDP && !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 if (option_bool(OPT_EXTRALOG))
my_syslog(LOG_INFO, _("%u dumping packet %u mask 0x%04x"), daemon->log_display_id, ++packet_count, mask);
else
my_syslog(LOG_INFO, _("dumping packet %u mask 0x%04x"), ++packet_count, mask);

View File

@@ -244,6 +244,14 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (!daemon->free_frec_src)
{
query_full(now, NULL);
/* This is tricky; if we're blasted with the same query
over and over, we'll end up taking this path each time
and never resetting until the frec gets deleted by
aging followed by the receipt of a different query. This
is a bit of a DoS vuln. Avoid by explicitly deleting the
frec once it expires. */
if (difftime(now, forward->time) >= TIMEOUT)
free_frec(forward);
goto reply;
}
@@ -510,7 +518,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, daemon->port);
dump_packet_udp(DUMP_UP_QUERY, (void *)header, plen, NULL, &srv->addr, fd);
#endif
/* Keep info in case we want to re-send this packet */
@@ -839,8 +847,8 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
NULL, NULL, NULL);
#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, daemon->port);
dump_packet_udp((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_BOGUS : DUMP_BOGUS,
header, (size_t)plen, &forward->sentto->addr, NULL, -daemon->port);
#endif
}
@@ -950,13 +958,13 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
set_outgoing_mark(orig, fd);
#endif
server_send(server, fd, header, nn, 0);
server->queries++;
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)nn, NULL, &server->addr, daemon->port);
dump_packet_udp(DUMP_SEC_QUERY, (void *)header, (size_t)nn, NULL, &server->addr, fd);
#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;
}
@@ -1045,16 +1053,16 @@ void reply_query(int fd, time_t now)
if (difftime(now, server->pktsz_reduced) > UDP_TEST_TIME)
server->edns_pktsz = daemon->edns_pktsz;
#ifdef HAVE_DUMPFILE
dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY,
(void *)header, n, &serveraddr, NULL, daemon->port);
#endif
/* log_query gets called indirectly all over the place, so
pass these in global variables - sorry. */
daemon->log_display_id = forward->frec_src.log_id;
daemon->log_source_addr = &forward->frec_src.source;
#ifdef HAVE_DUMPFILE
dump_packet_udp((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY,
(void *)header, n, &serveraddr, NULL, fd);
#endif
if (daemon->ignore_addr && RCODE(header) == NOERROR &&
check_for_ignored_address(header, n))
return;
@@ -1073,12 +1081,15 @@ void reply_query(int fd, time_t now)
size_t nn = 0;
#ifdef HAVE_DNSSEC
/* DNSSEC queries have a copy of the original query stashed.
The query MAY have got a good answer, and be awaiting
/* The query MAY have got a good answer, and be awaiting
the results of further queries, in which case
The Stash contains something else and we don't need to retry anyway. */
if ((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) && !forward->blocking_query)
if (forward->blocking_query)
return;
if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
{
/* DNSSEC queries have a copy of the original query stashed. */
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
nn = forward->stash_len;
udp_size = daemon->edns_pktsz;
@@ -1144,6 +1155,13 @@ void reply_query(int fd, time_t now)
}
forward->sentto = server;
/* We have a good answer, and will now validate it or return it.
It may be some time before this the validation completes, but we don't need
any more answers, so close the socket(s) on which we were expecting
answers, to conserve file descriptors, and to save work reading and
discarding answers for other upstreams. */
free_rfds(&forward->rfds);
#ifdef HAVE_DNSSEC
if ((forward->sentto->flags & SERV_DO_DNSSEC) &&
@@ -1251,7 +1269,7 @@ 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, daemon->port);
dump_packet_udp(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &src->source, src->fd);
#endif
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
@@ -1566,7 +1584,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, daemon->port);
dump_packet_udp(DUMP_QUERY, daemon->packet, (size_t)n, &source_addr, NULL, listen->fd);
#endif
#ifdef HAVE_CONNTRACK
@@ -1653,7 +1671,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, daemon->port);
dump_packet_udp(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, listen->fd);
#endif
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
(char *)header, m, &source_addr, &dst_addr, if_index);
@@ -1669,7 +1687,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, daemon->port);
dump_packet_udp(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, listen->fd);
#endif
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
if (local_auth)
@@ -1695,7 +1713,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, daemon->port);
dump_packet_udp(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, listen->fd);
#endif
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask))

View File

@@ -1180,17 +1180,11 @@ void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data, unsigned
if ((lease->extradata_size - lease->extradata_len) < (len + 1))
{
size_t newsz = lease->extradata_len + len + 100;
unsigned char *new = whine_malloc(newsz);
unsigned char *new = whine_realloc(lease->extradata, newsz);
if (!new)
return;
if (lease->extradata)
{
memcpy(new, lease->extradata, lease->extradata_len);
free(lease->extradata);
}
lease->extradata = new;
lease->extradata_size = newsz;
}

View File

@@ -96,28 +96,21 @@ void poll_listen(int fd, short event)
pollfds[i].events |= event;
else
{
if (arrsize != nfds)
memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
else
if (arrsize == nfds)
{
/* Array too small, extend. */
struct pollfd *new;
arrsize = (arrsize == 0) ? 64 : arrsize * 2;
if (!(new = whine_malloc(arrsize * sizeof(struct pollfd))))
if (!(new = whine_realloc(pollfds, arrsize * sizeof(struct pollfd))))
return;
if (pollfds)
{
memcpy(new, pollfds, i * sizeof(struct pollfd));
memcpy(&new[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
free(pollfds);
}
pollfds = new;
}
memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
pollfds[i].fd = fd;
pollfds[i].events = event;
nfds++;

View File

@@ -203,7 +203,7 @@ void icmp6_packet(time_t now)
int opt_sz;
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_RA, (void *)packet, sz, (union mysockaddr *)&from, NULL, -1);
dump_packet_icmp(DUMP_RA, (void *)packet, sz, (union mysockaddr *)&from, NULL);
#endif
/* look for link-layer address option for logging */
@@ -560,7 +560,13 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
}
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_RA, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL, (union mysockaddr *)&addr, -1);
{
struct sockaddr_in6 src;
src.sin6_family = AF_INET6;
src.sin6_addr = parm.link_local;
dump_packet_icmp(DUMP_RA, (void *)daemon->outpacket.iov_base, save_counter(-1), (union mysockaddr *)&src, (union mysockaddr *)&addr);
}
#endif
while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,

View File

@@ -2181,10 +2181,7 @@ int relay_upstream6(int iface_index, ssize_t sz,
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;
@@ -2206,18 +2203,11 @@ int relay_upstream6(int iface_index, ssize_t sz,
}
#ifdef HAVE_DUMPFILE
{
union mysockaddr fromsock;
fromsock.in6.sin6_port = htons(DHCPV6_SERVER_PORT);
fromsock.in6.sin6_addr = from.addr6;
fromsock.sa.sa_family = AF_INET6;
fromsock.in6.sin6_flowinfo = 0;
fromsock.in6.sin6_scope_id = 0;
dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), &fromsock, &to, 0);
}
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL, &to, daemon->dhcp6fd);
#endif
send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(-1), &to, &from, 0);
while (retry_send(sendto(daemon->dhcp6fd, (void *)daemon->outpacket.iov_base, save_counter(-1),
0, (struct sockaddr *)&to, sa_len(&to))));
if (option_bool(OPT_LOG_OPTS))
{

View File

@@ -159,7 +159,7 @@ static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, i
/* mode may be remove EDNS0 or DNSSEC RRs or remove A or AAAA from answer section. */
size_t rrfilter(struct dns_header *header, size_t plen, int mode)
{
static unsigned char **rrs;
static unsigned char **rrs = NULL;
static int rr_sz = 0;
unsigned char *p = (unsigned char *)(header+1);
@@ -339,15 +339,11 @@ int expand_workspace(unsigned char ***wkspc, int *szp, int new)
return 0;
new += 5;
if (!(p = whine_malloc(new * sizeof(unsigned char *))))
return 0;
if (old != 0 && *wkspc)
{
memcpy(p, *wkspc, old * sizeof(unsigned char *));
free(*wkspc);
}
if (!(p = whine_realloc(*wkspc, new * sizeof(unsigned char *))))
return 0;
memset(p+old, 0, new-old);
*wkspc = p;
*szp = new;

View File

@@ -97,7 +97,7 @@ void tftp_request(struct listener *listen, time_t now)
return;
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_TFTP, (void *)packet, len, (union mysockaddr *)&peer, NULL, TFTP_PORT);
dump_packet_udp(DUMP_TFTP, (void *)packet, len, (union mysockaddr *)&peer, NULL, listen->tftpfd);
#endif
/* Can always get recvd interface for IPv6 */
@@ -488,7 +488,7 @@ 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);
dump_packet_udp(DUMP_TFTP, (void *)packet, len, NULL, (union mysockaddr *)&peer, transfer->sockfd);
#endif
if (is_err)
@@ -610,7 +610,7 @@ void check_tftp_listeners(time_t now)
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);
dump_packet_udp(DUMP_TFTP, (void *)daemon->packet, len, NULL, (union mysockaddr *)&peer, transfer->sockfd);
#endif
}
}
@@ -650,7 +650,7 @@ void check_tftp_listeners(time_t now)
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);
dump_packet_udp(DUMP_TFTP, (void *)daemon->packet, len, NULL, (union mysockaddr *)&transfer->peer, transfer->sockfd);
#endif
}

View File

@@ -336,6 +336,16 @@ void *whine_malloc(size_t size)
return ret;
}
void *whine_realloc(void *ptr, size_t size)
{
void *ret = realloc(ptr, size);
if (!ret)
my_syslog(LOG_ERR, _("failed to reallocate %d bytes"), (int) size);
return ret;
}
int sockaddr_isequal(const union mysockaddr *s1, const union mysockaddr *s2)
{
if (s1->sa.sa_family == s2->sa.sa_family)