From a267a9e489ed824dbcf40ef857dfee55596e5405 Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Thu, 26 May 2022 16:40:44 +0100 Subject: 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. --- CHANGELOG | 8 ++++++++ man/dnsmasq.8 | 9 ++++++--- src/dhcp-common.c | 11 +++++++++-- src/dhcp.c | 2 +- src/dnsmasq.h | 1 + src/option.c | 10 ++++++++++ src/rfc3315.c | 2 +- 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=[,][,[,[#]][,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; -- cgit v1.2.1