#include "networkd.h"
#include "networkd-address-pool.h"
+#include "set.h"
int address_pool_new(
Manager *m,
HASHMAP_FOREACH(l, p->manager->links, i) {
Address *a;
+ Iterator j;
/* Don't clash with assigned addresses */
- LIST_FOREACH(addresses, a, l->addresses) {
+ SET_FOREACH(a, l->addresses, j) {
if (a->family != p->family)
continue;
UINT_TO_PTR(address->section));
}
+ if (address->link)
+ set_remove(address->link->addresses, address);
+
free(address);
}
return address_compare_func(a1, a2) == 0;
}
+int address_add(Link *link, Address *address) {
+ int r;
+
+ assert(link);
+ assert(address);
+
+ r = set_ensure_allocated(&link->addresses, &address_hash_ops);
+ if (r < 0)
+ return r;
+
+ r = set_put(link->addresses, address);
+ if (r < 0)
+ return r;
+
+ address->link = link;
+
+ return 0;
+}
+
+int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
+ Address address = {}, *existing;
+
+ assert(link);
+ assert(in_addr);
+ assert(ret);
+
+ address.family = family;
+ address.in_addr = *in_addr;
+ address.prefixlen = prefixlen;
+
+ existing = set_get(link->addresses, &address);
+ if (!existing)
+ return -ENOENT;
+
+ *ret = existing;
+
+ return 0;
+}
+
int address_establish(Address *address, Link *link) {
bool masq;
int r;
Network *network;
unsigned section;
+ Link *link;
+
int family;
unsigned char prefixlen;
unsigned char scope;
int address_new_static(Network *network, unsigned section, Address **ret);
int address_new(Address **ret);
void address_free(Address *address);
+int address_add(Link *link, Address *address);
+int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
int address_configure(Address *address, Link *link, sd_netlink_message_handler_t callback);
int address_update(Address *address, Link *link, sd_netlink_message_handler_t callback);
int address_drop(Address *address, Link *link, sd_netlink_message_handler_t callback);
#include <linux/if.h>
#include <unistd.h>
-#include "util.h"
-#include "virt.h"
-#include "fileio.h"
-#include "socket-util.h"
#include "bus-util.h"
-#include "udev-util.h"
-#include "netlink-util.h"
#include "dhcp-lease-internal.h"
+#include "fileio.h"
+#include "netlink-util.h"
#include "network-internal.h"
+#include "set.h"
+#include "socket-util.h"
+#include "udev-util.h"
+#include "util.h"
+#include "virt.h"
#include "networkd-link.h"
#include "networkd-netdev.h"
if (!link)
return;
- while ((address = link->addresses)) {
- LIST_REMOVE(addresses, link->addresses, address);
- address_free(address);
- }
+ while (!set_isempty(link->addresses))
+ address_free(set_first(link->addresses));
+
+ set_free(link->addresses);
while ((address = link->pool_addresses)) {
LIST_REMOVE(addresses, link->pool_addresses, address);
return 0;
}
-Address* link_get_equal_address(Link *link, Address *needle) {
- Address *i;
-
- assert(link);
- assert(needle);
-
- LIST_FOREACH(addresses, i, link->addresses)
- if (address_equal(i, needle))
- return i;
-
- return NULL;
-}
-
int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
Link *link;
_cleanup_udev_device_unref_ struct udev_device *device = NULL;
else if (link_has_carrier(link)) {
Address *address;
uint8_t scope = RT_SCOPE_NOWHERE;
+ Iterator i;
/* if we have carrier, check what addresses we have */
- LIST_FOREACH(addresses, address, link->addresses) {
+ SET_FOREACH(address, link->addresses, i) {
if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
continue;
unsigned link_messages;
unsigned enslaving;
- LIST_HEAD(Address, addresses);
+ Set *addresses;
sd_dhcp_client *dhcp_client;
sd_dhcp_lease *dhcp_lease;
int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
void link_drop(Link *link);
-Address *link_get_equal_address(Link *link, Address *address);
-
int link_address_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
int link_route_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
uint16_t type;
_cleanup_address_free_ Address *address = NULL;
unsigned char flags;
- Address *existing;
+ Address *existing = NULL;
char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
const char *valid_str = NULL;
int r, ifindex;
USEC_PER_SEC);
}
- existing = link_get_equal_address(link, address);
+ address_get(link, address->family, &address->in_addr, address->prefixlen, &existing);
switch (type) {
case RTM_NEWADDR:
existing->cinfo = address->cinfo;
} else {
- log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
+ r = address_add(link, address);
+ if (r < 0) {
+ log_link_warning_errno(link, r, "Failed to add address %s/%u: %m", buf, address->prefixlen);
+ return 0;
+ } else
+ log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
+
- LIST_PREPEND(addresses, link->addresses, address);
address_establish(address, link);
address = NULL;
if (existing) {
log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
address_release(existing, link);
- LIST_REMOVE(addresses, link->addresses, existing);
address_free(existing);
} else
log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);