[systemd-commits] 9 commits - src/libsystemd-network src/network src/systemd

Tom Gundersen tomegun at kemper.freedesktop.org
Mon Jul 28 07:06:23 PDT 2014


 src/libsystemd-network/dhcp-network.c         |   16 +-
 src/libsystemd-network/dhcp-protocol.h        |    2 
 src/libsystemd-network/dhcp-server-internal.h |    2 
 src/libsystemd-network/sd-dhcp-client.c       |  199 +++++++++++++++-----------
 src/libsystemd-network/sd-dhcp-server.c       |   60 +++++++
 src/network/networkd-address.c                |    8 -
 src/network/networkd-link.c                   |  107 ++-----------
 src/network/networkd-manager.c                |    4 
 src/network/networkd-network-gperf.gperf      |    8 -
 src/network/networkd-network.c                |   62 ++------
 src/network/networkd-route.c                  |   10 -
 src/network/networkd.h                        |   11 -
 src/systemd/sd-dhcp-client.h                  |    9 -
 src/systemd/sd-dhcp-server.h                  |    2 
 14 files changed, 249 insertions(+), 251 deletions(-)

New commits:
commit 16aa63a00b5b1db23a9c0b8de350ebf482d90cd0
Author: Tom Gundersen <teg at jklm.no>
Date:   Mon Jul 28 12:21:51 2014 +0200

    networkd: route/address - use trivial hash functions

