diff options
-rw-r--r-- | relay/dhcrelay.8 | 10 | ||||
-rw-r--r-- | relay/dhcrelay.c | 29 |
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; |