summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2022-05-26 16:40:44 +0100
committerSimon Kelley <simon@thekelleys.org.uk>2022-05-26 16:40:44 +0100
commita267a9e489ed824dbcf40ef857dfee55596e5405 (patch)
treec885e7ec6fd86f33c0980ba13eb22305c4e012a1
parentf65d21001244416d073addcbcfdb722c385f930d (diff)
downloaddnsmasq-a267a9e489ed824dbcf40ef857dfee55596e5405.tar.gz
Add the ability to specify destination port in DHCP-relay mode.
This change also removes a previous bug where --dhcp-alternate-port would affect the port used to relay _to_ as well as the port being listened on. The new feature allows configuration to provide bug-for-bug compatibility, if required. Thanks to Damian Kaczkowski for the feature suggestion.
-rw-r--r--CHANGELOG8
-rw-r--r--man/dnsmasq.89
-rw-r--r--src/dhcp-common.c11
-rw-r--r--src/dhcp.c2
-rw-r--r--src/dnsmasq.h1
-rw-r--r--src/option.c10
-rw-r--r--src/rfc3315.c2
7 files changed, 36 insertions, 7 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 4bc7fb1..780e55c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -58,6 +58,14 @@ version 2.87
Fix write-after-free error in DHCPv6 server code.
CVE-2022-0934 refers.
+ Add the ability to specify destination port in
+ DHCP-relay mode. This change also removes a previous bug
+ where --dhcp-alternate-port would affect the port used
+ to relay _to_ as well as the port being listened on.
+ The new feature allows configuration to provide bug-for-bug
+ compatibility, if required. Thanks to Damian Kaczkowski
+ for the feature suggestion.
+
version 2.86
Handle DHCPREBIND requests in the DHCPv6 server code.
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index fea89fa..f084757 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -1342,7 +1342,7 @@ DHCP options. This make extra space available in the DHCP packet for
options but can, rarely, confuse old or broken clients. This flag
forces "simple and safe" behaviour to avoid problems in such a case.
.TP
-.B --dhcp-relay=<local address>[,<server address>][,<interface]
+.B --dhcp-relay=<local address>[,<server address>[#<server port>]][,<interface]
Configure dnsmasq to do DHCP relay. The local address is an address
allocated to an interface on the host running dnsmasq. All DHCP
requests arriving on that interface will we relayed to a remote DHCP
@@ -1350,9 +1350,12 @@ server at the server address. It is possible to relay from a single local
address to multiple remote servers by using multiple \fB--dhcp-relay\fP
configs with the same local address and different server
addresses. A server address must be an IP literal address, not a
-domain name. If the server address is ommitted, the request will be
+domain name. If the server address is omitted, the request will be
forwarded by broadcast (IPv4) or multicast (IPv6). In this case the interface
-must be given and not be wildcard.
+must be given and not be wildcard. The server address may specify a non-standard
+port to relay to. If this is used then \fB--dhcp-proxy\fP should likely also be set,
+otherwise parts of the DHCP conversation which do not pass through the relay
+will be delivered to the wrong port.
Access control for DHCP clients has the same rules as for the DHCP
server, see \fB--interface\fP, \fB--except-interface\fP, etc. The optional
diff --git a/src/dhcp-common.c b/src/dhcp-common.c
index 95d41da..ab18342 100644
--- a/src/dhcp-common.c
+++ b/src/dhcp-common.c
@@ -1017,7 +1017,10 @@ void log_relay(int family, struct dhcp_relay *relay)
{
int broadcast = relay->server.addr4.s_addr == 0;
inet_ntop(family, &relay->local, daemon->addrbuff, ADDRSTRLEN);
- inet_ntop(family, &relay->server, daemon->namebuff, ADDRSTRLEN);
+ inet_ntop(family, &relay->server, daemon->namebuff, ADDRSTRLEN);
+
+ if (family == AF_INET && relay->port != DHCP_SERVER_PORT)
+ sprintf(daemon->namebuff + strlen(daemon->namebuff), "#%u", relay->port);
#ifdef HAVE_DHCP6
struct in6_addr multicast;
@@ -1025,7 +1028,11 @@ void log_relay(int family, struct dhcp_relay *relay)
inet_pton(AF_INET6, ALL_SERVERS, &multicast);
if (family == AF_INET6)
- broadcast = IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast);
+ {
+ broadcast = IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast);
+ if (relay->port != DHCPV6_SERVER_PORT)
+ sprintf(daemon->namebuff + strlen(daemon->namebuff), "#%u", relay->port);
+ }
#endif
diff --git a/src/dhcp.c b/src/dhcp.c
index 6104c87..8e9c606 100644
--- a/src/dhcp.c
+++ b/src/dhcp.c
@@ -1121,7 +1121,7 @@ static int relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz)
to.sa.sa_family = AF_INET;
to.in.sin_addr = relay->server.addr4;
- to.in.sin_port = htons(daemon->dhcp_server_port);
+ to.in.sin_port = htons(relay->port);
/* Broadcasting to server. */
if (relay->server.addr4.s_addr == 0)
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 0c21cde..a8937ce 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1085,6 +1085,7 @@ struct dhcp_relay {
union all_addr local, server;
char *interface; /* Allowable interface for replies from server, and dest for IPv6 multicast */
int iface_index; /* working - interface in which requests arrived, for return */
+ int port; /* Port of relay we forward to. */
#ifdef HAVE_SCRIPT
struct snoop_record {
struct in6_addr client, prefix;
diff --git a/src/option.c b/src/option.c
index 39e1179..c5e8cb4 100644
--- a/src/option.c
+++ b/src/option.c
@@ -4333,6 +4333,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
{
if (inet_pton(AF_INET, arg, &new->local))
{
+ char *hash = split_chr(two, '#');
+
+ if (!hash || !atoi_check16(hash, &new->port))
+ new->port = DHCP_SERVER_PORT;
+
if (!inet_pton(AF_INET, two, &new->server))
{
new->server.addr4.s_addr = 0;
@@ -4351,6 +4356,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
#ifdef HAVE_DHCP6
else if (inet_pton(AF_INET6, arg, &new->local))
{
+ char *hash = split_chr(two, '#');
+
+ if (!hash || !atoi_check16(hash, &new->port))
+ new->port = DHCPV6_SERVER_PORT;
+
if (!inet_pton(AF_INET6, two, &new->server))
{
inet_pton(AF_INET6, ALL_SERVERS, &new->server.addr6);
diff --git a/src/rfc3315.c b/src/rfc3315.c
index e218d26..6533197 100644
--- a/src/rfc3315.c
+++ b/src/rfc3315.c
@@ -2170,7 +2170,7 @@ int relay_upstream6(int iface_index, ssize_t sz,
to.sa.sa_family = AF_INET6;
to.in6.sin6_addr = relay->server.addr6;
- to.in6.sin6_port = htons(DHCPV6_SERVER_PORT);
+ to.in6.sin6_port = htons(relay->port);
to.in6.sin6_flowinfo = 0;
to.in6.sin6_scope_id = 0;