diff --git a/src/network/networkd-address.c b/src/network/networkd-address.c
index 551c1ea..539bd98 100644
--- a/src/network/networkd-address.c
+++ b/src/network/networkd-address.c
@@ -41,8 +41,7 @@ int address_new_static(Network *network, unsigned section, Address **ret) {
         _cleanup_address_free_ Address *address = NULL;
 
         if (section) {
-                uint64_t key = section;
-                address = hashmap_get(network->addresses_by_section, &key);
+                address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section));
                 if (address) {
                         *ret = address;
                         address = NULL;
@@ -63,7 +62,8 @@ int address_new_static(Network *network, unsigned section, Address **ret) {
 
         if (section) {
                 address->section = section;
-                hashmap_put(network->addresses_by_section, &address->section, address);
+                hashmap_put(network->addresses_by_section,
+                            UINT_TO_PTR(address->section), address);
         }
 
         *ret = address;
@@ -96,7 +96,7 @@ void address_free(Address *address) {
 
                 if (address->section)
                         hashmap_remove(address->network->addresses_by_section,
-                                       &address->section);
+                                       UINT_TO_PTR(address->section));
         }
 
         free(address);
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 7e753e1..c99dab8 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -66,11 +66,11 @@ static int network_load_one(Manager *manager, const char *filename) {
         if (!network->stacked_netdevs)
                 return log_oom();
 
-        network->addresses_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
+        network->addresses_by_section = hashmap_new(NULL, NULL);
         if (!network->addresses_by_section)
                 return log_oom();
 
-        network->routes_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
+        network->routes_by_section = hashmap_new(NULL, NULL);
         if (!network->routes_by_section)
                 return log_oom();
 
diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c
index 00fd952..f451b97 100644
--- a/src/network/networkd-route.c
+++ b/src/network/networkd-route.c
@@ -32,9 +32,8 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
         _cleanup_route_free_ Route *route = NULL;
 
         if (section) {
-                uint64_t key = section;
-
-                route = hashmap_get(network->routes_by_section, &key);
+                route = hashmap_get(network->routes_by_section,
+                                    UINT_TO_PTR(section));
                 if (route) {
                         *ret = route;
                         route = NULL;
@@ -57,7 +56,8 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
 
         if (section) {
                 route->section = section;
-                hashmap_put(network->routes_by_section, &route->section, route);
+                hashmap_put(network->routes_by_section,
+                            UINT_TO_PTR(route->section), route);
         }
 
         *ret = route;
@@ -92,7 +92,7 @@ void route_free(Route *route) {
 
                 if (route->section)
                         hashmap_remove(route->network->routes_by_section,
-                                       &route->section);
+                                       UINT_TO_PTR(route->section));
         }
 
         free(route);
diff --git a/src/network/networkd.h b/src/network/networkd.h
index bf73fe2..766297c 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -110,7 +110,7 @@ struct Network {
 
 struct Address {
         Network *network;
-        uint64_t section;
+        unsigned section;
 
         int family;
         unsigned char prefixlen;
@@ -128,7 +128,7 @@ struct Address {
 
 struct Route {
         Network *network;
-        uint64_t section;
+        unsigned section;
 
         int family;
         unsigned char dst_prefixlen;

commit 6a0a2f860f1ca4a10932da3b41dbc3c0139757cc
Author: Tom Gundersen <teg at jklm.no>
Date:   Mon Jul 28 12:10:37 2014 +0200

    networkd: unify handling of stacked netdevs

diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 5eeeb3d..3b8b7ed 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1770,7 +1770,7 @@ static int netdev_join_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata
 }
 
 static int link_enter_join_netdev(Link *link) {
-        NetDev *vlan, *macvlan, *vxlan;
+        NetDev *netdev;
         Iterator i;
         int r;
 
@@ -1784,10 +1784,7 @@ static int link_enter_join_netdev(Link *link) {
 
         if (!link->network->bridge &&
             !link->network->bond &&
-            !link->network->tunnel &&
-            hashmap_isempty(link->network->vlans) &&
-            hashmap_isempty(link->network->macvlans) &&
-            hashmap_isempty(link->network->vxlans))
+            hashmap_isempty(link->network->stacked_netdevs))
                 return link_joined(link);
 
         if (link->network->bond) {
@@ -1836,82 +1833,19 @@ static int link_enter_join_netdev(Link *link) {
                 link->enslaving ++;
         }
 
-        if (link->network->tunnel) {
+        HASHMAP_FOREACH(netdev, link->network->stacked_netdevs, i) {
                 log_struct_link(LOG_DEBUG, link,
                                 "MESSAGE=%-*s: enslaving by '%s'",
                                 IFNAMSIZ,
-                                link->ifname, link->network->tunnel->ifname,
-                                NETDEVIF(link->network->tunnel),
-                                NULL);
+                                link->ifname, netdev->ifname, NETDEVIF(netdev), NULL);
 
-                r = netdev_join(link->network->tunnel, link, &netdev_join_handler);
+                r = netdev_join(netdev, link, &netdev_join_handler);
                 if (r < 0) {
                         log_struct_link(LOG_WARNING, link,
                                         "MESSAGE=%-*s: could not join netdev '%s': %s",
                                         IFNAMSIZ,
-                                        link->ifname, link->network->tunnel->ifname, strerror(-r),
-                                        NETDEVIF(link->network->tunnel),
-                                        NULL);
-                        link_enter_failed(link);
-                        return r;
-                }
-
-                link->enslaving ++;
-        }
-
-        HASHMAP_FOREACH(vlan, link->network->vlans, i) {
-                log_struct_link(LOG_DEBUG, link,
-                                "MESSAGE=%-*s: enslaving by '%s'",
-                                IFNAMSIZ,
-                                link->ifname, vlan->ifname, NETDEVIF(vlan), NULL);
-
-                r = netdev_join(vlan, link, &netdev_join_handler);
-                if (r < 0) {
-                        log_struct_link(LOG_WARNING, link,
-                                        "MESSAGE=%-*s: could not join netdev '%s': %s",
-                                        IFNAMSIZ,
-                                        link->ifname, vlan->ifname, strerror(-r),
-                                        NETDEVIF(vlan), NULL);
-                        link_enter_failed(link);
-                        return r;
-                }
-
-                link->enslaving ++;
-        }
-
-        HASHMAP_FOREACH(macvlan, link->network->macvlans, i) {
-                log_struct_link(LOG_DEBUG, link,
-                                "MESSAGE=%-*s: enslaving by '%s'",
-                                IFNAMSIZ,
-                                link->ifname, macvlan->ifname, NETDEVIF(macvlan), NULL);
-
-                r = netdev_join(macvlan, link, &netdev_join_handler);
-                if (r < 0) {
-                        log_struct_link(LOG_WARNING, link,
-                                        "MESSAGE=%-*s: could not join netdev '%s': %s",
-                                        IFNAMSIZ,
-                                        link->ifname, macvlan->ifname, strerror(-r),
-                                        NETDEVIF(macvlan), NULL);
-                        link_enter_failed(link);
-                        return r;
-                }
-
-                link->enslaving ++;
-        }
-
-        HASHMAP_FOREACH(vxlan, link->network->vxlans, i) {
-                log_struct_link(LOG_DEBUG, link,
-                                "MESSAGE=%*s: enslaving by '%s'",
-                                IFNAMSIZ,
-                                link->ifname, vxlan->ifname, NETDEVIF(vxlan), NULL);
-
-                r = netdev_join(vxlan, link, &netdev_join_handler);
-                if (r < 0) {
-                        log_struct_link(LOG_WARNING, link,
-                                        "MESSAGE=%*s: could not join netdev '%s': %s",
-                                        IFNAMSIZ,
-                                        link->ifname, vxlan->ifname, strerror(-r),
-                                        NETDEVIF(vxlan), NULL);
+                                        link->ifname, netdev->ifname, strerror(-r),
+                                        NETDEVIF(netdev), NULL);
                         link_enter_failed(link);
                         return r;
                 }
diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf
index 852142f..3a58a40 100644
--- a/src/network/networkd-network-gperf.gperf
+++ b/src/network/networkd-network-gperf.gperf
@@ -27,9 +27,10 @@ Match.Architecture,          config_parse_net_condition,         CONDITION_ARCHI
 Network.Description,         config_parse_string,                0,                             offsetof(Network, description)
 Network.Bridge,              config_parse_netdev,                0,                             offsetof(Network, bridge)
 Network.Bond,                config_parse_netdev,                0,                             offsetof(Network, bond)
-Network.VLAN,                config_parse_netdev,                0,                             offsetof(Network, vlans)
-Network.MACVLAN,             config_parse_netdev,                0,                             offsetof(Network, macvlans)
-Network.VXLAN,               config_parse_netdev,                0,                             offsetof(Network, vxlans)
+Network.VLAN,                config_parse_netdev,                0,                             0
+Network.MACVLAN,             config_parse_netdev,                0,                             0
+Network.VXLAN,               config_parse_netdev,                0,                             0
+Network.Tunnel,              config_parse_tunnel,                0,                             0
 Network.DHCP,                config_parse_dhcp,                  0,                             offsetof(Network, dhcp)
 Network.DHCPServer,          config_parse_bool,                  0,                             offsetof(Network, dhcp_server)
 Network.IPv4LL,              config_parse_bool,                  0,                             offsetof(Network, ipv4ll)
@@ -38,7 +39,6 @@ Network.Address,             config_parse_address,               0,
 Network.Gateway,             config_parse_gateway,               0,                             0
 Network.DNS,                 config_parse_strv,                  0,                             offsetof(Network, dns)
 Network.NTP,                 config_parse_strv,                  0,                             offsetof(Network, ntp)
-Network.Tunnel,              config_parse_tunnel,                0,                             offsetof(Network, tunnel)
 Address.Address,             config_parse_address,               0,                             0
 Address.Peer,                config_parse_address,               0,                             0
 Address.Broadcast,           config_parse_broadcast,             0,                             0
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 84b6973..7e753e1 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -62,16 +62,8 @@ static int network_load_one(Manager *manager, const char *filename) {
         LIST_HEAD_INIT(network->static_addresses);
         LIST_HEAD_INIT(network->static_routes);
 
-        network->vlans = hashmap_new(string_hash_func, string_compare_func);
-        if (!network->vlans)
-                return log_oom();
-
-        network->macvlans = hashmap_new(string_hash_func, string_compare_func);
-        if (!network->macvlans)
-                return log_oom();
-
-        network->vxlans = hashmap_new(string_hash_func, string_compare_func);
-        if (!network->vxlans)
+        network->stacked_netdevs = hashmap_new(string_hash_func, string_compare_func);
+        if (!network->stacked_netdevs)
                 return log_oom();
 
         network->addresses_by_section = hashmap_new(uint64_hash_func, uint64_compare_func);
@@ -178,19 +170,9 @@ void network_free(Network *network) {
 
         netdev_unref(network->bond);
 
-        netdev_unref(network->tunnel);
-
-        HASHMAP_FOREACH(netdev, network->vlans, i)
-                netdev_unref(netdev);
-        hashmap_free(network->vlans);
-
-        HASHMAP_FOREACH(netdev, network->macvlans, i)
-                netdev_unref(netdev);
-        hashmap_free(network->macvlans);
-
-        HASHMAP_FOREACH(netdev, network->vxlans, i)
+        HASHMAP_FOREACH(netdev, network->stacked_netdevs, i)
                 netdev_unref(netdev);
-        hashmap_free(network->vxlans);
+        hashmap_free(network->stacked_netdevs);
 
         while ((route = network->static_routes))
                 route_free(route);
@@ -338,30 +320,12 @@ int config_parse_netdev(const char *unit,
 
                 break;
         case NETDEV_KIND_VLAN:
-                r = hashmap_put(network->vlans, netdev->ifname, netdev);
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                                   "Can not add VLAN '%s' to network: %s",
-                                   rvalue, strerror(-r));
-                        return 0;
-                }
-
-                break;
         case NETDEV_KIND_MACVLAN:
-                r = hashmap_put(network->macvlans, netdev->ifname, netdev);
-                if (r < 0) {
-                        log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                                   "Can not add MACVLAN '%s' to network: %s",
-                                   rvalue, strerror(-r));
-                        return 0;
-                }
-
-                break;
         case NETDEV_KIND_VXLAN:
-                r = hashmap_put(network->vxlans, netdev->ifname, netdev);
+                r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
                 if (r < 0) {
                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                                   "Can not add VXLAN '%s' to network: %s",
+                                   "Can not add VLAN '%s' to network: %s",
                                    rvalue, strerror(-r));
                         return 0;
                 }
@@ -411,7 +375,15 @@ int config_parse_tunnel(const char *unit,
                 return 0;
         }
 
-        network->tunnel = netdev;
+        r = hashmap_put(network->stacked_netdevs, netdev->ifname, netdev);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                           "Can not add VLAN '%s' to network: %s",
+                           rvalue, strerror(-r));
+                return 0;
+        }
+
+        netdev_ref(netdev);
 
         return 0;
 }
diff --git a/src/network/networkd.h b/src/network/networkd.h
index fe63cfb..bf73fe2 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -81,10 +81,7 @@ struct Network {
         char *description;
         NetDev *bridge;
         NetDev *bond;
-        NetDev *tunnel;
-        Hashmap *vlans;
-        Hashmap *macvlans;
-        Hashmap *vxlans;
+        Hashmap *stacked_netdevs;
         DHCPSupport dhcp;
         bool dhcp_dns;
         bool dhcp_ntp;

commit ae06ab1014641feb83ffd0d08f0957e69bbbae08
Author: Tom Gundersen <teg at jklm.no>
Date:   Mon Jul 28 11:39:37 2014 +0200

    networkd: store ifindex as int

diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index ac9f473..5eeeb3d 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -46,7 +46,6 @@ static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) {
         int r, ifindex;
 
         assert(manager);
-        assert(manager->links);
         assert(message);
         assert(ret);
 
@@ -82,17 +81,19 @@ static int link_new(Manager *manager, sd_rtnl_message *message, Link **ret) {
         if (r < 0)
                 log_debug_link(link, "MAC address not found for new device, continuing without");
 
-        r = asprintf(&link->state_file, "/run/systemd/netif/links/%"PRIu64,
-                     link->ifindex);
+        r = asprintf(&link->state_file, "/run/systemd/netif/links/%d", link->ifindex);
         if (r < 0)
                 return -ENOMEM;
 
-        r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%"PRIu64,
-                     link->ifindex);
+        r = asprintf(&link->lease_file, "/run/systemd/netif/leases/%d", link->ifindex);
         if (r < 0)
                 return -ENOMEM;
 
-        r = hashmap_put(manager->links, &link->ifindex, link);
+        r = hashmap_ensure_allocated(&manager->links, NULL, NULL);
+        if (r < 0)
+                return r;
+
+        r = hashmap_put(manager->links, INT_TO_PTR(link->ifindex), link);
         if (r < 0)
                 return r;
 
@@ -129,7 +130,7 @@ static void link_free(Link *link) {
         sd_icmp6_nd_unref(link->icmp6_router_discovery);
 
         if (link->manager)
-                hashmap_remove(link->manager->links, &link->ifindex);
+                hashmap_remove(link->manager->links, INT_TO_PTR(link->ifindex));
 
         free(link->ifname);
 
@@ -157,15 +158,12 @@ Link *link_ref(Link *link) {
 
 int link_get(Manager *m, int ifindex, Link **ret) {
         Link *link;
-        uint64_t ifindex_64;
 
         assert(m);
-        assert(m->links);
         assert(ifindex);
         assert(ret);
 
-        ifindex_64 = ifindex;
-        link = hashmap_get(m->links, &ifindex_64);
+        link = hashmap_get(m->links, INT_TO_PTR(ifindex));
         if (!link)
                 return -ENODEV;
 
@@ -2282,7 +2280,7 @@ int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
 
         link = *ret;
 
-        log_debug_link(link, "link %"PRIu64" added", link->ifindex);
+        log_debug_link(link, "link %d added", link->ifindex);
 
         r = sd_rtnl_message_new_addr(m->rtnl, &req, RTM_GETADDR, link->ifindex, 0);
         if (r < 0)
@@ -2296,7 +2294,7 @@ int link_add(Manager *m, sd_rtnl_message *message, Link **ret) {
 
         if (detect_container(NULL) <= 0) {
                 /* not in a container, udev will be around */
-                sprintf(ifindex_str, "n%"PRIu64, link->ifindex);
+                sprintf(ifindex_str, "n%d", link->ifindex);
                 device = udev_device_new_from_device_id(m->udev, ifindex_str);
                 if (!device) {
                         log_warning_link(link, "could not find udev device");
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index b0e3191..223cb2a 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -114,10 +114,6 @@ int manager_new(Manager **ret) {
                         return -ENOMEM;
         }
 
-        m->links = hashmap_new(uint64_hash_func, uint64_compare_func);
-        if (!m->links)
-                return -ENOMEM;
-
         m->netdevs = hashmap_new(string_hash_func, string_compare_func);
         if (!m->netdevs)
                 return -ENOMEM;
diff --git a/src/network/networkd.h b/src/network/networkd.h
index 138b82d..fe63cfb 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -173,7 +173,7 @@ struct Link {
 
         int n_ref;
 
-        uint64_t ifindex;
+        int ifindex;
         char *ifname;
         char *state_file;
         struct ether_addr mac;

commit 527503444ef24ae03c73cf85128c7acbb1146f3c
Author: Tom Gundersen <teg at jklm.no>
Date:   Sat Jul 26 19:12:24 2014 +0200

    sd-dhcp-server: add forcerenew support

diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h
index 7fe7253..cdaa471 100644
--- a/src/libsystemd-network/dhcp-server-internal.h
+++ b/src/libsystemd-network/dhcp-server-internal.h
@@ -39,6 +39,8 @@ typedef struct DHCPLease {
         DHCPClientId client_id;
 
         be32_t address;
+        be32_t gateway;
+        uint8_t chaddr[16];
         usec_t expiration;
 } DHCPLease;
 
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index bcf7d1f..99b833a 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -456,6 +456,39 @@ static int server_send_nak(sd_dhcp_server *server, DHCPRequest *req) {
         return 0;
 }
 
+static int server_send_forcerenew(sd_dhcp_server *server, be32_t address, be32_t gateway,
+                                  uint8_t chaddr[]) {
+        _cleanup_free_ DHCPPacket *packet = NULL;
+        size_t optoffset = 0;
+        int r;
+
+        assert(server);
+        assert(address != INADDR_ANY);
+        assert(chaddr);
+
+        packet = malloc0(sizeof(DHCPPacket) + DHCP_MIN_OPTIONS_SIZE);
+        if (!packet)
+                return -ENOMEM;
+
+        r = dhcp_message_init(&packet->dhcp, BOOTREPLY, 0,
+                              DHCP_FORCERENEW, DHCP_MIN_OPTIONS_SIZE,
+                              &optoffset);
+        if (r < 0)
+                return r;
+
+        r = dhcp_option_append(&packet->dhcp, DHCP_MIN_OPTIONS_SIZE,
+                               &optoffset, 0, DHCP_OPTION_END, 0, NULL);
+        if (r < 0)
+                return r;
+
+        memcpy(&packet->dhcp.chaddr, chaddr, ETH_ALEN);
+
+        r = dhcp_server_send_udp(server, address, &packet->dhcp,
+                                 sizeof(DHCPMessage) + optoffset);
+
+        return 0;
+}
+
 static int parse_request(uint8_t code, uint8_t len, const uint8_t *option,
                          void *user_data) {
         DHCPRequest *req = user_data;
@@ -709,6 +742,8 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
                                         return -ENOMEM;
                                 }
                                 lease->client_id.length = req->client_id.length;
+                                memcpy(&lease->chaddr, &req->message->chaddr, ETH_ALEN);
+                                lease->gateway = req->message->giaddr;
                         } else
                                 lease = existing_lease;
 
@@ -879,3 +914,28 @@ int sd_dhcp_server_start(sd_dhcp_server *server) {
 
         return 0;
 }
+
+int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {
+        unsigned i;
+        int r;
+
+        assert_return(server, -EINVAL);
+        assert(server->bound_leases);
+
+        for (i = 0; i < server->pool_size; i++) {
+                DHCPLease *lease = server->bound_leases[i];
+
+                if (!lease)
+                        continue;
+
+                r = server_send_forcerenew(server, lease->address,
+                                           lease->gateway,
+                                           lease->chaddr);
+                if (r < 0)
+                        return r;
+                else
+                        log_dhcp_server(server, "FORCERENEW");
+        }
+
+        return r;
+}
diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h
index 01595d3..a4f7c85 100644
--- a/src/systemd/sd-dhcp-server.h
+++ b/src/systemd/sd-dhcp-server.h
@@ -46,4 +46,6 @@ int sd_dhcp_server_stop(sd_dhcp_server *server);
 
 int sd_dhcp_server_set_address(sd_dhcp_server *server, struct in_addr *address);
 int sd_dhcp_server_set_lease_pool(sd_dhcp_server *server, struct in_addr *start, size_t size);
+
+int sd_dhcp_server_forcerenew(sd_dhcp_server *server);
 #endif

commit 615c1467c81411bf1d19fd7092e8995b5ebadc13
Author: Tom Gundersen <teg at jklm.no>
Date:   Fri May 16 00:50:44 2014 +0200

    sd-dhcp-client: add support for FORCERENEW
    
    This partially implements RFC3203. Note that we are not fully compliant as we do not
    support authentication.

diff --git a/src/libsystemd-network/dhcp-protocol.h b/src/libsystemd-network/dhcp-protocol.h
index 7c06b5a..f5119a7 100644
--- a/src/libsystemd-network/dhcp-protocol.h
+++ b/src/libsystemd-network/dhcp-protocol.h
@@ -95,6 +95,8 @@ enum {
         DHCP_ACK                                = 5,
         DHCP_NAK                                = 6,
         DHCP_RELEASE                            = 7,
+        DHCP_INFORM                             = 8,
+        DHCP_FORCERENEW                         = 9,
 };
 
 enum {
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 68bce5e..8205ad0 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -862,7 +862,6 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec,
                              void *userdata) {
         sd_dhcp_client *client = userdata;
         DHCP_CLIENT_DONT_DESTROY(client);
-        int r;
 
         client->state = DHCP_STATE_RENEWING;
         client->attempt = 1;
@@ -916,6 +915,19 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
         return 0;
 }
 
+static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force,
+                                    size_t len) {
+        int r;
+
+        r = dhcp_option_parse(force, len, NULL, NULL);
+        if (r != DHCP_FORCERENEW)
+                return -ENOMSG;
+
+        log_dhcp_client(client, "FORCERENEW");
+
+        return 0;
+}
+
 static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
                              size_t len) {
         _cleanup_dhcp_lease_unref_ sd_dhcp_lease *lease = NULL;
@@ -1226,9 +1238,20 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
 
                 break;
 
+        case DHCP_STATE_BOUND:
+                r = client_handle_forcerenew(client, message, len);
+                if (r >= 0) {
+                        r = client_timeout_t1(NULL, 0, client);
+                        if (r < 0)
+                                goto error;
+                } else if (r == -ENOMSG)
+                        /* invalid message, let's ignore it */
+                        return 0;
+
+                break;
+
         case DHCP_STATE_INIT:
         case DHCP_STATE_INIT_REBOOT:
-        case DHCP_STATE_BOUND:
 
                 break;
 
@@ -1285,13 +1308,6 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
                 return 0;
         }
 
-        if (be32toh(message->xid) != client->xid) {
-                log_dhcp_client(client, "received xid (%u) does not match "
-                                "expected (%u): ignoring",
-                                be32toh(message->xid), client->xid);
-                return 0;
-        }
-
         if (message->htype != ARPHRD_ETHER || message->hlen != ETHER_ADDR_LEN) {
                 log_dhcp_client(client, "not an ethernet packet");
                 return 0;
@@ -1304,6 +1320,16 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
                 return 0;
         }
 
+        if (client->state != DHCP_STATE_BOUND &&
+            be32toh(message->xid) != client->xid) {
+                /* in BOUND state, we may receive FORCERENEW with xid set by server,
+                   so ignore the xid in this case */
+                log_dhcp_client(client, "received xid (%u) does not match "
+                                "expected (%u): ignoring",
+                                be32toh(message->xid), client->xid);
+                return 0;
+        }
+
         return client_handle_message(client, message, len);
 }
 

commit 0af03ba57f43b973463e15949c2830cbd228f19d
Author: Tom Gundersen <teg at jklm.no>
Date:   Fri Jul 25 14:44:12 2014 +0200

    sd-dhcp-client: listen on UDP socket as soon as a lease is acquired
    
    This is necessary in order to listen for FORCERENEW events.

diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 1a60f44..68bce5e 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -731,8 +731,8 @@ error:
         return 0;
 }
 
-static int client_initialize_events(sd_dhcp_client *client,
-                                    sd_event_io_handler_t io_callback) {
+static int client_initialize_io_events(sd_dhcp_client *client,
+                                       sd_event_io_handler_t io_callback) {
         int r;
 
         assert(client);
@@ -749,6 +749,19 @@ static int client_initialize_events(sd_dhcp_client *client,
         if (r < 0)
                 goto error;
 
+error:
+        if (r < 0)
+                client_stop(client, r);
+
+        return 0;
+}
+
+static int client_initialize_time_events(sd_dhcp_client *client) {
+        int r;
+
+        assert(client);
+        assert(client->event);
+
         client->timeout_resend = sd_event_source_unref(client->timeout_resend);
 
         r = sd_event_add_time(client->event,
@@ -770,6 +783,14 @@ error:
 
 }
 
+static int client_initialize_events(sd_dhcp_client *client,
+                                    sd_event_io_handler_t io_callback) {
+        client_initialize_io_events(client, io_callback);
+        client_initialize_time_events(client);
+
+        return 0;
+}
+
 static int client_start(sd_dhcp_client *client) {
         int r;
 
@@ -846,16 +867,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec,
         client->state = DHCP_STATE_RENEWING;
         client->attempt = 1;
 
-        r = dhcp_network_bind_udp_socket(client->lease->address,
-                                         DHCP_PORT_CLIENT);
-        if (r < 0) {
-                log_dhcp_client(client, "could not bind UDP socket");
-                return 0;
-        }
-
-        client->fd = r;
-
-        return client_initialize_events(client, client_receive_message_udp);
+        return client_initialize_time_events(client);
 }
 
 static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
@@ -1175,15 +1187,23 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
                         if (r < 0)
                                 goto error;
 
+                        r = dhcp_network_bind_udp_socket(client->lease->address,
+                                                         DHCP_PORT_CLIENT);
+                        if (r < 0) {
+                                log_dhcp_client(client, "could not bind UDP socket");
+                                goto error;
+                        }
+
+                        client->fd = r;
+
+                        client_initialize_io_events(client, client_receive_message_udp);
+
                         if (notify_event) {
                                 client_notify(client, notify_event);
                                 if (client->state == DHCP_STATE_STOPPED)
                                         return 0;
                         }
 
-                        client->receive_message =
-                                sd_event_source_unref(client->receive_message);
-                        client->fd = asynchronous_close(client->fd);
                 } else if (r == -EADDRNOTAVAIL) {
                         /* got a NAK, let's restart the client */
                         client->timeout_resend =

commit 076adf013a171e819f84684e2eb22e965e96ee59
Author: Tom Gundersen <teg at jklm.no>
Date:   Fri Jul 25 14:43:16 2014 +0200

    dhcp-network: enable IP_FREEBIND for UDP sockets
    
    This allows the sockets to be bound to a specific address before it is configured,
    also enable SO_REUSEADDR to allow multiple DHCP clients to run at the same time.

diff --git a/src/libsystemd-network/dhcp-network.c b/src/libsystemd-network/dhcp-network.c
index 16411cc..29276c0 100644
--- a/src/libsystemd-network/dhcp-network.c
+++ b/src/libsystemd-network/dhcp-network.c
@@ -126,7 +126,7 @@ int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
                 .in.sin_addr.s_addr = address,
         };
         _cleanup_close_ int s = -1;
-        int r, tos = IPTOS_CLASS_CS6;
+        int r, on = 1, tos = IPTOS_CLASS_CS6;
 
         s = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
         if (s < 0)
@@ -136,13 +136,11 @@ int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
         if (r < 0)
                 return -errno;
 
-        if (address == INADDR_ANY) {
-                int on = 1;
-
-                r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
-                if (r < 0)
-                        return -errno;
+        r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+        if (r < 0)
+                return -errno;
 
+        if (address == INADDR_ANY) {
                 r = setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
                 if (r < 0)
                         return -errno;
@@ -150,6 +148,10 @@ int dhcp_network_bind_udp_socket(be32_t address, uint16_t port) {
                 r = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
                 if (r < 0)
                         return -errno;
+        } else {
+                r = setsockopt(s, IPPROTO_IP, IP_FREEBIND, &on, sizeof(on));
+                if (r < 0)
+                        return -errno;
         }
 
         r = bind(s, &src.sa, sizeof(src.in));

commit 2d2349cc3ed43153344807892332c9fa626c8d8a
Author: Tom Gundersen <teg at jklm.no>
Date:   Sat May 17 21:23:20 2014 +0200

    sd-dhcp-client: drop event DHCP_EVENT_NO_LEASE
    
    Keep this internal to the client and simply restart it when NAK is receieved, as
    per the RFC.

diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 64c67b4..1a60f44 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -276,19 +276,10 @@ static void client_stop(sd_dhcp_client *client, int error) {
 
         if (error < 0)
                 log_dhcp_client(client, "STOPPED: %s", strerror(-error));
-        else {
-                switch(error) {
-                case DHCP_EVENT_STOP:
-                        log_dhcp_client(client, "STOPPED");
-                        break;
-                case DHCP_EVENT_NO_LEASE:
-                        log_dhcp_client(client, "STOPPED: No lease");
-                        break;
-                default:
-                        log_dhcp_client(client, "STOPPED: Unknown reason");
-                        break;
-                }
-        }
+        else if (error == DHCP_EVENT_STOP)
+                log_dhcp_client(client, "STOPPED");
+        else
+                log_dhcp_client(client, "STOPPED: Unknown event");
 
         client_notify(client, error);
 
@@ -925,7 +916,7 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
         r = dhcp_option_parse(ack, len, dhcp_lease_parse_options, lease);
         if (r == DHCP_NAK) {
                 log_dhcp_client(client, "NAK");
-                return DHCP_EVENT_NO_LEASE;
+                return -EADDRNOTAVAIL;
         }
 
         if (r != DHCP_ACK) {
@@ -1165,25 +1156,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
         case DHCP_STATE_REBINDING:
 
                 r = client_handle_ack(client, message, len);
-                if (r == DHCP_EVENT_NO_LEASE) {
-
-                        client->timeout_resend =
-                                sd_event_source_unref(client->timeout_resend);
-
-                        if (client->state == DHCP_STATE_REBOOTING) {
-                                r = client_initialize(client);
-                                if (r < 0)
-                                        goto error;
-
-                                r = client_start(client);
-                                if (r < 0)
-                                        goto error;
-
-                                log_dhcp_client(client, "REBOOTED");
-                        }
-
-                        goto error;
-                } else if (r >= 0) {
+                if (r >= 0) {
                         client->timeout_resend =
                                 sd_event_source_unref(client->timeout_resend);
 
@@ -1211,6 +1184,22 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
                         client->receive_message =
                                 sd_event_source_unref(client->receive_message);
                         client->fd = asynchronous_close(client->fd);
+                } else if (r == -EADDRNOTAVAIL) {
+                        /* got a NAK, let's restart the client */
+                        client->timeout_resend =
+                                sd_event_source_unref(client->timeout_resend);
+
+                        r = client_initialize(client);
+                        if (r < 0)
+                                goto error;
+
+                        r = client_start(client);
+                        if (r < 0)
+                                goto error;
+
+                        log_dhcp_client(client, "REBOOTED");
+
+                        return 0;
                 } else if (r == -ENOMSG)
                         /* invalid message, let's ignore it */
                         return 0;
@@ -1229,7 +1218,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
         }
 
 error:
-        if (r < 0 || r == DHCP_EVENT_NO_LEASE)
+        if (r < 0)
                 client_stop(client, r);
 
         return r;
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index c346df4..ac9f473 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1172,9 +1172,6 @@ static void dhcp_handler(sd_dhcp_client *client, int event, void *userdata) {
                 return;
 
         switch (event) {
-                case DHCP_EVENT_NO_LEASE:
-                        log_debug_link(link, "IP address in use.");
-                        break;
                 case DHCP_EVENT_EXPIRED:
                 case DHCP_EVENT_STOP:
                 case DHCP_EVENT_IP_CHANGE:
diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h
index 08aa0dc..36b8710 100644
--- a/src/systemd/sd-dhcp-client.h
+++ b/src/systemd/sd-dhcp-client.h
@@ -30,11 +30,10 @@
 
 enum {
         DHCP_EVENT_STOP                         = 0,
-        DHCP_EVENT_NO_LEASE                     = 1,
-        DHCP_EVENT_IP_ACQUIRE                   = 2,
-        DHCP_EVENT_IP_CHANGE                    = 3,
-        DHCP_EVENT_EXPIRED                      = 4,
-        DHCP_EVENT_RENEW                        = 5,
+        DHCP_EVENT_IP_ACQUIRE                   = 1,
+        DHCP_EVENT_IP_CHANGE                    = 2,
+        DHCP_EVENT_EXPIRED                      = 3,
+        DHCP_EVENT_RENEW                        = 4,
 };
 
 typedef struct sd_dhcp_client sd_dhcp_client;

commit 9fbc25232c123aac886b5327418b7254a48ea3dc
Author: Tom Gundersen <teg at jklm.no>
Date:   Sat Jul 26 17:53:33 2014 +0200

    sd-dhcp-client: only verify UDP messages
    
    RAW messages are verified by the BPF in the kernel.

diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index e622564..64c67b4 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -1129,35 +1129,6 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message,
         assert(client->event);
         assert(message);
 
-        if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
-                log_dhcp_client(client, "not a DHCP message: ignoring");
-                return 0;
-        }
-
-        if (message->op != BOOTREPLY) {
-                log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
-                return 0;
-        }
-
-        if (be32toh(message->xid) != client->xid) {
-                log_dhcp_client(client, "received xid (%u) does not match "
-                                "expected (%u): ignoring",
-                                be32toh(message->xid), client->xid);
-                return 0;
-        }
-
-        if (message->htype != ARPHRD_ETHER || message->hlen != ETHER_ADDR_LEN) {
-                log_dhcp_client(client, "not an ethernet packet");
-                return 0;
-        }
-
-        if (memcmp(&message->chaddr[0], &client->client_id.mac_addr,
-                   ETH_ALEN)) {
-                log_dhcp_client(client, "received chaddr does not match "
-                                "expected: ignoring");
-                return 0;
-        }
-
         switch (client->state) {
         case DHCP_STATE_SELECTING:
 
@@ -1290,8 +1261,39 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
                 log_dhcp_client(client, "could not receive message from UDP "
                                 "socket: %m");
                 return 0;
-        } else if ((size_t)len < sizeof(DHCPMessage))
+        } else if ((size_t)len < sizeof(DHCPMessage)) {
+                log_dhcp_client(client, "too small to be a DHCP message: ignoring");
                 return 0;
+        }
+
+        if (be32toh(message->magic) != DHCP_MAGIC_COOKIE) {
+                log_dhcp_client(client, "not a DHCP message: ignoring");
+                return 0;
+        }
+
+        if (message->op != BOOTREPLY) {
+                log_dhcp_client(client, "not a BOOTREPLY message: ignoring");
+                return 0;
+        }
+
+        if (be32toh(message->xid) != client->xid) {
+                log_dhcp_client(client, "received xid (%u) does not match "
+                                "expected (%u): ignoring",
+                                be32toh(message->xid), client->xid);
+                return 0;
+        }
+
+        if (message->htype != ARPHRD_ETHER || message->hlen != ETHER_ADDR_LEN) {
+                log_dhcp_client(client, "not an ethernet packet");
+                return 0;
+        }
+
+        if (memcmp(&message->chaddr[0], &client->client_id.mac_addr,
+                   ETH_ALEN)) {
+                log_dhcp_client(client, "received chaddr does not match "
+                                "expected: ignoring");
+                return 0;
+        }
 
         return client_handle_message(client, message, len);
 }



More information about the systemd-commits mailing list