[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