summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Elkner <jel+git@iks.cs.uni-magdeburg.de>2022-01-29 09:32:04 +0100
committerTomek Mrugalski <tomek@isc.org>2022-03-04 09:39:00 +0000
commit57913f7f7fc24b66372a5e144ce4a028fea5c61c (patch)
tree82f97debd9887657f530c5464e482a2769ef70f9
parent726912a1c955d15af11acdc9c190b24355ad3441 (diff)
downloadisc-dhcp-57913f7f7fc24b66372a5e144ce4a028fea5c61c.tar.gz
dhcrelay: option to force giaddr
Use option -g ipaddr to replace the giaddr sent to clients with the given ipaddr to workaround bogus clients like Solaris 11 grub which use giaddr instead of the announced router (3) to setup its default route.
-rw-r--r--relay/dhcrelay.810
-rw-r--r--relay/dhcrelay.c29
2 files changed, 35 insertions, 4 deletions
diff --git a/relay/dhcrelay.8 b/relay/dhcrelay.8
index b7183f9a..9667e608 100644
--- a/relay/dhcrelay.8
+++ b/relay/dhcrelay.8
@@ -103,6 +103,10 @@ dhcrelay - Dynamic Host Configuration Protocol Relay Agent
.B -U
.I interface
]
+[
+.B -g
+.I ipaddr
+]
.I server0
[
.I ...serverN
@@ -234,6 +238,12 @@ Information options that indicate they were generated in response to
a query that came via a different relay agent. If this option is not
specified, such packets will be relayed anyway.
.TP
+-g \fIipaddr\fR
+When a package gets sent back to the client, replace the gateway's IP
+address (giaddr) with the given \fIipaddr\fR. This can be used as a
+workaround for bogus clients like Solaris 11 grub, which use the giaddr
+instead of the announced router (3) to setup its default route.
+.TP
-i \fIifname\fR
Listen for DHCPv4/BOOTP traffic on interface \fIifname\fR. Multiple
interfaces may be specified by using more than one \fB-i\fR option. If
diff --git a/relay/dhcrelay.c b/relay/dhcrelay.c
index 91f5694d..3e4ede1a 100644
--- a/relay/dhcrelay.c
+++ b/relay/dhcrelay.c
@@ -105,6 +105,8 @@ struct server_list {
} *servers;
struct interface_info *uplink = NULL;
+static isc_boolean_t fake_gw = ISC_FALSE;
+static struct in_addr gw ;
#ifdef DHCPv6
struct stream_list {
@@ -169,7 +171,7 @@ char *progname;
" [-i interface0 [ ... -i interfaceN]\n" \
" [-iu interface0 [ ... -iu interfaceN]\n" \
" [-id interface0 [ ... -id interfaceN]\n" \
-" [-U interface]\n" \
+" [-U interface] [-g <ip_address>]\n" \
" server0 [ ... serverN]\n\n" \
" %s -6 [-d] [-q] [-I] [-c <hops>]\n" \
" [-p <port> | -rp <relay-port>]\n" \
@@ -189,7 +191,7 @@ char *progname;
" [-i interface0 [ ... -i interfaceN]\n" \
" [-iu interface0 [ ... -iu interfaceN]\n" \
" [-id interface0 [ ... -id interfaceN]\n" \
-" [-U interface]\n" \
+" [-U interface] [-g <ip_address>]\n" \
" server0 [ ... serverN]\n\n" \
" %s -6 [-d] [-q] [-I] [-c <hops>] [-p <port>]\n" \
" [-pf <pid-file>] [--no-pid]\n" \
@@ -210,7 +212,7 @@ char *progname;
" [-i interface0 [ ... -i interfaceN]\n" \
" [-iu interface0 [ ... -iu interfaceN]\n" \
" [-id interface0 [ ... -id interfaceN]\n" \
-" [-U interface]\n" \
+" [-U interface] [-g <ip_address>]\n" \
" server0 [ ... serverN]\n\n" \
" %s {--version|--help|-h}"
#else
@@ -221,7 +223,7 @@ char *progname;
" [-i interface0 [ ... -i interfaceN]\n" \
" [-iu interface0 [ ... -iu interfaceN]\n" \
" [-id interface0 [ ... -id interfaceN]\n" \
-" [-U interface]\n" \
+" [-U interface] [-g <ip_address>]\n" \
" server0 [ ... serverN]\n\n" \
" %s {--version|--help|-h}"
#endif
@@ -547,6 +549,21 @@ main(int argc, char **argv) {
/* Turn on -a, in case they don't do so explicitly */
add_agent_options = 1;
add_rfc3527_suboption = 1;
+ } else if (!strcmp(argv[i], "-g")) {
+ if (++i == argc)
+ usage(use_noarg, argv[i-1]);
+#ifdef DHCPv6
+ if (local_family_set && (local_family == AF_INET6)) {
+ usage(use_v4command, argv[i]);
+ }
+ local_family_set = 1;
+ local_family = AF_INET;
+#endif
+ if (inet_pton(AF_INET, argv[i], &gw) <= 0) {
+ usage("Invalid gateway address '%s'", argv[i]);
+ } else {
+ fake_gw = ISC_TRUE;
+ }
} else if (!strcmp(argv[i], "-D")) {
#ifdef DHCPv6
if (local_family_set && (local_family == AF_INET6)) {
@@ -878,6 +895,7 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet,
return;
}
+ log_debug("BOOTREPLY giaddr: %s\n", inet_ntoa(packet->giaddr));
if (!(packet->flags & htons(BOOTP_BROADCAST)) &&
can_unicast_without_arp(out)) {
to.sin_addr = packet->yiaddr;
@@ -916,6 +934,9 @@ do_relay4(struct interface_info *ip, struct dhcp_packet *packet,
return;
}
+ if (fake_gw) {
+ packet->giaddr = gw;
+ }
if (send_packet(out, NULL, packet, length, out->addresses[0],
&to, htop) < 0) {
++server_packet_errors;