On Tue, Dec 03, 2013 at 11:48:05PM -0500, Kenneth Westerback wrote:
> Rfc 3442 is what I referred to.

I don't think RFC 3442 discusses what to do with /32 IP address
assignments though?

Anyway, below is a revised diff that does the same direct-route magic
for all gateway IPs, not just the default gateway IP.  I'll try this
out later today to make sure it still works with Compute Engine.

Assuming it works as intended, ok?

Index: dhclient.c
===================================================================
RCS file: /cvs/src/sbin/dhclient/dhclient.c,v
retrieving revision 1.268
diff -u -p -r1.268 dhclient.c
--- dhclient.c  20 Nov 2013 17:22:46 -0000      1.268
+++ dhclient.c  4 Dec 2013 18:45:21 -0000
@@ -107,9 +107,11 @@ struct client_lease *clone_lease(struct 
 void            socket_nonblockmode(int);
 void            apply_ignore_list(char *);
 
-void add_default_route(int, struct in_addr, struct in_addr);
-void add_static_routes(int, struct option_data *);
-void add_classless_static_routes(int, struct option_data *);
+void add_default_route(int, struct in_addr, struct in_addr, struct in_addr);
+void add_static_routes(int, struct in_addr, struct in_addr,
+    struct option_data *);
+void add_classless_static_routes(int, struct in_addr, struct in_addr,
+    struct option_data *);
 
 int compare_lease(struct client_lease *, struct client_lease *);
 
@@ -871,8 +873,8 @@ bind_lease(void)
         */
        add_address(ifi->name, ifi->rdomain, client->new->address, mask);
        if (options[DHO_CLASSLESS_STATIC_ROUTES].len) {
-               add_classless_static_routes(ifi->rdomain,
-                   &options[DHO_CLASSLESS_STATIC_ROUTES]);
+               add_classless_static_routes(ifi->rdomain, client->new->address,
+                   mask, &options[DHO_CLASSLESS_STATIC_ROUTES]);
        } else {
                if (options[DHO_ROUTERS].len) {
                        memset(&gateway, 0, sizeof(gateway));
@@ -880,11 +882,11 @@ bind_lease(void)
                        memcpy(&gateway.s_addr, options[DHO_ROUTERS].data,
                            options[DHO_ROUTERS].len);
                        add_default_route(ifi->rdomain, client->new->address,
-                           gateway);
+                           mask, gateway);
                }
                if (options[DHO_STATIC_ROUTES].len)
-                       add_static_routes(ifi->rdomain,
-                           &options[DHO_STATIC_ROUTES]);
+                       add_static_routes(ifi->rdomain, client->new->address,
+                           mask, &options[DHO_STATIC_ROUTES]);
        }
 
        client->new->resolv_conf = resolv_conf_contents(
@@ -2379,6 +2381,23 @@ priv_write_file(struct imsg_write_file *
 }
 
 /*
+ * If we were given a /32 IP address assignment, then make sure the
+ * gateway address is routable with the equivalent of
+ *
+ *     route add -net $gw -netmask 255.255.255.255 -cloning -iface $addr
+ */
+void
+ensure_direct_route(int rdomain, struct in_addr addr, struct in_addr addrmask,
+    struct in_addr gateway)
+{
+       if (addrmask.s_addr == INADDR_BROADCAST) {
+               add_route(rdomain, gateway, addrmask, addr,
+                   RTA_DST | RTA_NETMASK | RTA_GATEWAY,
+                   RTF_CLONING | RTF_STATIC);
+       }
+}
+
+/*
  * add_default_route is the equivalent of
  *
  *     route -q $rdomain add default -iface $router
@@ -2388,11 +2407,14 @@ priv_write_file(struct imsg_write_file *
  *     route -q $rdomain add default $router
  */
 void
-add_default_route(int rdomain, struct in_addr addr, struct in_addr gateway)
+add_default_route(int rdomain, struct in_addr addr, struct in_addr addrmask,
+    struct in_addr gateway)
 {
        struct in_addr netmask, dest;
        int addrs, flags;
 
+       ensure_direct_route(rdomain, addr, addrmask, gateway);
+
        memset(&netmask, 0, sizeof(netmask));
        memset(&dest, 0, sizeof(dest));
        addrs = RTA_DST | RTA_NETMASK;
@@ -2412,23 +2434,26 @@ add_default_route(int rdomain, struct in
 }
 
 void
-add_static_routes(int rdomain, struct option_data *static_routes)
+add_static_routes(int rdomain, struct in_addr addr, struct in_addr addrmask,
+    struct option_data *static_routes)
 {
        struct in_addr           dest, netmask, gateway;
-       u_int8_t                 *addr;
+       u_int8_t                 *data;
        int                      i;
 
        memset(&netmask, 0, sizeof(netmask));   /* Not used for CLASSFULL! */
 
        for (i = 0; (i + 7) < static_routes->len; i += 8) {
-               addr = &static_routes->data[i];
+               data = &static_routes->data[i];
                memset(&dest, 0, sizeof(dest));
                memset(&gateway, 0, sizeof(gateway));
 
-               memcpy(&dest.s_addr, addr, 4);
+               memcpy(&dest.s_addr, data, 4);
                if (dest.s_addr == INADDR_ANY)
                        continue; /* RFC 2132 says 0.0.0.0 is not allowed. */
-               memcpy(&gateway.s_addr, addr+4, 4);
+               memcpy(&gateway.s_addr, data+4, 4);
+
+               ensure_direct_route(rdomain, addr, addrmask, gateway);
 
                /* XXX Order implies priority but we're ignoring that. */
                add_route(rdomain, dest, netmask, gateway,
@@ -2436,8 +2461,9 @@ add_static_routes(int rdomain, struct op
        }
 }
 
-void add_classless_static_routes(int rdomain,
-    struct option_data *classless_static_routes)
+void
+add_classless_static_routes(int rdomain, struct in_addr addr,
+    struct in_addr addrmask, struct option_data *classless_static_routes)
 {
        struct in_addr   dest, netmask, gateway;
        int              bits, bytes, i;
@@ -2463,6 +2489,8 @@ void add_classless_static_routes(int rdo
 
                if (gateway.s_addr == INADDR_ANY)
                        continue; /* OBSD TCP/IP doesn't support this. */
+
+               ensure_direct_route(rdomain, addr, addrmask, gateway);
 
                add_route(rdomain, dest, netmask, gateway,
                    RTA_DST | RTA_GATEWAY | RTA_NETMASK,

Reply via email to