From c6d4c33d612c26f7d7518bef301a448a143b0a58 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Mon, 24 Jan 2022 15:19:00 +0000 Subject: [PATCH 1/8] Bump copyright to 2022. --- Makefile | 2 +- src/arp.c | 2 +- src/auth.c | 2 +- src/blockdata.c | 2 +- src/bpf.c | 2 +- src/cache.c | 2 +- src/config.h | 2 +- src/conntrack.c | 2 +- src/crypto.c | 2 +- src/dbus.c | 2 +- src/dhcp-common.c | 2 +- src/dhcp-protocol.h | 2 +- src/dhcp.c | 2 +- src/dhcp6-protocol.h | 2 +- src/dhcp6.c | 2 +- src/dns-protocol.h | 2 +- src/dnsmasq.c | 2 +- src/dnsmasq.h | 4 ++-- src/domain-match.c | 2 +- src/domain.c | 2 +- src/dump.c | 2 +- src/edns0.c | 2 +- src/forward.c | 2 +- src/helper.c | 2 +- src/inotify.c | 2 +- src/ip6addr.h | 2 +- src/lease.c | 2 +- src/log.c | 2 +- src/loop.c | 2 +- src/metrics.c | 2 +- src/metrics.h | 2 +- src/netlink.c | 2 +- src/network.c | 2 +- src/nftset.c | 2 +- src/option.c | 2 +- src/outpacket.c | 2 +- src/pattern.c | 2 +- src/poll.c | 2 +- src/radv-protocol.h | 2 +- src/radv.c | 2 +- src/rfc1035.c | 2 +- src/rfc2131.c | 2 +- src/rfc3315.c | 2 +- src/rrfilter.c | 2 +- src/slaac.c | 2 +- src/tftp.c | 2 +- src/ubus.c | 2 +- src/util.c | 2 +- 48 files changed, 49 insertions(+), 49 deletions(-) diff --git a/Makefile b/Makefile index d06ccc1..48e8d3b 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# dnsmasq is Copyright (c) 2000-2021 Simon Kelley +# dnsmasq is Copyright (c) 2000-2022 Simon Kelley # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/src/arp.c b/src/arp.c index 1e4aad2..eda165f 100644 --- a/src/arp.c +++ b/src/arp.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/auth.c b/src/auth.c index aa2403b..7088d67 100644 --- a/src/auth.c +++ b/src/auth.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/blockdata.c b/src/blockdata.c index 0986285..4c26155 100644 --- a/src/blockdata.c +++ b/src/blockdata.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/bpf.c b/src/bpf.c index 15c42fc..4dd97c0 100644 --- a/src/bpf.c +++ b/src/bpf.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/cache.c b/src/cache.c index 1ee19e0..a99d70d 100644 --- a/src/cache.c +++ b/src/cache.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/config.h b/src/config.h index 227fb1f..cd37900 100644 --- a/src/config.h +++ b/src/config.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/conntrack.c b/src/conntrack.c index 745a2a3..fe48f2b 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/crypto.c b/src/crypto.c index 4009569..060e27f 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dbus.c b/src/dbus.c index 4eae789..0c55ea5 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dhcp-common.c b/src/dhcp-common.c index 291e82b..611b5cb 100644 --- a/src/dhcp-common.c +++ b/src/dhcp-common.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dhcp-protocol.h b/src/dhcp-protocol.h index 6ff3ffa..75c9cd3 100644 --- a/src/dhcp-protocol.h +++ b/src/dhcp-protocol.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dhcp.c b/src/dhcp.c index 2c1272f..cdea79e 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dhcp6-protocol.h b/src/dhcp6-protocol.h index f1d0991..332d536 100644 --- a/src/dhcp6-protocol.h +++ b/src/dhcp6-protocol.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dhcp6.c b/src/dhcp6.c index c061879..9831255 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dns-protocol.h b/src/dns-protocol.h index 496a4bb..8558c33 100644 --- a/src/dns-protocol.h +++ b/src/dns-protocol.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq.c b/src/dnsmasq.c index 0de8d18..d112a7e 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dnsmasq.h b/src/dnsmasq.h index e77e1eb..f37d7b1 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,7 +14,7 @@ along with this program. If not, see . */ -#define COPYRIGHT "Copyright (c) 2000-2021 Simon Kelley" +#define COPYRIGHT "Copyright (c) 2000-2022 Simon Kelley" /* We do defines that influence behavior of stdio.h, so complain if included too early. */ diff --git a/src/domain-match.c b/src/domain-match.c index 4e01092..3ec49b8 100644 --- a/src/domain-match.c +++ b/src/domain-match.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/domain.c b/src/domain.c index 91e0f22..7166433 100644 --- a/src/domain.c +++ b/src/domain.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/dump.c b/src/dump.c index c131953..14365d8 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/edns0.c b/src/edns0.c index 7591b78..c498eb1 100644 --- a/src/edns0.c +++ b/src/edns0.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/forward.c b/src/forward.c index 5d135b4..d9633f5 100644 --- a/src/forward.c +++ b/src/forward.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/helper.c b/src/helper.c index d7c7dbd..39e4b89 100644 --- a/src/helper.c +++ b/src/helper.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/inotify.c b/src/inotify.c index 3a8e375..5687e37 100644 --- a/src/inotify.c +++ b/src/inotify.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/ip6addr.h b/src/ip6addr.h index 6388c7d..977e684 100644 --- a/src/ip6addr.h +++ b/src/ip6addr.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/lease.c b/src/lease.c index 1a9f1c6..81477d5 100644 --- a/src/lease.c +++ b/src/lease.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/log.c b/src/log.c index bcd6e52..0a64026 100644 --- a/src/log.c +++ b/src/log.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/loop.c b/src/loop.c index 01f0c28..cd4855e 100644 --- a/src/loop.c +++ b/src/loop.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/metrics.c b/src/metrics.c index fac5b00..6873529 100644 --- a/src/metrics.c +++ b/src/metrics.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/metrics.h b/src/metrics.h index cecf8c8..df72ec6 100644 --- a/src/metrics.h +++ b/src/metrics.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/netlink.c b/src/netlink.c index 7840ef9..ae1426c 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/network.c b/src/network.c index 3c1c176..7cd3371 100644 --- a/src/network.c +++ b/src/network.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/nftset.c b/src/nftset.c index 5373a1c..4e152dc 100644 --- a/src/nftset.c +++ b/src/nftset.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/option.c b/src/option.c index 6942432..7133a30 100644 --- a/src/option.c +++ b/src/option.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/outpacket.c b/src/outpacket.c index da6f73c..abb3a3a 100644 --- a/src/outpacket.c +++ b/src/outpacket.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/pattern.c b/src/pattern.c index 928d259..e56e495 100644 --- a/src/pattern.c +++ b/src/pattern.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/poll.c b/src/poll.c index f414690..29b33a0 100644 --- a/src/poll.c +++ b/src/poll.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/radv-protocol.h b/src/radv-protocol.h index 8314e8a..7fb6bd8 100644 --- a/src/radv-protocol.h +++ b/src/radv-protocol.h @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/radv.c b/src/radv.c index 6d6fa32..2b6d944 100644 --- a/src/radv.c +++ b/src/radv.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/rfc1035.c b/src/rfc1035.c index 124a4f2..34eaf0a 100644 --- a/src/rfc1035.c +++ b/src/rfc1035.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/rfc2131.c b/src/rfc2131.c index a99bb89..ecda2d3 100644 --- a/src/rfc2131.c +++ b/src/rfc2131.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/rfc3315.c b/src/rfc3315.c index 236df47..a286395 100644 --- a/src/rfc3315.c +++ b/src/rfc3315.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/rrfilter.c b/src/rrfilter.c index ef276c0..f02f5a5 100644 --- a/src/rrfilter.c +++ b/src/rrfilter.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/slaac.c b/src/slaac.c index 9b10063..7d3fce4 100644 --- a/src/slaac.c +++ b/src/slaac.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/tftp.c b/src/tftp.c index e8474d9..b82d89d 100644 --- a/src/tftp.c +++ b/src/tftp.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/ubus.c b/src/ubus.c index 0c502ad..09071cf 100644 --- a/src/ubus.c +++ b/src/ubus.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/src/util.c b/src/util.c index f2adac1..ae514d2 100644 --- a/src/util.c +++ b/src/util.c @@ -1,4 +1,4 @@ -/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley +/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From fc664d114d6e11ced4912b746f18d543f662066b Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Sat, 29 Jan 2022 15:55:04 +0000 Subject: [PATCH 2/8] Extend packet-dump system to DHCP and TFTP. --- man/dnsmasq.8 | 2 +- src/dhcp.c | 35 ++++++++++++++++++++++++++++++++--- src/dhcp6.c | 33 ++++++++++++++++++++++++--------- src/dnsmasq.h | 22 +++++++++++++--------- src/dump.c | 5 +++-- src/forward.c | 40 +++++++++++++++------------------------- src/rfc3315.c | 12 ++++++++++++ src/tftp.c | 23 ++++++++++++++++++++--- 8 files changed, 120 insertions(+), 52 deletions(-) diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index 0d53474..398c2c6 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -734,7 +734,7 @@ Specify the location of a pcap-format file which dnsmasq uses to dump copies of .TP .B --dumpmask= Specify which types of packets should be added to the dumpfile. The argument should be the OR of the bitmasks for each type of packet to be dumped: it can be specified in hex by preceding the number with 0x in the normal way. Each time a packet is written to the dumpfile, dnsmasq logs the packet sequence and the mask -representing its type. The current types are: 0x0001 - DNS queries from clients 0x0002 DNS replies to clients 0x0004 - DNS queries to upstream 0x0008 - DNS replies from upstream 0x0010 - queries send upstream for DNSSEC validation 0x0020 - replies to queries for DNSSEC validation 0x0040 - replies to client queries which fail DNSSEC validation 0x0080 replies to queries for DNSSEC validation which fail validation. +representing its type. The current types are: 0x0001 - DNS queries from clients, 0x0002 DNS replies to clients, 0x0004 - DNS queries to upstream, 0x0008 - DNS replies from upstream, 0x0010 - queries send upstream for DNSSEC validation, 0x0020 - replies to queries for DNSSEC validation, 0x0040 - replies to client queries which fail DNSSEC validation, 0x0080 replies to queries for DNSSEC validation which fail validation, 0x1000 - DHCPv4, 0x2000 - DHCPv6, 0x8000 - TFTP. .TP .B --add-mac[=base64|text] Add the MAC address of the requestor to DNS queries which are diff --git a/src/dhcp.c b/src/dhcp.c index cdea79e..de766c1 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -177,11 +177,16 @@ void dhcp_packet(time_t now, int pxe_fd) if ((sz = recv_dhcp_packet(fd, &msg)) == -1 || (sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))) return; - - #if defined (HAVE_LINUX_NETWORK) + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_DHCP, (void *)daemon->dhcp_packet.iov_base, sz, (union mysockaddr *)&dest, NULL, + pxe_fd ? PXE_PORT : daemon->dhcp_server_port); +#endif + +#if defined (HAVE_LINUX_NETWORK) if (ioctl(fd, SIOCGSTAMP, &tv) == 0) recvtime = tv.tv_sec; - + if (msg.msg_controllen >= sizeof(struct cmsghdr)) for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO) @@ -455,6 +460,14 @@ void dhcp_packet(time_t now, int pxe_fd) #elif defined(HAVE_BSD_NETWORK) else { +#ifdef HAVE_DUMPFILE + dest.sin_addr.s_addr = (ntohs(mess->flags) & 0x8000) ? INADDR_BROADCAST : mess->yiaddr; + dest.sin_port = htons(daemon->dhcp_client_port); + + dump_packet(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL, + (union mysockaddr *)&dest, daemon->dhcp_server_port); +#endif + send_via_bpf(mess, iov.iov_len, iface_addr, &ifr); return; } @@ -463,6 +476,11 @@ void dhcp_packet(time_t now, int pxe_fd) #ifdef HAVE_SOLARIS_NETWORK setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index)); #endif + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL, + (union mysockaddr *)&dest, daemon->dhcp_server_port); +#endif while(retry_send(sendmsg(fd, &msg, 0))); @@ -1114,6 +1132,17 @@ static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, to.in.sin_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; } +#ifdef HAVE_DUMPFILE + { + union mysockaddr fromsock; + fromsock.in.sin_port = htons(daemon->dhcp_server_port); + fromsock.in.sin_addr = from.addr4; + fromsock.sa.sa_family = AF_INET; + + dump_packet(DUMP_DHCP, (void *)mess, sz, &fromsock, &to, 0); + } +#endif + send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0); if (option_bool(OPT_LOG_OPTS)) diff --git a/src/dhcp6.c b/src/dhcp6.c index 9831255..a343740 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -119,6 +119,11 @@ void dhcp6_packet(time_t now) if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1) return; +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz, + (union mysockaddr *)&from, NULL, DHCPV6_SERVER_PORT); +#endif + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo) { @@ -137,6 +142,11 @@ void dhcp6_packet(time_t now) if (relay_reply6(&from, sz, ifr.ifr_name)) { +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL, + (union mysockaddr *)&from, DHCPV6_SERVER_PORT); +#endif + while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, save_counter(-1), 0, (struct sockaddr *)&from, sizeof(from)))); @@ -144,7 +154,7 @@ void dhcp6_packet(time_t now) else { struct dhcp_bridge *bridge, *alias; - + for (tmp = daemon->if_except; tmp; tmp = tmp->next) if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name)) return; @@ -161,7 +171,7 @@ void dhcp6_packet(time_t now) memset(&parm.fallback, 0, IN6ADDRSZ); memset(&parm.ll_addr, 0, IN6ADDRSZ); memset(&parm.ula_addr, 0, IN6ADDRSZ); - + /* If the interface on which the DHCPv6 request was received is an alias of some other interface (as specified by the --bridge-interface option), change parm.ind so that we look @@ -199,13 +209,13 @@ void dhcp6_packet(time_t now) context->current = context; memset(&context->local6, 0, IN6ADDRSZ); } - + for (relay = daemon->relay6; relay; relay = relay->next) relay->current = relay; if (!iface_enumerate(AF_INET6, &parm, complete_context6)) return; - + if (daemon->if_names || daemon->if_addrs) { @@ -233,7 +243,7 @@ void dhcp6_packet(time_t now) /* May have configured relay, but not DHCP server */ if (!daemon->doing_dhcp6) return; - + lease_prune(NULL, now); /* lose any expired leases */ port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback, @@ -246,11 +256,16 @@ void dhcp6_packet(time_t now) if (port != 0) { from.sin6_port = htons(port); - while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, - save_counter(-1), 0, (struct sockaddr *)&from, - sizeof(from)))); + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), + NULL, (union mysockaddr *)&from, DHCPV6_SERVER_PORT); +#endif + + while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, + save_counter(-1), 0, (struct sockaddr *)&from, sizeof(from)))); } - + /* These need to be called _after_ we send DHCPv6 packet, since lease_update_file() may trigger sending an RA packet, which overwrites our buffer. */ lease_update_file(now); diff --git a/src/dnsmasq.h b/src/dnsmasq.h index f37d7b1..a921f7d 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -690,14 +690,17 @@ struct hostsfile { }; /* packet-dump flags */ -#define DUMP_QUERY 0x0001 -#define DUMP_REPLY 0x0002 -#define DUMP_UP_QUERY 0x0004 -#define DUMP_UP_REPLY 0x0008 -#define DUMP_SEC_QUERY 0x0010 -#define DUMP_SEC_REPLY 0x0020 -#define DUMP_BOGUS 0x0040 -#define DUMP_SEC_BOGUS 0x0080 +#define DUMP_QUERY 0x0001 +#define DUMP_REPLY 0x0002 +#define DUMP_UP_QUERY 0x0004 +#define DUMP_UP_REPLY 0x0008 +#define DUMP_SEC_QUERY 0x0010 +#define DUMP_SEC_REPLY 0x0020 +#define DUMP_BOGUS 0x0040 +#define DUMP_SEC_BOGUS 0x0080 +#define DUMP_DHCP 0x1000 +#define DUMP_DHCPV6 0x2000 +#define DUMP_TFTP 0x8000 /* DNSSEC status values. */ #define STAT_SECURE 0x10000 @@ -1794,7 +1797,8 @@ int do_arp_script_run(void); /* dump.c */ #ifdef HAVE_DUMPFILE void dump_init(void); -void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst); +void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, + union mysockaddr *dst, unsigned short port); #endif /* domain-match.c */ diff --git a/src/dump.c b/src/dump.c index 14365d8..4aae008 100644 --- a/src/dump.c +++ b/src/dump.c @@ -79,7 +79,8 @@ void dump_init(void) } } -void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst) +void dump_packet(int mask, void *packet, size_t len, + union mysockaddr *src, union mysockaddr *dst, unsigned short port) { struct ip ip; struct ip6_hdr ip6; @@ -101,7 +102,7 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio return; /* So wireshark can Id the packet. */ - udp.uh_sport = udp.uh_dport = htons(NAMESERVER_PORT); + udp.uh_sport = udp.uh_dport = htons(port); if (src) family = src->sa.sa_family; diff --git a/src/forward.c b/src/forward.c index d9633f5..c17541b 100644 --- a/src/forward.c +++ b/src/forward.c @@ -146,20 +146,6 @@ static void server_send(struct server *server, int fd, sa_len(&server->addr)))); } -#ifdef HAVE_DNSSEC -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) -{ -#ifdef HAVE_DUMPFILE - dump_packet(dumpflags, (void *)header, (size_t)plen, NULL, &server->addr); -#endif - log_query_mysockaddr(logflags, name, &server->addr, arg, type); - server_send(server, fd, header, plen, 0); -} -#endif - static int domain_no_rebind(char *domain) { struct rebind_domain *rbd; @@ -524,7 +510,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 */ @@ -854,7 +840,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 } @@ -963,9 +949,13 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header, if (option_bool(OPT_CONNTRACK)) set_outgoing_mark(orig, fd); #endif - server_send_log(server, fd, header, nn, DUMP_SEC_QUERY, - F_NOEXTRA | F_DNSSEC | F_SERVER, daemon->keyname, - STAT_ISEQUAL(status, STAT_NEED_KEY) ? "dnssec-query[DNSKEY]" : "dnssec-query[DS]", 0); + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)nn, NULL, &server->addr, daemon->port); +#endif + log_query_mysockaddr(F_NOEXTRA | F_DNSSEC | F_SERVER, daemon->keyname, &server->addr, + STAT_ISEQUAL(status, STAT_NEED_KEY) ? "dnssec-query[DNSKEY]" : "dnssec-query[DS]", 0); + server_send(server, fd, header, nn, 0); server->queries++; return; } @@ -1057,7 +1047,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 @@ -1261,7 +1251,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); + dump_packet(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &src->source, daemon->port); #endif #if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS) @@ -1576,7 +1566,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 @@ -1659,7 +1649,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); @@ -1675,7 +1665,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) @@ -1701,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 #if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS) if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask)) diff --git a/src/rfc3315.c b/src/rfc3315.c index a286395..6c55672 100644 --- a/src/rfc3315.c +++ b/src/rfc3315.c @@ -2176,6 +2176,18 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, } } +#ifdef HAVE_DUMPFILE + { + union mysockaddr fromsock; + fromsock.in6.sin6_port = htons(DHCPV6_SERVER_PORT); + fromsock.in6.sin6_addr = from.addr6; + fromsock.sa.sa_family = AF_INET6; + fromsock.in6.sin6_flowinfo = 0; + fromsock.in6.sin6_scope_id = 0; + + dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), &fromsock, &to, 0); + } +#endif send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(-1), &to, &from, 0); if (option_bool(OPT_LOG_OPTS)) diff --git a/src/tftp.c b/src/tftp.c index b82d89d..bdf37a3 100644 --- a/src/tftp.c +++ b/src/tftp.c @@ -95,6 +95,10 @@ void tftp_request(struct listener *listen, time_t now) if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2) return; + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_TFTP, (void *)packet, len, (union mysockaddr *)&peer, NULL, TFTP_PORT); +#endif /* Can always get recvd interface for IPv6 */ if (!check_dest) @@ -482,6 +486,10 @@ void tftp_request(struct listener *listen, time_t now) } send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), packet, len, &peer, &addra, if_index); + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_TFTP, (void *)packet, len, NULL, (union mysockaddr *)&peer, TFTP_PORT); +#endif if (is_err) free_transfer(transfer); @@ -600,6 +608,10 @@ void check_tftp_listeners(time_t now) prettyprint_addr(&peer, daemon->addrbuff); len = tftp_err(ERR_TID, daemon->packet, _("ignoring packet from %s (TID mismatch)"), daemon->addrbuff, NULL); while(retry_send(sendto(transfer->sockfd, daemon->packet, len, 0, &peer.sa, sa_len(&peer)))); + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_TFTP, (void *)daemon->packet, len, NULL, (union mysockaddr *)&peer, TFTP_PORT); +#endif } } } @@ -634,9 +646,14 @@ void check_tftp_listeners(time_t now) } if (len != 0) - send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), daemon->packet, len, - &transfer->peer, &transfer->source, transfer->if_index); - + { + send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), daemon->packet, len, + &transfer->peer, &transfer->source, transfer->if_index); +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_TFTP, (void *)daemon->packet, len, NULL, (union mysockaddr *)&transfer->peer, TFTP_PORT); +#endif + } + if (endcon || len == 0) { strcpy(daemon->namebuff, transfer->file->filename); From b5dafc0b7e3a3b6bad70d33a64873dbb6e8087a3 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Sat, 29 Jan 2022 22:52:21 +0000 Subject: [PATCH 3/8] Extend packet dump system to RA. --- man/dnsmasq.8 | 2 +- src/dnsmasq.h | 3 +- src/dump.c | 88 +++++++++++++++++++++++++++++++++++++++------------ src/radv.c | 18 +++++++++-- 4 files changed, 86 insertions(+), 25 deletions(-) diff --git a/man/dnsmasq.8 b/man/dnsmasq.8 index 398c2c6..abed551 100644 --- a/man/dnsmasq.8 +++ b/man/dnsmasq.8 @@ -734,7 +734,7 @@ Specify the location of a pcap-format file which dnsmasq uses to dump copies of .TP .B --dumpmask= Specify which types of packets should be added to the dumpfile. The argument should be the OR of the bitmasks for each type of packet to be dumped: it can be specified in hex by preceding the number with 0x in the normal way. Each time a packet is written to the dumpfile, dnsmasq logs the packet sequence and the mask -representing its type. The current types are: 0x0001 - DNS queries from clients, 0x0002 DNS replies to clients, 0x0004 - DNS queries to upstream, 0x0008 - DNS replies from upstream, 0x0010 - queries send upstream for DNSSEC validation, 0x0020 - replies to queries for DNSSEC validation, 0x0040 - replies to client queries which fail DNSSEC validation, 0x0080 replies to queries for DNSSEC validation which fail validation, 0x1000 - DHCPv4, 0x2000 - DHCPv6, 0x8000 - TFTP. +representing its type. The current types are: 0x0001 - DNS queries from clients, 0x0002 DNS replies to clients, 0x0004 - DNS queries to upstream, 0x0008 - DNS replies from upstream, 0x0010 - queries send upstream for DNSSEC validation, 0x0020 - replies to queries for DNSSEC validation, 0x0040 - replies to client queries which fail DNSSEC validation, 0x0080 replies to queries for DNSSEC validation which fail validation, 0x1000 - DHCPv4, 0x2000 - DHCPv6, 0x4000 - Router advertisement, 0x8000 - TFTP. .TP .B --add-mac[=base64|text] Add the MAC address of the requestor to DNS queries which are diff --git a/src/dnsmasq.h b/src/dnsmasq.h index a921f7d..ad2837e 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -700,6 +700,7 @@ struct hostsfile { #define DUMP_SEC_BOGUS 0x0080 #define DUMP_DHCP 0x1000 #define DUMP_DHCPV6 0x2000 +#define DUMP_RA 0x4000 #define DUMP_TFTP 0x8000 /* DNSSEC status values. */ @@ -1798,7 +1799,7 @@ int do_arp_script_run(void); #ifdef HAVE_DUMPFILE void dump_init(void); void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, - union mysockaddr *dst, unsigned short port); + union mysockaddr *dst, int port); #endif /* domain-match.c */ diff --git a/src/dump.c b/src/dump.c index 4aae008..3d9ef1f 100644 --- a/src/dump.c +++ b/src/dump.c @@ -18,6 +18,8 @@ #ifdef HAVE_DUMPFILE +#include + static u32 packet_count; /* https://wiki.wireshark.org/Development/LibpcapFileFormat */ @@ -79,8 +81,9 @@ void dump_init(void) } } +/* port == -1 ->ICMPv6 */ void dump_packet(int mask, void *packet, size_t len, - union mysockaddr *src, union mysockaddr *dst, unsigned short port) + union mysockaddr *src, union mysockaddr *dst, int port) { struct ip ip; struct ip6_hdr ip6; @@ -116,10 +119,19 @@ void dump_packet(int mask, void *packet, size_t len, memset(&ip6, 0, sizeof(ip6)); ip6.ip6_vfc = 6 << 4; - ip6.ip6_plen = htons(sizeof(struct udphdr) + len); - ip6.ip6_nxt = IPPROTO_UDP; ip6.ip6_hops = 64; + if (port == -1) + { + ip6.ip6_plen = htons(len); + ip6.ip6_nxt = IPPROTO_ICMPV6; + } + else + { + ip6.ip6_plen = htons(sizeof(struct udphdr) + len); + ip6.ip6_nxt = IPPROTO_UDP; + } + if (src) { memcpy(&ip6.ip6_src, &src->in6.sin6_addr, IN6ADDRSZ); @@ -137,7 +149,6 @@ void dump_packet(int mask, void *packet, size_t len, { sum += ip6.ip6_src.s6_addr[i] + (ip6.ip6_src.s6_addr[i+1] << 8) ; sum += ip6.ip6_dst.s6_addr[i] + (ip6.ip6_dst.s6_addr[i+1] << 8) ; - } } else @@ -148,9 +159,18 @@ void dump_packet(int mask, void *packet, size_t len, ip.ip_v = IPVERSION; ip.ip_hl = sizeof(struct ip) / 4; - ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len); ip.ip_ttl = IPDEFTTL; - ip.ip_p = IPPROTO_UDP; + + if (port == -1) + { + ip.ip_len = htons(sizeof(struct ip) + len); + ip.ip_p = IPPROTO_ICMP; + } + else + { + ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len); + ip.ip_p = IPPROTO_UDP; + } if (src) { @@ -181,31 +201,59 @@ void dump_packet(int mask, void *packet, size_t len, if (len & 1) ((unsigned char *)packet)[len] = 0; /* for checksum, in case length is odd. */ - udp.uh_sum = 0; - udp.uh_ulen = htons(sizeof(struct udphdr) + len); - sum += htons(IPPROTO_UDP); - sum += htons(sizeof(struct udphdr) + len); - for (i = 0; i < sizeof(struct udphdr)/2; i++) - sum += ((u16 *)&udp)[i]; - for (i = 0; i < (len + 1) / 2; i++) - sum += ((u16 *)packet)[i]; - while (sum >> 16) - sum = (sum & 0xffff) + (sum >> 16); - udp.uh_sum = (sum == 0xffff) ? sum : ~sum; + if (port == -1) + { + /* ICMP - ICMPv6 packet is a superset of ICMP */ + struct icmp6_hdr *icmp = packet; + + /* See comment in UDP code below. */ + sum += htons(family == AF_INET6 ? IPPROTO_ICMPV6 : IPPROTO_ICMP); + sum += htons(len); + + icmp->icmp6_cksum = 0; + for (i = 0; i < (len + 1) / 2; i++) + sum += ((u16 *)packet)[i]; + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + icmp->icmp6_cksum = (sum == 0xffff) ? sum : ~sum; + pcap_header.incl_len = pcap_header.orig_len = ipsz + len; + } + else + { + /* Add Remaining part of the pseudoheader. Note that though the + IPv6 pseudoheader is very different to the IPv4 one, the + net result of this calculation is correct as long as the + packet length is less than 65536, which is fine for us. */ + sum += htons(IPPROTO_UDP); + sum += htons(sizeof(struct udphdr) + len); + + udp.uh_sum = 0; + udp.uh_ulen = htons(sizeof(struct udphdr) + len); + + for (i = 0; i < sizeof(struct udphdr)/2; i++) + sum += ((u16 *)&udp)[i]; + for (i = 0; i < (len + 1) / 2; i++) + sum += ((u16 *)packet)[i]; + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + udp.uh_sum = (sum == 0xffff) ? sum : ~sum; + + pcap_header.incl_len = pcap_header.orig_len = ipsz + sizeof(udp) + len; + } + rc = gettimeofday(&time, NULL); pcap_header.ts_sec = time.tv_sec; pcap_header.ts_usec = time.tv_usec; - pcap_header.incl_len = pcap_header.orig_len = ipsz + sizeof(udp) + len; if (rc == -1 || !read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 0) || !read_write(daemon->dumpfd, iphdr, ipsz, 0) || - !read_write(daemon->dumpfd, (void *)&udp, sizeof(udp), 0) || + (port != -1 && !read_write(daemon->dumpfd, (void *)&udp, sizeof(udp), 0)) || !read_write(daemon->dumpfd, (void *)packet, len, 0)) my_syslog(LOG_ERR, _("failed to write packet dump")); else - my_syslog(LOG_INFO, _("dumping UDP packet %u mask 0x%04x"), ++packet_count, mask); + my_syslog(LOG_INFO, _("dumping packet %u mask 0x%04x"), ++packet_count, mask); } diff --git a/src/radv.c b/src/radv.c index 2b6d944..021c62a 100644 --- a/src/radv.c +++ b/src/radv.c @@ -123,7 +123,11 @@ void ra_start_unsolicited(time_t now, struct dhcp_context *context) and pick up new interfaces */ if (context) - context->ra_short_period_start = context->ra_time = now; + { + context->ra_short_period_start = now; + /* start after 1 second to get logging right at startup. */ + context->ra_time = now + 1; + } else for (context = daemon->dhcp6; context; context = context->next) if (!(context->flags & CONTEXT_TEMPLATE)) @@ -162,7 +166,7 @@ void icmp6_packet(time_t now) return; packet = (unsigned char *)daemon->outpacket.iov_base; - + for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo) { @@ -187,13 +191,17 @@ void icmp6_packet(time_t now) if (packet[1] != 0) return; - + if (packet[0] == ICMP6_ECHO_REPLY) lease_ping_reply(&from.sin6_addr, packet, interface); else if (packet[0] == ND_ROUTER_SOLICIT) { char *mac = ""; struct dhcp_bridge *bridge, *alias; + +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_RA, (void *)packet, sz, (union mysockaddr *)&from, NULL, -1); +#endif /* look for link-layer address option for logging */ if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz) @@ -543,6 +551,10 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &send_iface, sizeof(send_iface)); } +#ifdef HAVE_DUMPFILE + dump_packet(DUMP_RA, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL, (union mysockaddr *)&addr, -1); +#endif + while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(-1), 0, (struct sockaddr *)&addr, sizeof(addr)))); From ed200fa0018dfafdb7f402ef7789c3896d1c5739 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Sat, 29 Jan 2022 23:22:52 +0000 Subject: [PATCH 4/8] Handle options other than source link-layer address in router solicitations. RFC 4861 para 4.1 is a MUST. --- src/radv.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/radv.c b/src/radv.c index 021c62a..2b4326c 100644 --- a/src/radv.c +++ b/src/radv.c @@ -198,21 +198,29 @@ void icmp6_packet(time_t now) { char *mac = ""; struct dhcp_bridge *bridge, *alias; - + ssize_t rem; + unsigned char *p; + int opt_sz; + #ifdef HAVE_DUMPFILE dump_packet(DUMP_RA, (void *)packet, sz, (union mysockaddr *)&from, NULL, -1); #endif /* look for link-layer address option for logging */ - if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz) + for (rem = sz - 8, p = &packet[8]; rem >= 2; rem -= opt_sz, p += opt_sz) { - if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) { - return; - } - print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2); - mac = daemon->namebuff; + opt_sz = p[1] * 8; + + if (opt_sz == 0 || opt_sz > rem) + return; /* Bad packet */ + + if (p[0] == ICMP6_OPT_SOURCE_MAC && ((opt_sz - 2) * 3 - 1 < MAXDNAME)) + { + print_mac(daemon->namebuff, &p[2], opt_sz - 2); + mac = daemon->namebuff; + } } - + if (!option_bool(OPT_QUIET_RA)) my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac); From dbceeb4178af80619c0e319f71c4466daeedec82 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Sun, 30 Jan 2022 00:42:46 +0000 Subject: [PATCH 5/8] Dump.c Fix IPv6 checksum on big-endian. --- src/dump.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dump.c b/src/dump.c index 3d9ef1f..7b15945 100644 --- a/src/dump.c +++ b/src/dump.c @@ -147,8 +147,8 @@ void dump_packet(int mask, void *packet, size_t len, /* start UDP checksum */ for (sum = 0, i = 0; i < IN6ADDRSZ; i+=2) { - sum += ip6.ip6_src.s6_addr[i] + (ip6.ip6_src.s6_addr[i+1] << 8) ; - sum += ip6.ip6_dst.s6_addr[i] + (ip6.ip6_dst.s6_addr[i+1] << 8) ; + sum += ntohs((ip6.ip6_src.s6_addr[i] << 8) + (ip6.ip6_src.s6_addr[i+1])) ; + sum += ntohs((ip6.ip6_dst.s6_addr[i] << 8) + (ip6.ip6_dst.s6_addr[i+1])) ; } } else @@ -207,7 +207,7 @@ void dump_packet(int mask, void *packet, size_t len, struct icmp6_hdr *icmp = packet; /* See comment in UDP code below. */ - sum += htons(family == AF_INET6 ? IPPROTO_ICMPV6 : IPPROTO_ICMP); + sum += htons((family == AF_INET6) ? IPPROTO_ICMPV6 : IPPROTO_ICMP); sum += htons(len); icmp->icmp6_cksum = 0; From 7fbf1cce7b63e366138cb336d60020885d60f848 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Tue, 1 Feb 2022 00:18:44 +0000 Subject: [PATCH 6/8] Improve the performance of DHCP relay. On machines with many interfaces, enumerating them via netlink on each packet reciept is slow, and unneccesary. All we need is the local address->interface mapping, which can be cached in the relay structures. --- src/dhcp.c | 183 +++++++++++++++++++++++++------------------------- src/dhcp6.c | 57 +++++++--------- src/dnsmasq.h | 4 +- src/network.c | 11 +++ src/rfc3315.c | 169 +++++++++++++++++++++++----------------------- 5 files changed, 217 insertions(+), 207 deletions(-) diff --git a/src/dhcp.c b/src/dhcp.c index de766c1..a71ddf0 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -20,8 +20,6 @@ struct iface_param { struct dhcp_context *current; - struct dhcp_relay *relay; - struct in_addr relay_local; int ind; }; @@ -34,7 +32,7 @@ static int complete_context(struct in_addr local, int if_index, char *label, struct in_addr netmask, struct in_addr broadcast, void *vparam); static int check_listen_addrs(struct in_addr local, int if_index, char *label, struct in_addr netmask, struct in_addr broadcast, void *vparam); -static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index); +static int relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz); static struct dhcp_relay *relay_reply4(struct dhcp_packet *mess, char *arrival_interface); static int make_fd(int port) @@ -307,12 +305,7 @@ void dhcp_packet(time_t now, int pxe_fd) for (context = daemon->dhcp; context; context = context->next) context->current = context; - for (relay = daemon->relay4; relay; relay = relay->next) - relay->current = relay; - parm.current = NULL; - parm.relay = NULL; - parm.relay_local.s_addr = 0; parm.ind = iface_index; if (!iface_check(AF_INET, (union all_addr *)&iface_addr, ifr.ifr_name, NULL)) @@ -334,15 +327,19 @@ void dhcp_packet(time_t now, int pxe_fd) there is more than one address on the interface in the same subnet */ complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm); } + + if (relay_upstream4(iface_index, mess, (size_t)sz)) + return; if (!iface_enumerate(AF_INET, &parm, complete_context)) return; - /* We're relaying this request */ - if (parm.relay_local.s_addr != 0 && - relay_upstream4(parm.relay, mess, (size_t)sz, iface_index)) + /* Check for a relay again after iface_enumerate/complete_context has had + chance to fill in relay->iface_index fields. This handles first time through + and any changes in interface config. */ + if (relay_upstream4(iface_index, mess, (size_t)sz)) return; - + /* May have configured relay, but not DHCP server */ if (!daemon->dhcp) return; @@ -631,14 +628,9 @@ static int complete_context(struct in_addr local, int if_index, char *label, } for (relay = daemon->relay4; relay; relay = relay->next) - if (if_index == param->ind && relay->local.addr4.s_addr == local.s_addr && relay->current == relay && - (param->relay_local.s_addr == 0 || param->relay_local.s_addr == local.s_addr)) - { - relay->current = param->relay; - param->relay = relay; - param->relay_local = local; - } - + if (relay->local.addr4.s_addr == local.s_addr) + relay->iface_index = if_index; + return 1; } @@ -1079,85 +1071,96 @@ char *host_from_dns(struct in_addr addr) return NULL; } -static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index) +static int relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz) { - /* ->local is same value for all relays on ->current chain */ - union all_addr from; - + struct in_addr giaddr = mess->giaddr; + u8 hops = mess->hops; + struct dhcp_relay *relay; + if (mess->op != BOOTREQUEST) return 0; - /* source address == relay address */ - from.addr4 = relay->local.addr4; + for (relay = daemon->relay4; relay; relay = relay->next) + if (relay->iface_index != 0 && relay->iface_index == iface_index) + break; + + /* No relay config. */ + if (!relay) + return 0; - /* already gatewayed ? */ - if (mess->giaddr.s_addr) - { - /* if so check if by us, to stomp on loops. */ - if (mess->giaddr.s_addr == relay->local.addr4.s_addr) - return 1; - } - else - { - /* plug in our address */ - mess->giaddr.s_addr = relay->local.addr4.s_addr; - } - - if ((mess->hops++) > 20) - return 1; - - for (; relay; relay = relay->current) - { - union mysockaddr to; - - to.sa.sa_family = AF_INET; - to.in.sin_addr = relay->server.addr4; - to.in.sin_port = htons(daemon->dhcp_server_port); - - /* Broadcasting to server. */ - if (relay->server.addr4.s_addr == 0) - { - struct ifreq ifr; - - if (relay->interface) - safe_strncpy(ifr.ifr_name, relay->interface, IF_NAMESIZE); - - if (!relay->interface || strchr(relay->interface, '*') || - ioctl(daemon->dhcpfd, SIOCGIFBRDADDR, &ifr) == -1) - { - my_syslog(MS_DHCP | LOG_ERR, _("Cannot broadcast DHCP relay via interface %s"), relay->interface); - return 1; - } - - to.in.sin_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; - } - -#ifdef HAVE_DUMPFILE + for (; relay; relay = relay->next) + if (relay->iface_index != 0 && relay->iface_index == iface_index) { - union mysockaddr fromsock; - fromsock.in.sin_port = htons(daemon->dhcp_server_port); - fromsock.in.sin_addr = from.addr4; - fromsock.sa.sa_family = AF_INET; + union mysockaddr to; + union all_addr from; + + mess->hops = hops; + mess->giaddr = giaddr; - dump_packet(DUMP_DHCP, (void *)mess, sz, &fromsock, &to, 0); - } -#endif - - send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0); - - if (option_bool(OPT_LOG_OPTS)) + if ((mess->hops++) > 20) + continue; + + /* source address == relay address */ + from.addr4 = relay->local.addr4; + + /* already gatewayed ? */ + if (giaddr.s_addr) + { + /* if so check if by us, to stomp on loops. */ + if (giaddr.s_addr == relay->local.addr4.s_addr) + continue; + } + else + { + /* plug in our address */ + mess->giaddr.s_addr = relay->local.addr4.s_addr; + } + + to.sa.sa_family = AF_INET; + to.in.sin_addr = relay->server.addr4; + to.in.sin_port = htons(daemon->dhcp_server_port); + + /* Broadcasting to server. */ + if (relay->server.addr4.s_addr == 0) + { + struct ifreq ifr; + + if (relay->interface) + safe_strncpy(ifr.ifr_name, relay->interface, IF_NAMESIZE); + + if (!relay->interface || strchr(relay->interface, '*') || + ioctl(daemon->dhcpfd, SIOCGIFBRDADDR, &ifr) == -1) + { + my_syslog(MS_DHCP | LOG_ERR, _("Cannot broadcast DHCP relay via interface %s"), relay->interface); + continue; + } + + to.in.sin_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; + } + +#ifdef HAVE_DUMPFILE { - inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN); - if (relay->server.addr4.s_addr == 0) - snprintf(daemon->dhcp_buff2, DHCP_BUFF_SZ, _("broadcast via %s"), relay->interface); - else - inet_ntop(AF_INET, &relay->server.addr4, daemon->dhcp_buff2, DHCP_BUFF_SZ); - my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->dhcp_buff2); + union mysockaddr fromsock; + fromsock.in.sin_port = htons(daemon->dhcp_server_port); + fromsock.in.sin_addr = from.addr4; + fromsock.sa.sa_family = AF_INET; + + dump_packet(DUMP_DHCP, (void *)mess, sz, &fromsock, &to, 0); } - - /* Save this for replies */ - relay->iface_index = iface_index; - } +#endif + + send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0); + + if (option_bool(OPT_LOG_OPTS)) + { + inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN); + if (relay->server.addr4.s_addr == 0) + snprintf(daemon->dhcp_buff2, DHCP_BUFF_SZ, _("broadcast via %s"), relay->interface); + else + inet_ntop(AF_INET, &relay->server.addr4, daemon->dhcp_buff2, DHCP_BUFF_SZ); + my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->dhcp_buff2); + } + } return 1; } diff --git a/src/dhcp6.c b/src/dhcp6.c index a343740..edb87a4 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -22,8 +22,7 @@ struct iface_param { struct dhcp_context *current; - struct dhcp_relay *relay; - struct in6_addr fallback, relay_local, ll_addr, ula_addr; + struct in6_addr fallback, ll_addr, ula_addr; int ind, addr_match; }; @@ -90,7 +89,6 @@ void dhcp6_init(void) void dhcp6_packet(time_t now) { struct dhcp_context *context; - struct dhcp_relay *relay; struct iface_param parm; struct cmsghdr *cmptr; struct msghdr msg; @@ -105,7 +103,8 @@ void dhcp6_packet(time_t now) struct iname *tmp; unsigned short port; struct in6_addr dst_addr; - + struct in6_addr all_servers; + memset(&dst_addr, 0, sizeof(dst_addr)); msg.msg_control = control_u.control6; @@ -164,8 +163,6 @@ void dhcp6_packet(time_t now) return; parm.current = NULL; - parm.relay = NULL; - memset(&parm.relay_local, 0, IN6ADDRSZ); parm.ind = if_index; parm.addr_match = 0; memset(&parm.fallback, 0, IN6ADDRSZ); @@ -210,12 +207,24 @@ void dhcp6_packet(time_t now) memset(&context->local6, 0, IN6ADDRSZ); } - for (relay = daemon->relay6; relay; relay = relay->next) - relay->current = relay; + /* Ignore requests sent to the ALL_SERVERS multicast address for relay when + we're listening there for DHCPv6 server reasons. */ + inet_pton(AF_INET6, ALL_SERVERS, &all_servers); + + if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) && + relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now)) + return; if (!iface_enumerate(AF_INET6, &parm, complete_context6)) return; + /* Check for a relay again after iface_enumerate/complete_context has had + chance to fill in relay->iface_index fields. This handles first time through + and any changes in interface config. */ + if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) && + relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now)) + return; + if (daemon->if_names || daemon->if_addrs) { @@ -227,19 +236,6 @@ void dhcp6_packet(time_t now) return; } - if (parm.relay) - { - /* Ignore requests sent to the ALL_SERVERS multicast address for relay when - we're listening there for DHCPv6 server reasons. */ - struct in6_addr all_servers; - - inet_pton(AF_INET6, ALL_SERVERS, &all_servers); - - if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers)) - relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id, now); - return; - } - /* May have configured relay, but not DHCP server */ if (!daemon->doing_dhcp6) return; @@ -326,6 +322,7 @@ static int complete_context6(struct in6_addr *local, int prefix, struct dhcp_relay *relay; struct iface_param *param = vparam; struct iname *tmp; + int match = !daemon->if_addrs; (void)scope; /* warning */ @@ -347,7 +344,7 @@ static int complete_context6(struct in6_addr *local, int prefix, for (tmp = daemon->if_addrs; tmp; tmp = tmp->next) if (tmp->addr.sa.sa_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local)) - param->addr_match = 1; + match = param->addr_match = 1; /* Determine a globally address on the arrival interface, even if we have no matching dhcp-context, because we're only @@ -419,16 +416,12 @@ static int complete_context6(struct in6_addr *local, int prefix, } } } - - for (relay = daemon->relay6; relay; relay = relay->next) - if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6) && relay->current == relay && - (IN6_IS_ADDR_UNSPECIFIED(¶m->relay_local) || IN6_ARE_ADDR_EQUAL(local, ¶m->relay_local))) - { - relay->current = param->relay; - param->relay = relay; - param->relay_local = *local; - } - + + if (match) + for (relay = daemon->relay6; relay; relay = relay->next) + if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6)) + relay->iface_index = if_index; + return 1; } diff --git a/src/dnsmasq.h b/src/dnsmasq.h index ad2837e..2ffe808 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -1089,7 +1089,7 @@ struct dhcp_relay { struct snoop_record *next; } *snoop_records; #endif - struct dhcp_relay *current, *next; + struct dhcp_relay *next; }; extern struct daemon { @@ -1682,7 +1682,7 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name, struct in6_addr *fallback, struct in6_addr *ll_addr, struct in6_addr *ula_addr, size_t sz, struct in6_addr *client_addr, time_t now); -void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, +int relay_upstream6(int iface_index, ssize_t sz, struct in6_addr *peer_address, u32 scope_id, time_t now); int relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface); diff --git a/src/network.c b/src/network.c index 7cd3371..68aaa6c 100644 --- a/src/network.c +++ b/src/network.c @@ -1743,6 +1743,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) || @@ -1751,6 +1753,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) @@ -1761,5 +1769,8 @@ void newaddress(time_t now) if (daemon->doing_dhcp6) lease_find_interfaces(now); + + for (relay = daemon->relay6; relay; relay = relay->next) + relay->iface_index = 0; #endif } diff --git a/src/rfc3315.c b/src/rfc3315.c index 6c55672..cee8382 100644 --- a/src/rfc3315.c +++ b/src/rfc3315.c @@ -2100,110 +2100,113 @@ static unsigned int opt6_uint(unsigned char *opt, int offset, int size) return ret; } -void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, - struct in6_addr *peer_address, u32 scope_id, time_t now) +int relay_upstream6(int iface_index, ssize_t sz, + struct in6_addr *peer_address, u32 scope_id, time_t now) { - /* ->local is same value for all relays on ->current chain */ - - union all_addr from; unsigned char *header; unsigned char *inbuff = daemon->dhcp_packet.iov_base; int msg_type = *inbuff; - int hopcount; + int hopcount, o; struct in6_addr multicast; unsigned int maclen, mactype; unsigned char mac[DHCP_CHADDR_MAX]; + struct dhcp_relay *relay; + + for (relay = daemon->relay6; relay; relay = relay->next) + if (relay->iface_index != 0 && relay->iface_index == iface_index) + break; + /* No relay config. */ + if (!relay) + return 0; + inet_pton(AF_INET6, ALL_SERVERS, &multicast); get_client_mac(peer_address, scope_id, mac, &maclen, &mactype, now); - - /* source address == relay address */ - from.addr6 = relay->local.addr6; - + /* Get hop count from nested relayed message */ if (msg_type == DHCP6RELAYFORW) hopcount = *((unsigned char *)inbuff+1) + 1; else hopcount = 0; - /* RFC 3315 HOP_COUNT_LIMIT */ - if (hopcount > 32) - return; - reset_counter(); - if ((header = put_opt6(NULL, 34))) + /* RFC 3315 HOP_COUNT_LIMIT */ + if (hopcount > 32 || !(header = put_opt6(NULL, 34))) + return 1; + + header[0] = DHCP6RELAYFORW; + header[1] = hopcount; + memcpy(&header[18], peer_address, IN6ADDRSZ); + + /* RFC-6939 */ + if (maclen != 0) { - int o; - - header[0] = DHCP6RELAYFORW; - header[1] = hopcount; - memcpy(&header[2], &relay->local.addr6, IN6ADDRSZ); - memcpy(&header[18], peer_address, IN6ADDRSZ); - - /* RFC-6939 */ - if (maclen != 0) - { - o = new_opt6(OPTION6_CLIENT_MAC); - put_opt6_short(mactype); - put_opt6(mac, maclen); - end_opt6(o); - } - - o = new_opt6(OPTION6_RELAY_MSG); - put_opt6(inbuff, sz); + o = new_opt6(OPTION6_CLIENT_MAC); + put_opt6_short(mactype); + put_opt6(mac, maclen); end_opt6(o); - - for (; relay; relay = relay->current) - { - union mysockaddr to; - - to.sa.sa_family = AF_INET6; - to.in6.sin6_addr = relay->server.addr6; - to.in6.sin6_port = htons(DHCPV6_SERVER_PORT); - to.in6.sin6_flowinfo = 0; - to.in6.sin6_scope_id = 0; - - if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast)) - { - int multicast_iface; - if (!relay->interface || strchr(relay->interface, '*') || - (multicast_iface = if_nametoindex(relay->interface)) == 0 || - setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_iface, sizeof(multicast_iface)) == -1) - { - my_syslog(MS_DHCP | LOG_ERR, _("Cannot multicast DHCP relay via interface %s"), relay->interface); - return; - } - } - -#ifdef HAVE_DUMPFILE - { - union mysockaddr fromsock; - fromsock.in6.sin6_port = htons(DHCPV6_SERVER_PORT); - fromsock.in6.sin6_addr = from.addr6; - fromsock.sa.sa_family = AF_INET6; - fromsock.in6.sin6_flowinfo = 0; - fromsock.in6.sin6_scope_id = 0; - - dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), &fromsock, &to, 0); - } -#endif - send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(-1), &to, &from, 0); - - if (option_bool(OPT_LOG_OPTS)) - { - inet_ntop(AF_INET6, &relay->local, daemon->addrbuff, ADDRSTRLEN); - if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast)) - snprintf(daemon->namebuff, MAXDNAME, _("multicast via %s"), relay->interface); - else - inet_ntop(AF_INET6, &relay->server, daemon->namebuff, ADDRSTRLEN); - my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->namebuff); - } - - /* Save this for replies */ - relay->iface_index = scope_id; - } } + + o = new_opt6(OPTION6_RELAY_MSG); + put_opt6(inbuff, sz); + end_opt6(o); + + for (; relay; relay = relay->next) + if (relay->iface_index != 0 && relay->iface_index == iface_index) + { + union mysockaddr to; + union all_addr from; + + /* source address == relay address */ + from.addr6 = relay->local.addr6; + memcpy(&header[2], &relay->local.addr6, IN6ADDRSZ); + + to.sa.sa_family = AF_INET6; + to.in6.sin6_addr = relay->server.addr6; + to.in6.sin6_port = htons(DHCPV6_SERVER_PORT); + to.in6.sin6_flowinfo = 0; + to.in6.sin6_scope_id = 0; + + if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast)) + { + int multicast_iface; + if (!relay->interface || strchr(relay->interface, '*') || + (multicast_iface = if_nametoindex(relay->interface)) == 0 || + setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_iface, sizeof(multicast_iface)) == -1) + { + my_syslog(MS_DHCP | LOG_ERR, _("Cannot multicast DHCP relay via interface %s"), relay->interface); + continue; + } + } + +#ifdef HAVE_DUMPFILE + { + union mysockaddr fromsock; + fromsock.in6.sin6_port = htons(DHCPV6_SERVER_PORT); + fromsock.in6.sin6_addr = from.addr6; + fromsock.sa.sa_family = AF_INET6; + fromsock.in6.sin6_flowinfo = 0; + fromsock.in6.sin6_scope_id = 0; + + dump_packet(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), &fromsock, &to, 0); + } +#endif + send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(-1), &to, &from, 0); + + if (option_bool(OPT_LOG_OPTS)) + { + inet_ntop(AF_INET6, &relay->local, daemon->addrbuff, ADDRSTRLEN); + if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast)) + snprintf(daemon->namebuff, MAXDNAME, _("multicast via %s"), relay->interface); + else + inet_ntop(AF_INET6, &relay->server, daemon->namebuff, ADDRSTRLEN); + my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->namebuff); + } + + } + + return 1; } int relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface) From fa580ad3eb3d40207425cf3dfb7dae48fe7b5680 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Thu, 3 Feb 2022 17:12:38 +0000 Subject: [PATCH 7/8] Handle changing interface indexes when binding DHCP sockets. --- CHANGELOG | 8 ++++++++ src/dhcp-common.c | 38 ++++++++++++++++++++++++++++++++++---- src/dnsmasq.c | 34 +++++++++++++--------------------- src/dnsmasq.h | 2 +- 4 files changed, 56 insertions(+), 26 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e7a5d4a..82835ee 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -39,6 +39,14 @@ version 2.87 a local NODATA answer. The pre-2.86 behaviour is still available, by configuring --address=/example.com/1.2.3.4 --local=/example.com/ + Fix problem with binding DHCP sockets to an individual interface. + Despite the fact that the system call tales the interface _name_ as + a parameter, it actually, binds the socket to interface _index_. + Deleting the interface and creating a new one with the same name + leaves the socket bound to the old index. (Creating new sockets + always allocates a fresh index, they are not reused). We now + take this behaviour into account and keep up with changing indexes. + version 2.86 Handle DHCPREBIND requests in the DHCPv6 server code. diff --git a/src/dhcp-common.c b/src/dhcp-common.c index 611b5cb..95d41da 100644 --- a/src/dhcp-common.c +++ b/src/dhcp-common.c @@ -566,12 +566,16 @@ char *whichdevice(void) } if (found) - return found->name; - + { + char *ret = safe_malloc(strlen(found->name)+1); + strcpy(ret, found->name); + return ret; + } + return NULL; } -void bindtodevice(char *device, int fd) +static int bindtodevice(char *device, int fd) { size_t len = strlen(device)+1; if (len > IFNAMSIZ) @@ -579,7 +583,33 @@ void bindtodevice(char *device, int fd) /* only allowed by root. */ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, len) == -1 && errno != EPERM) - die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET); + return 2; + + return 1; +} + +int bind_dhcp_devices(char *bound_device) +{ + int ret = 0; + + if (bound_device) + { + if (daemon->dhcp) + { + if (!daemon->relay4) + ret |= bindtodevice(bound_device, daemon->dhcpfd); + + if (daemon->enable_pxe && daemon->pxefd != -1) + ret |= bindtodevice(bound_device, daemon->pxefd); + } + +#if defined(HAVE_DHCP6) + if (daemon->doing_dhcp6 && !daemon->relay6) + ret |= bindtodevice(bound_device, daemon->dhcp6fd); +#endif + } + + return ret; } #endif diff --git a/src/dnsmasq.c b/src/dnsmasq.c index d112a7e..7cfb493 100644 --- a/src/dnsmasq.c +++ b/src/dnsmasq.c @@ -387,28 +387,9 @@ int main (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 @@ -1100,6 +1081,17 @@ int main (int argc, char **argv) #endif #ifdef HAVE_DHCP +# if defined(HAVE_LINUX_NETWORK) + if (bind_dhcp_devices(bound_device) & 2) + { + static int warned = 0; + if (!warned) + { + my_syslog(LOG_ERR, _("error binding DHCP socket to device %s"), bound_device); + warned = 1; + } + } +# endif if (daemon->dhcp || daemon->relay4) { poll_listen(daemon->dhcpfd, POLLIN); diff --git a/src/dnsmasq.h b/src/dnsmasq.h index 2ffe808..51a1aa6 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -1715,7 +1715,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs, int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type); #ifdef HAVE_LINUX_NETWORK char *whichdevice(void); -void bindtodevice(char *device, int fd); +int bind_dhcp_devices(char *bound_device); #endif # ifdef HAVE_DHCP6 void display_opts6(void); From 4333d5d93a8fb2c14ef3d9eefb1a13fb6ca8d9d5 Mon Sep 17 00:00:00 2001 From: "Johnny S. Lee via Dnsmasq-discuss" Date: Thu, 3 Feb 2022 23:42:00 +0000 Subject: [PATCH 8/8] Fix FTBFS on BSD platforms. Bug introduced in fc664d114d6e11ced4912b746f18d543f662066b --- src/dhcp.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/dhcp.c b/src/dhcp.c index a71ddf0..6104c87 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -458,9 +458,12 @@ void dhcp_packet(time_t now, int pxe_fd) else { #ifdef HAVE_DUMPFILE - dest.sin_addr.s_addr = (ntohs(mess->flags) & 0x8000) ? INADDR_BROADCAST : mess->yiaddr; + if (ntohs(mess->flags) & 0x8000) + dest.sin_addr.s_addr = INADDR_BROADCAST; + else + dest.sin_addr = mess->yiaddr; dest.sin_port = htons(daemon->dhcp_client_port); - + dump_packet(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL, (union mysockaddr *)&dest, daemon->dhcp_server_port); #endif