From 9a46344e91545ea47be50a6f52dd870144e6cfbf Mon Sep 17 00:00:00 2001
From: Brandon Philips <brandon@ifup.co>
Date: Wed, 19 Mar 2014 12:22:33 -0700
Subject: [PATCH] network: dhcp: create host route if dhcp subnet is
 255.255.255.255

The Google Compute Engine DHCP server gives you a netmask of
255.255.255.255 so gateway is not routable. Make a host route instead.
---
 src/network/networkd-link.c                    | 43 ++++++++++++++++
 2 files changed, 43 insertions(+), 69 deletions(-)
 delete mode 100644 d1b60dd716b243eb49ff0b599539d16f137317f6.patch

diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 275ad97..8dbdbf2 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -149,6 +149,7 @@ static int route_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
                link->state == LINK_STATE_FAILED);
 
         link->route_messages --;
+        log_debug_link(link, "route_handler: %i, link->state: %i", link->route_messages, link->state);
 
         if (link->state == LINK_STATE_FAILED)
                 return 1;
@@ -237,7 +238,10 @@ static int link_enter_set_routes(Link *link) {
 
         if (link->dhcp_lease) {
                 _cleanup_route_free_ Route *route = NULL;
+                _cleanup_route_free_ Route *route_host = NULL;
+                struct in_addr netmask;
                 struct in_addr gateway;
+                unsigned prefixlen;
 
                 r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
                 if (r < 0) {
@@ -253,6 +257,45 @@ static int link_enter_set_routes(Link *link) {
                         return r;
                 }
 
+                sd_dhcp_lease_get_netmask(link->dhcp_lease, &netmask);
+                prefixlen = net_netmask_to_prefixlen(&netmask);
+
+                log_debug_link(link,
+				 "prefixlen: %i", prefixlen);
+
+                // If the dhcp netmask is 255.255.255.255 we need to create a
+                // route to the gateway. This will need to be expanded to look
+                // at the existing routes and a host route if the gw is
+                // outside the current table.
+                if (prefixlen == 32) {
+                        struct in_addr gw_addr;
+
+                        r = route_new_dynamic(&route_host);
+                        if (r < 0) {
+                                log_error_link(link, "Could not allocate route: %s",
+                                               strerror(-r));
+                                return r;
+                        }
+
+                        memcpy(&gw_addr, &gateway, sizeof(struct in_addr));
+
+                        route_host->family = AF_INET;
+                        route_host->dst_addr.in = gateway;
+                        route_host->dst_prefixlen = 32;
+                        route_host->scope = RT_SCOPE_LINK;
+
+                        r = route_configure(route_host, link, &route_handler);
+                        if (r < 0) {
+                                log_warning_link(link,
+                                                 "could not set host route: %s", strerror(-r));
+                                return r;
+                        }
+
+                        log_debug_link(link, "route setup: %i", r);
+
+                        link->route_messages ++;
+                }
+
                 route->family = AF_INET;
                 route->in_addr.in = gateway;
 
-- 
1.8.3.2

