]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
dhcrelay: option to force giaddr
authorJens Elkner <jel+git@iks.cs.uni-magdeburg.de>
Sat, 29 Jan 2022 08:32:04 +0000 (09:32 +0100)
committerTomek Mrugalski <tomek@isc.org>
Fri, 4 Mar 2022 09:39:00 +0000 (09:39 +0000)
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.

relay/dhcrelay.8
relay/dhcrelay.c

index b7183f9a10cc0d5c6fcacd1746315c281e28fe5a..9667e60890c72b5bf5d4c753ccefc483902d4c1f 100644 (file)
@@ -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
index 91f5694db0a537aa804b08929c786f287f7b9313..3e4ede1ae6e51590d3f1d499621a073ca084bf12 100644 (file)
@@ -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;