Merge pull request #1530 from teg/network-fixes-2

networkd/libsystemd-network: collection of trivial patches v2
This commit is contained in:
Lennart Poettering 2015-10-14 12:15:09 +02:00
commit 9ea79b459e
23 changed files with 618 additions and 384 deletions

View file

@ -1265,8 +1265,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
return r;
log_dhcp_client(client, "lease expires in %s",
format_timespan(time_string, FORMAT_TIMESPAN_MAX,
lifetime_timeout - time_now, 0));
format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_timeout - time_now, USEC_PER_SEC));
/* don't arm earlier timeouts if this has already expired */
if (lifetime_timeout <= time_now)
@ -1292,8 +1291,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
return r;
log_dhcp_client(client, "T2 expires in %s",
format_timespan(time_string, FORMAT_TIMESPAN_MAX,
t2_timeout - time_now, 0));
format_timespan(time_string, FORMAT_TIMESPAN_MAX, t2_timeout - time_now, USEC_PER_SEC));
/* don't arm earlier timeout if this has already expired */
if (t2_timeout <= time_now)
@ -1318,8 +1316,7 @@ static int client_set_lease_timeouts(sd_dhcp_client *client) {
return r;
log_dhcp_client(client, "T1 expires in %s",
format_timespan(time_string, FORMAT_TIMESPAN_MAX,
t1_timeout - time_now, 0));
format_timespan(time_string, FORMAT_TIMESPAN_MAX, t1_timeout - time_now, USEC_PER_SEC));
return 0;
}

View file

@ -595,8 +595,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
}
log_dhcp6_client(client, "Next retransmission in %s",
format_timespan(time_string, FORMAT_TIMESPAN_MAX,
client->retransmit_time, 0));
format_timespan(time_string, FORMAT_TIMESPAN_MAX, client->retransmit_time, USEC_PER_SEC));
r = sd_event_add_time(client->event, &client->timeout_resend,
clock_boottime_or_monotonic(),
@ -1048,9 +1047,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t1) * USEC_PER_SEC);
log_dhcp6_client(client, "T1 expires in %s",
format_timespan(time_string,
FORMAT_TIMESPAN_MAX,
timeout, 0));
format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
r = sd_event_add_time(client->event,
&client->lease->ia.timeout_t1,
@ -1072,9 +1069,7 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
timeout = client_timeout_compute_random(be32toh(client->lease->ia.lifetime_t2) * USEC_PER_SEC);
log_dhcp6_client(client, "T2 expires in %s",
format_timespan(time_string,
FORMAT_TIMESPAN_MAX,
timeout, 0));
format_timespan(time_string, FORMAT_TIMESPAN_MAX, timeout, USEC_PER_SEC));
r = sd_event_add_time(client->event,
&client->lease->ia.timeout_t2,

View file

@ -444,8 +444,7 @@ static int icmp6_ra_prefix_update(sd_icmp6_nd *nd, ssize_t len,
log_icmp6_nd(nd, "New prefix "SD_ICMP6_ND_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
SD_ICMP6_ND_ADDRESS_FORMAT_VAL(prefix->addr),
prefix->len, lifetime,
format_timespan(time_string, FORMAT_TIMESPAN_MAX,
lifetime * USEC_PER_SEC, 0));
format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime * USEC_PER_SEC, USEC_PER_SEC));
LIST_PREPEND(prefixes, nd->prefixes, prefix);
@ -466,8 +465,7 @@ static int icmp6_ra_prefix_update(sd_icmp6_nd *nd, ssize_t len,
log_icmp6_nd(nd, "Update prefix "SD_ICMP6_ND_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
SD_ICMP6_ND_ADDRESS_FORMAT_VAL(prefix->addr),
prefix->len, lifetime,
format_timespan(time_string, FORMAT_TIMESPAN_MAX,
lifetime * USEC_PER_SEC, 0));
format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime * USEC_PER_SEC, USEC_PER_SEC));
}
r = icmp6_ra_prefix_set_timeout(nd, prefix, lifetime * USEC_PER_SEC);

View file

@ -25,6 +25,7 @@
#include <arpa/inet.h>
#include "event-util.h"
#include "in-addr-util.h"
#include "list.h"
#include "random-util.h"
#include "refcnt.h"
@ -232,6 +233,39 @@ bool sd_ipv4ll_is_running(sd_ipv4ll *ll) {
return sd_ipv4acd_is_running(ll->acd);
}
static bool ipv4ll_address_is_valid(const struct in_addr *address) {
uint32_t addr;
assert(address);
if (!in_addr_is_link_local(AF_INET, (const union in_addr_union *) address))
return false;
addr = be32toh(address->s_addr);
if ((addr & 0x0000FF00) == 0x0000 ||
(addr & 0x0000FF00) == 0xFF00)
return false;
return true;
}
int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address) {
int r;
assert_return(ll, -EINVAL);
assert_return(address, -EINVAL);
assert_return(ipv4ll_address_is_valid(address), -EINVAL);
r = sd_ipv4acd_set_address(ll->acd, address);
if (r < 0)
return r;
ll->address = address->s_addr;
return 0;
}
static int ipv4ll_pick_address(sd_ipv4ll *ll) {
struct in_addr in_addr;
be32_t addr;
@ -247,18 +281,15 @@ static int ipv4ll_pick_address(sd_ipv4ll *ll) {
return r;
addr = htonl((random & 0x0000FFFF) | IPV4LL_NETWORK);
} while (addr == ll->address ||
(ntohl(addr) & IPV4LL_NETMASK) != IPV4LL_NETWORK ||
(ntohl(addr) & 0x0000FF00) == 0x0000 ||
(ntohl(addr) & 0x0000FF00) == 0xFF00);
in_addr.s_addr = addr;
r = sd_ipv4acd_set_address(ll->acd, &in_addr);
r = sd_ipv4ll_set_address(ll, &in_addr);
if (r < 0)
return r;
ll->address = addr;
return 0;
}

View file

@ -100,6 +100,7 @@ int arp_network_bind_raw_socket(int index, be32_t address, const struct ether_ad
}
static void test_public_api_setters(sd_event *e) {
struct in_addr address = {};
unsigned seed = 0;
sd_ipv4ll *ll;
struct ether_addr mac_addr = {
@ -118,6 +119,16 @@ static void test_public_api_setters(sd_event *e) {
assert_se(sd_ipv4ll_set_callback(NULL, NULL, NULL) == -EINVAL);
assert_se(sd_ipv4ll_set_callback(ll, NULL, NULL) == 0);
assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
address.s_addr |= htobe32(169U << 24 | 254U << 16);
assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
address.s_addr |= htobe32(0x00FF);
assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
address.s_addr |= htobe32(0xF000);
assert_se(sd_ipv4ll_set_address(ll, &address) == 0);
address.s_addr |= htobe32(0x0F00);
assert_se(sd_ipv4ll_set_address(ll, &address) == -EINVAL);
assert_se(sd_ipv4ll_set_address_seed(NULL, seed) == -EINVAL);
assert_se(sd_ipv4ll_set_address_seed(ll, seed) == 0);

View file

@ -99,6 +99,66 @@ int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family) {
return 0;
}
int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol) {
struct rtmsg *rtm;
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
assert_return(protocol, -EINVAL);
rtm = NLMSG_DATA(m->hdr);
*protocol = rtm->rtm_protocol;
return 0;
}
int sd_rtnl_message_route_get_scope(sd_netlink_message *m, unsigned char *scope) {
struct rtmsg *rtm;
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
assert_return(scope, -EINVAL);
rtm = NLMSG_DATA(m->hdr);
*scope = rtm->rtm_scope;
return 0;
}
int sd_rtnl_message_route_get_tos(sd_netlink_message *m, unsigned char *tos) {
struct rtmsg *rtm;
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
assert_return(tos, -EINVAL);
rtm = NLMSG_DATA(m->hdr);
*tos = rtm->rtm_tos;
return 0;
}
int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table) {
struct rtmsg *rtm;
assert_return(m, -EINVAL);
assert_return(m->hdr, -EINVAL);
assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
assert_return(table, -EINVAL);
rtm = NLMSG_DATA(m->hdr);
*table = rtm->rtm_table;
return 0;
}
int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char *dst_len) {
struct rtmsg *rtm;

View file

@ -856,8 +856,6 @@ int sd_netlink_add_match(sd_netlink *rtnl,
switch (type) {
case RTM_NEWLINK:
case RTM_SETLINK:
case RTM_GETLINK:
case RTM_DELLINK:
r = socket_join_broadcast_group(rtnl, RTNLGRP_LINK);
if (r < 0)
@ -865,7 +863,6 @@ int sd_netlink_add_match(sd_netlink *rtnl,
break;
case RTM_NEWADDR:
case RTM_GETADDR:
case RTM_DELADDR:
r = socket_join_broadcast_group(rtnl, RTNLGRP_IPV4_IFADDR);
if (r < 0)
@ -876,6 +873,16 @@ int sd_netlink_add_match(sd_netlink *rtnl,
return r;
break;
case RTM_NEWROUTE:
case RTM_DELROUTE:
r = socket_join_broadcast_group(rtnl, RTNLGRP_IPV4_ROUTE);
if (r < 0)
return r;
r = socket_join_broadcast_group(rtnl, RTNLGRP_IPV6_ROUTE);
if (r < 0)
return r;
break;
default:
return -EOPNOTSUPP;
}

View file

@ -21,6 +21,7 @@
#include "networkd.h"
#include "networkd-address-pool.h"
#include "set.h"
int address_pool_new(
Manager *m,
@ -96,9 +97,10 @@ static bool address_pool_prefix_is_taken(
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;

View file

@ -21,26 +21,37 @@
#include <net/if.h>
#include "utf8.h"
#include "util.h"
#include "conf-parser.h"
#include "firewall-util.h"
#include "netlink-util.h"
#include "set.h"
#include "utf8.h"
#include "util.h"
#include "networkd.h"
#include "networkd-address.h"
static void address_init(Address *address) {
assert(address);
int address_new(Address **ret) {
_cleanup_address_free_ Address *address = NULL;
address = new0(Address, 1);
if (!address)
return -ENOMEM;
address->family = AF_UNSPEC;
address->scope = RT_SCOPE_UNIVERSE;
address->cinfo.ifa_prefered = CACHE_INFO_INFINITY_LIFE_TIME;
address->cinfo.ifa_valid = CACHE_INFO_INFINITY_LIFE_TIME;
*ret = address;
address = NULL;
return 0;
}
int address_new_static(Network *network, unsigned section, Address **ret) {
_cleanup_address_free_ Address *address = NULL;
int r;
if (section) {
address = hashmap_get(network->addresses_by_section, UINT_TO_PTR(section));
@ -52,11 +63,9 @@ int address_new_static(Network *network, unsigned section, Address **ret) {
}
}
address = new0(Address, 1);
if (!address)
return -ENOMEM;
address_init(address);
r = address_new(&address);
if (r < 0)
return r;
address->network = network;
@ -74,21 +83,6 @@ int address_new_static(Network *network, unsigned section, Address **ret) {
return 0;
}
int address_new_dynamic(Address **ret) {
_cleanup_address_free_ Address *address = NULL;
address = new0(Address, 1);
if (!address)
return -ENOMEM;
address_init(address);
*ret = address;
address = NULL;
return 0;
}
void address_free(Address *address) {
if (!address)
return;
@ -101,10 +95,110 @@ void address_free(Address *address) {
UINT_TO_PTR(address->section));
}
if (address->link)
set_remove(address->link->addresses, address);
free(address);
}
int address_establish(Address *address, Link *link) {
static void address_hash_func(const void *b, struct siphash *state) {
const Address *a = b;
assert(a);
siphash24_compress(&a->family, sizeof(a->family), state);
switch (a->family) {
case AF_INET:
siphash24_compress(&a->prefixlen, sizeof(a->prefixlen), state);
/* peer prefix */
if (a->prefixlen != 0) {
uint32_t prefix;
if (a->in_addr_peer.in.s_addr != 0)
prefix = be32toh(a->in_addr_peer.in.s_addr) >> (32 - a->prefixlen);
else
prefix = be32toh(a->in_addr.in.s_addr) >> (32 - a->prefixlen);
siphash24_compress(&prefix, sizeof(prefix), state);
}
/* fallthrough */
case AF_INET6:
/* local address */
siphash24_compress(&a->in_addr, FAMILY_ADDRESS_SIZE(a->family), state);
break;
default:
/* treat any other address family as AF_UNSPEC */
break;
}
}
static int address_compare_func(const void *c1, const void *c2) {
const Address *a1 = c1, *a2 = c2;
if (a1->family < a2->family)
return -1;
if (a1->family > a2->family)
return 1;
switch (a1->family) {
/* use the same notion of equality as the kernel does */
case AF_INET:
if (a1->prefixlen < a2->prefixlen)
return -1;
if (a1->prefixlen > a2->prefixlen)
return 1;
/* compare the peer prefixes */
if (a1->prefixlen != 0) {
/* make sure we don't try to shift by 32.
* See ISO/IEC 9899:TC3 § 6.5.7.3. */
uint32_t b1, b2;
if (a1->in_addr_peer.in.s_addr != 0)
b1 = be32toh(a1->in_addr_peer.in.s_addr) >> (32 - a1->prefixlen);
else
b1 = be32toh(a1->in_addr.in.s_addr) >> (32 - a1->prefixlen);
if (a2->in_addr_peer.in.s_addr != 0)
b2 = be32toh(a2->in_addr_peer.in.s_addr) >> (32 - a1->prefixlen);
else
b2 = be32toh(a2->in_addr.in.s_addr) >> (32 - a1->prefixlen);
if (b1 < b2)
return -1;
if (b1 > b2)
return 1;
}
/* fall-through */
case AF_INET6:
return memcmp(&a1->in_addr, &a2->in_addr, FAMILY_ADDRESS_SIZE(a1->family));
default:
/* treat any other address family as AF_UNSPEC */
return 0;
}
}
static const struct hash_ops address_hash_ops = {
.hash = address_hash_func,
.compare = address_compare_func
};
bool address_equal(Address *a1, Address *a2) {
if (a1 == a2)
return true;
if (!a1 || !a2)
return false;
return address_compare_func(a1, a2) == 0;
}
static int address_establish(Address *address, Link *link) {
bool masq;
int r;
@ -131,7 +225,43 @@ int address_establish(Address *address, Link *link) {
return 0;
}
int address_release(Address *address, Link *link) {
int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret) {
_cleanup_address_free_ Address *address = NULL;
int r;
assert(link);
assert(in_addr);
assert(ret);
r = address_new(&address);
if (r < 0)
return r;
address->family = family;
address->in_addr = *in_addr;
address->prefixlen = prefixlen;
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;
r = address_establish(address, link);
if (r < 0)
return r;
*ret = address;
address = NULL;
return 0;
}
static int address_release(Address *address, Link *link) {
int r;
assert(address);
@ -152,7 +282,36 @@ int address_release(Address *address, Link *link) {
return 0;
}
int address_drop(Address *address, Link *link,
int address_drop(Address *address) {
assert(address);
address_release(address, address->link);
address_free(address);
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_remove(Address *address, Link *link,
sd_netlink_message_handler_t callback) {
_cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
int r;
@ -292,7 +451,7 @@ static int address_acquire(Link *link, Address *original, Address **ret) {
} else if (original->family == AF_INET6)
in_addr.in6.s6_addr[15] |= 1;
r = address_new_dynamic(&na);
r = address_new(&na);
if (r < 0)
return r;
@ -580,49 +739,8 @@ int config_parse_label(const char *unit,
return 0;
}
bool address_equal(Address *a1, Address *a2) {
/* same object */
if (a1 == a2)
return true;
bool address_is_ready(const Address *a) {
assert(a);
/* one, but not both, is NULL */
if (!a1 || !a2)
return false;
if (a1->family != a2->family)
return false;
switch (a1->family) {
/* use the same notion of equality as the kernel does */
case AF_UNSPEC:
return true;
case AF_INET:
if (a1->prefixlen != a2->prefixlen)
return false;
else if (a1->prefixlen == 0)
/* make sure we don't try to shift by 32.
* See ISO/IEC 9899:TC3 § 6.5.7.3. */
return true;
else {
uint32_t b1, b2;
b1 = be32toh(a1->in_addr.in.s_addr);
b2 = be32toh(a2->in_addr.in.s_addr);
return (b1 >> (32 - a1->prefixlen)) == (b2 >> (32 - a1->prefixlen));
}
case AF_INET6: {
uint64_t *b1, *b2;
b1 = (uint64_t*)&a1->in_addr.in6;
b2 = (uint64_t*)&a2->in_addr.in6;
return (((b1[0] ^ b2[0]) | (b1[1] ^ b2[1])) == 0UL);
}
default:
assert_not_reached("Invalid address family");
}
return !(a->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED));
}

View file

@ -38,6 +38,8 @@ struct Address {
Network *network;
unsigned section;
Link *link;
int family;
unsigned char prefixlen;
unsigned char scope;
@ -56,14 +58,16 @@ struct Address {
};
int address_new_static(Network *network, unsigned section, Address **ret);
int address_new_dynamic(Address **ret);
int address_new(Address **ret);
void address_free(Address *address);
int address_add(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
int address_get(Link *link, int family, const union in_addr_union *in_addr, unsigned char prefixlen, Address **ret);
int address_drop(Address *address);
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);
int address_establish(Address *address, Link *link);
int address_release(Address *address, Link *link);
int address_remove(Address *address, Link *link, sd_netlink_message_handler_t callback);
bool address_equal(Address *a1, Address *a2);
bool address_is_ready(const Address *a);
DEFINE_TRIVIAL_CLEANUP_FUNC(Address*, address_free);
#define _cleanup_address_free_ _cleanup_(address_freep)

View file

@ -72,11 +72,11 @@ static int link_set_dhcp_routes(Link *link) {
if (r < 0)
return log_link_warning_errno(link, r, "DHCP error: could not get address: %m");
r = route_new_dynamic(&route, RTPROT_DHCP);
r = route_new(&route, RTPROT_DHCP);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate route: %m");
r = route_new_dynamic(&route_gw, RTPROT_DHCP);
r = route_new(&route_gw, RTPROT_DHCP);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate route: %m");
@ -120,7 +120,7 @@ static int link_set_dhcp_routes(Link *link) {
for (i = 0; i < n; i++) {
_cleanup_route_free_ Route *route = NULL;
r = route_new_dynamic(&route, RTPROT_DHCP);
r = route_new(&route, RTPROT_DHCP);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate route: %m");
@ -162,45 +162,45 @@ static int dhcp_lease_lost(Link *link) {
for (i = 0; i < n; i++) {
_cleanup_route_free_ Route *route = NULL;
r = route_new_dynamic(&route, RTPROT_UNSPEC);
r = route_new(&route, RTPROT_UNSPEC);
if (r >= 0) {
route->family = AF_INET;
route->in_addr.in = routes[i].gw_addr;
route->dst_addr.in = routes[i].dst_addr;
route->dst_prefixlen = routes[i].dst_prefixlen;
route_drop(route, link,
&link_route_drop_handler);
route_remove(route, link,
&link_route_remove_handler);
}
}
}
}
r = address_new_dynamic(&address);
r = address_new(&address);
if (r >= 0) {
r = sd_dhcp_lease_get_router(link->dhcp_lease, &gateway);
if (r >= 0) {
_cleanup_route_free_ Route *route_gw = NULL;
_cleanup_route_free_ Route *route = NULL;
r = route_new_dynamic(&route_gw, RTPROT_UNSPEC);
r = route_new(&route_gw, RTPROT_UNSPEC);
if (r >= 0) {
route_gw->family = AF_INET;
route_gw->dst_addr.in = gateway;
route_gw->dst_prefixlen = 32;
route_gw->scope = RT_SCOPE_LINK;
route_drop(route_gw, link,
&link_route_drop_handler);
route_remove(route_gw, link,
&link_route_remove_handler);
}
r = route_new_dynamic(&route, RTPROT_UNSPEC);
r = route_new(&route, RTPROT_UNSPEC);
if (r >= 0) {
route->family = AF_INET;
route->in_addr.in = gateway;
route_drop(route, link,
&link_route_drop_handler);
route_remove(route, link,
&link_route_remove_handler);
}
}
@ -214,7 +214,7 @@ static int dhcp_lease_lost(Link *link) {
address->in_addr.in = addr;
address->prefixlen = prefixlen;
address_drop(address, link, &link_address_drop_handler);
address_remove(address, link, &link_address_remove_handler);
}
}
@ -267,7 +267,7 @@ static int dhcp4_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
log_link_error_errno(link, r, "Could not set DHCPv4 address: %m");
link_enter_failed(link);
} else if (r >= 0)
link_rtnl_process_address(rtnl, m, link->manager);
manager_rtnl_process_address(rtnl, m, link->manager);
link_set_dhcp_routes(link);
@ -288,7 +288,7 @@ static int dhcp4_update_address(Link *link,
prefixlen = in_addr_netmask_to_prefixlen(netmask);
r = address_new_dynamic(&addr);
r = address_new(&addr);
if (r < 0)
return r;

View file

@ -58,7 +58,7 @@ static int dhcp6_address_handler(sd_netlink *rtnl, sd_netlink_message *m,
link_enter_failed(link);
} else if (r >= 0)
link_rtnl_process_address(rtnl, m, link->manager);
manager_rtnl_process_address(rtnl, m, link->manager);
return 1;
}
@ -69,7 +69,7 @@ static int dhcp6_address_update(Link *link, struct in6_addr *ip6_addr,
int r;
_cleanup_address_free_ Address *addr = NULL;
r = address_new_dynamic(&addr);
r = address_new(&addr);
if (r < 0)
return r;

View file

@ -42,7 +42,7 @@ static int ipv4ll_address_lost(Link *link) {
log_link_debug(link, "IPv4 link-local release %u.%u.%u.%u", ADDRESS_FMT_VAL(addr));
r = address_new_dynamic(&address);
r = address_new(&address);
if (r < 0) {
log_link_error_errno(link, r, "Could not allocate address: %m");
return r;
@ -53,9 +53,9 @@ static int ipv4ll_address_lost(Link *link) {
address->prefixlen = 16;
address->scope = RT_SCOPE_LINK;
address_drop(address, link, &link_address_drop_handler);
address_remove(address, link, &link_address_remove_handler);
r = route_new_dynamic(&route, RTPROT_UNSPEC);
r = route_new(&route, RTPROT_UNSPEC);
if (r < 0) {
log_link_error_errno(link, r, "Could not allocate route: %m");
return r;
@ -65,7 +65,7 @@ static int ipv4ll_address_lost(Link *link) {
route->scope = RT_SCOPE_LINK;
route->metrics = IPV4LL_ROUTE_METRIC;
route_drop(route, link, &link_route_drop_handler);
route_remove(route, link, &link_route_remove_handler);
link_client_handler(link);
@ -105,7 +105,7 @@ static int ipv4ll_address_handler(sd_netlink *rtnl, sd_netlink_message *m, void
log_link_error_errno(link, r, "could not set ipv4ll address: %m");
link_enter_failed(link);
} else if (r >= 0)
link_rtnl_process_address(rtnl, m, link->manager);
manager_rtnl_process_address(rtnl, m, link->manager);
link->ipv4ll_address = true;
@ -133,7 +133,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
log_link_debug(link, "IPv4 link-local claim %u.%u.%u.%u",
ADDRESS_FMT_VAL(address));
r = address_new_dynamic(&ll_addr);
r = address_new(&ll_addr);
if (r < 0)
return r;
@ -149,7 +149,7 @@ static int ipv4ll_address_claimed(sd_ipv4ll *ll, Link *link) {
link->ipv4ll_address = false;
r = route_new_dynamic(&route, RTPROT_STATIC);
r = route_new(&route, RTPROT_STATIC);
if (r < 0)
return r;

View file

@ -23,15 +23,16 @@
#include <linux/if.h>
#include <unistd.h>
#include "bus-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 "fileio.h"
#include "socket-util.h"
#include "bus-util.h"
#include "udev-util.h"
#include "netlink-util.h"
#include "dhcp-lease-internal.h"
#include "network-internal.h"
#include "networkd-link.h"
#include "networkd-netdev.h"
@ -291,10 +292,10 @@ static void link_free(Link *link) {
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);
@ -336,15 +337,28 @@ static void link_free(Link *link) {
}
Link *link_unref(Link *link) {
if (link && (-- link->n_ref <= 0))
link_free(link);
if (!link)
return NULL;
assert(link->n_ref > 0);
link->n_ref --;
if (link->n_ref > 0)
return NULL;
link_free(link);
return NULL;
}
Link *link_ref(Link *link) {
if (link)
assert_se(++ link->n_ref >= 2);
if (!link)
return NULL;
assert(link->n_ref > 0);
link->n_ref ++;
return link;
}
@ -531,7 +545,7 @@ static int route_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST)
log_link_warning_errno(link, r, "%-*s: could not set route: %m", IFNAMSIZ, link->ifname);
log_link_warning_errno(link, r, "Could not set route: %m");
if (link->link_messages == 0) {
log_link_debug(link, "Routes set");
@ -572,7 +586,7 @@ static int link_enter_set_routes(Link *link) {
return 0;
}
int link_route_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_link_unref_ Link *link = userdata;
int r;
@ -585,7 +599,7 @@ int link_route_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userd
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -ESRCH)
log_link_warning_errno(link, r, "%-*s: could not drop route: %m", IFNAMSIZ, link->ifname);
log_link_warning_errno(link, r, "Could not drop route: %m");
return 1;
}
@ -609,9 +623,9 @@ static int address_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST)
log_link_warning_errno(link, r, "%-*s: could not set address: %m", IFNAMSIZ, link->ifname);
log_link_warning_errno(link, r, "could not set address: %m");
else if (r >= 0)
link_rtnl_process_address(rtnl, m, link->manager);
manager_rtnl_process_address(rtnl, m, link->manager);
if (link->link_messages == 0) {
log_link_debug(link, "Addresses set");
@ -854,7 +868,7 @@ static int link_enter_set_addresses(Link *link) {
return 0;
}
int link_address_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
_cleanup_link_unref_ Link *link = userdata;
int r;
@ -867,7 +881,7 @@ int link_address_drop_handler(sd_netlink *rtnl, sd_netlink_message *m, void *use
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EADDRNOTAVAIL)
log_link_warning_errno(link, r, "%-*s: could not drop address: %m", IFNAMSIZ, link->ifname);
log_link_warning_errno(link, r, "Could not drop address: %m");
return 1;
}
@ -1019,7 +1033,7 @@ static int set_mtu_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
r = sd_netlink_message_get_errno(m);
if (r < 0)
log_link_warning_errno(link, r, "%-*s: could not set MTU: %m", IFNAMSIZ, link->ifname);
log_link_warning_errno(link, r, "Could not set MTU: %m");
return 1;
}
@ -1207,7 +1221,7 @@ static int link_up_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userda
if (r < 0)
/* we warn but don't fail the link, as it may be
brought up later */
log_link_warning_errno(link, r, "%-*s: could not bring up interface: %m", IFNAMSIZ, link->ifname);
log_link_warning_errno(link, r, "Could not bring up interface: %m");
return 1;
}
@ -1294,7 +1308,7 @@ static int link_down_handler(sd_netlink *rtnl, sd_netlink_message *m, void *user
r = sd_netlink_message_get_errno(m);
if (r < 0)
log_link_warning_errno(link, r, "%-*s: could not bring down interface: %m", IFNAMSIZ, link->ifname);
log_link_warning_errno(link, r, "Could not bring down interface: %m");
return 1;
}
@ -1616,7 +1630,7 @@ static int netdev_join_handler(sd_netlink *rtnl, sd_netlink_message *m, void *us
r = sd_netlink_message_get_errno(m);
if (r < 0 && r != -EEXIST) {
log_link_error_errno(link, r, "%-*s: could not join netdev: %m", IFNAMSIZ, link->ifname);
log_link_error_errno(link, r, "Could not join netdev: %m");
link_enter_failed(link);
return 1;
} else
@ -2011,179 +2025,6 @@ int link_initialized(Link *link, struct udev_device *device) {
return 0;
}
static 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_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
Manager *m = userdata;
Link *link = NULL;
uint16_t type;
_cleanup_address_free_ Address *address = NULL;
unsigned char flags;
Address *existing;
char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
const char *valid_str = NULL;
int r, ifindex;
assert(rtnl);
assert(message);
assert(m);
if (sd_netlink_message_is_error(message)) {
r = sd_netlink_message_get_errno(message);
if (r < 0)
log_warning_errno(r, "rtnl: failed to receive address: %m");
return 0;
}
r = sd_netlink_message_get_type(message, &type);
if (r < 0) {
log_warning_errno(r, "rtnl: could not get message type: %m");
return 0;
} else if (type != RTM_NEWADDR && type != RTM_DELADDR) {
log_warning("rtnl: received unexpected message type when processing address");
return 0;
}
r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
if (r < 0) {
log_warning_errno(r, "rtnl: could not get ifindex from address: %m");
return 0;
} else if (ifindex <= 0) {
log_warning("rtnl: received address message with invalid ifindex: %d", ifindex);
return 0;
} else {
r = link_get(m, ifindex, &link);
if (r < 0 || !link) {
/* when enumerating we might be out of sync, but we will
* get the address again, so just ignore it */
if (!m->enumerating)
log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
return 0;
}
}
r = address_new_dynamic(&address);
if (r < 0)
return r;
r = sd_rtnl_message_addr_get_family(message, &address->family);
if (r < 0 || !IN_SET(address->family, AF_INET, AF_INET6)) {
log_link_warning(link, "rtnl: received address with invalid family, ignoring.");
return 0;
}
r = sd_rtnl_message_addr_get_prefixlen(message, &address->prefixlen);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m");
return 0;
}
r = sd_rtnl_message_addr_get_scope(message, &address->scope);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m");
return 0;
}
r = sd_rtnl_message_addr_get_flags(message, &flags);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m");
return 0;
}
address->flags = flags;
switch (address->family) {
case AF_INET:
r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &address->in_addr.in);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
return 0;
}
break;
case AF_INET6:
r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &address->in_addr.in6);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
return 0;
}
break;
default:
assert_not_reached("invalid address family");
}
if (!inet_ntop(address->family, &address->in_addr, buf, INET6_ADDRSTRLEN)) {
log_link_warning(link, "Could not print address");
return 0;
}
r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &address->cinfo);
if (r >= 0) {
if (address->cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
valid_str = "ever";
else
valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
address->cinfo.ifa_valid * USEC_PER_SEC,
USEC_PER_SEC);
}
existing = link_get_equal_address(link, address);
switch (type) {
case RTM_NEWADDR:
if (existing) {
log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, address->prefixlen, valid_str);
existing->scope = address->scope;
existing->flags = address->flags;
existing->cinfo = address->cinfo;
} 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;
link_save(link);
}
break;
case RTM_DELADDR:
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);
break;
default:
assert_not_reached("Received invalid RTNL message type");
}
return 1;
}
int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
Link *link;
_cleanup_udev_device_unref_ struct udev_device *device = NULL;
@ -2207,8 +2048,10 @@ int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
/* not in a container, udev will be around */
sprintf(ifindex_str, "n%d", link->ifindex);
device = udev_device_new_from_device_id(m->udev, ifindex_str);
if (!device)
return log_link_warning_errno(link, errno, "Could not find udev device: %m");
if (!device) {
r = log_link_warning_errno(link, errno, "Could not find udev device: %m");
goto failed;
}
if (udev_device_get_is_initialized(device) <= 0) {
/* not yet ready */
@ -2218,17 +2061,20 @@ int link_add(Manager *m, sd_netlink_message *message, Link **ret) {
r = link_initialized(link, device);
if (r < 0)
return r;
goto failed;
} else {
/* we are calling a callback directly, so must take a ref */
link_ref(link);
r = link_initialized_and_synced(m->rtnl, NULL, link);
if (r < 0)
return r;
goto failed;
}
return 0;
failed:
link_enter_failed(link);
return r;
}
static int link_carrier_gained(Link *link) {
@ -2425,10 +2271,11 @@ static void link_update_operstate(Link *link) {
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) {
if (address->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED))
SET_FOREACH(address, link->addresses, i) {
if (!address_is_ready(address))
continue;
if (address->scope < scope)

View file

@ -83,7 +83,7 @@ struct Link {
unsigned link_messages;
unsigned enslaving;
LIST_HEAD(Address, addresses);
Set *addresses;
sd_dhcp_client *dhcp_client;
sd_dhcp_lease *dhcp_lease;
@ -120,8 +120,8 @@ int link_get(Manager *m, int ifindex, Link **ret);
int link_add(Manager *manager, sd_netlink_message *message, Link **ret);
void link_drop(Link *link);
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);
int link_address_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
int link_route_remove_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata);
void link_enter_failed(Link *link);
int link_initialized(Link *link, struct udev_device *device);
@ -129,7 +129,6 @@ int link_initialized(Link *link, struct udev_device *device);
void link_client_handler(Link *link);
int link_update(Link *link, sd_netlink_message *message);
int link_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata);
int link_save(Link *link);

View file

@ -277,6 +277,166 @@ static int manager_connect_udev(Manager *m) {
return 0;
}
int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
Manager *m = userdata;
Link *link = NULL;
uint16_t type;
unsigned char flags;
int family;
unsigned char prefixlen;
unsigned char scope;
union in_addr_union in_addr;
struct ifa_cacheinfo cinfo;
Address *address = NULL;
char buf[INET6_ADDRSTRLEN], valid_buf[FORMAT_TIMESPAN_MAX];
const char *valid_str = NULL;
int r, ifindex;
assert(rtnl);
assert(message);
assert(m);
if (sd_netlink_message_is_error(message)) {
r = sd_netlink_message_get_errno(message);
if (r < 0)
log_warning_errno(r, "rtnl: failed to receive address: %m");
return 0;
}
r = sd_netlink_message_get_type(message, &type);
if (r < 0) {
log_warning_errno(r, "rtnl: could not get message type: %m");
return 0;
} else if (type != RTM_NEWADDR && type != RTM_DELADDR) {
log_warning("rtnl: received unexpected message type when processing address");
return 0;
}
r = sd_rtnl_message_addr_get_ifindex(message, &ifindex);
if (r < 0) {
log_warning_errno(r, "rtnl: could not get ifindex from address: %m");
return 0;
} else if (ifindex <= 0) {
log_warning("rtnl: received address message with invalid ifindex: %d", ifindex);
return 0;
} else {
r = link_get(m, ifindex, &link);
if (r < 0 || !link) {
/* when enumerating we might be out of sync, but we will
* get the address again, so just ignore it */
if (!m->enumerating)
log_warning("rtnl: received address for nonexistent link (%d), ignoring", ifindex);
return 0;
}
}
r = sd_rtnl_message_addr_get_family(message, &family);
if (r < 0 || !IN_SET(family, AF_INET, AF_INET6)) {
log_link_warning(link, "rtnl: received address with invalid family, ignoring.");
return 0;
}
r = sd_rtnl_message_addr_get_prefixlen(message, &prefixlen);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received address with invalid prefixlen, ignoring: %m");
return 0;
}
r = sd_rtnl_message_addr_get_scope(message, &scope);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received address with invalid scope, ignoring: %m");
return 0;
}
r = sd_rtnl_message_addr_get_flags(message, &flags);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received address with invalid flags, ignoring: %m");
return 0;
}
switch (family) {
case AF_INET:
r = sd_netlink_message_read_in_addr(message, IFA_LOCAL, &in_addr.in);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
return 0;
}
break;
case AF_INET6:
r = sd_netlink_message_read_in6_addr(message, IFA_ADDRESS, &in_addr.in6);
if (r < 0) {
log_link_warning_errno(link, r, "rtnl: received address without valid address, ignoring: %m");
return 0;
}
break;
default:
assert_not_reached("invalid address family");
}
if (!inet_ntop(family, &in_addr, buf, INET6_ADDRSTRLEN)) {
log_link_warning(link, "Could not print address");
return 0;
}
r = sd_netlink_message_read_cache_info(message, IFA_CACHEINFO, &cinfo);
if (r >= 0) {
if (cinfo.ifa_valid == CACHE_INFO_INFINITY_LIFE_TIME)
valid_str = "ever";
else
valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
cinfo.ifa_valid * USEC_PER_SEC,
USEC_PER_SEC);
}
address_get(link, family, &in_addr, prefixlen, &address);
switch (type) {
case RTM_NEWADDR:
if (address) {
log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
address->scope = scope;
address->flags = flags;
address->cinfo = cinfo;
} else {
r = address_add(link, family, &in_addr, prefixlen, &address);
if (r < 0) {
log_link_warning_errno(link, r, "Failed to add address %s/%u: %m", buf, prefixlen);
return 0;
} else
log_link_debug(link, "Adding address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
address->scope = scope;
address->flags = flags;
address->cinfo = cinfo;
link_save(link);
}
break;
case RTM_DELADDR:
if (address) {
log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
address_drop(address);
} else
log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
break;
default:
assert_not_reached("Received invalid RTNL message type");
}
return 1;
}
static int manager_rtnl_process_link(sd_netlink *rtnl, sd_netlink_message *message, void *userdata) {
Manager *m = userdata;
Link *link = NULL;
@ -410,11 +570,11 @@ static int manager_connect_rtnl(Manager *m) {
if (r < 0)
return r;
r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, &link_rtnl_process_address, m);
r = sd_netlink_add_match(m->rtnl, RTM_NEWADDR, &manager_rtnl_process_address, m);
if (r < 0)
return r;
r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, &link_rtnl_process_address, m);
r = sd_netlink_add_match(m->rtnl, RTM_DELADDR, &manager_rtnl_process_address, m);
if (r < 0)
return r;
@ -477,14 +637,6 @@ void manager_free(Manager *m) {
free(m->state_file);
sd_event_source_unref(m->udev_event_source);
udev_monitor_unref(m->udev_monitor);
udev_unref(m->udev);
sd_bus_unref(m->bus);
sd_bus_slot_unref(m->prepare_for_sleep_slot);
sd_event_source_unref(m->bus_retry_event_source);
while ((link = hashmap_first(m->links)))
link_unref(link);
hashmap_free(m->links);
@ -504,6 +656,14 @@ void manager_free(Manager *m) {
sd_netlink_unref(m->rtnl);
sd_event_unref(m->event);
sd_event_source_unref(m->udev_event_source);
udev_monitor_unref(m->udev_monitor);
udev_unref(m->udev);
sd_bus_unref(m->bus);
sd_bus_slot_unref(m->prepare_for_sleep_slot);
sd_event_source_unref(m->bus_retry_event_source);
free(m);
}
@ -633,7 +793,7 @@ int manager_rtnl_enumerate_addresses(Manager *m) {
m->enumerating = true;
k = link_rtnl_process_address(m->rtnl, addr, m);
k = manager_rtnl_process_address(m->rtnl, addr, m);
if (k < 0)
r = k;

View file

@ -326,12 +326,12 @@ int network_get(Manager *manager, struct udev_device *device,
(void) safe_atou8(attr, &name_assign_type);
if (name_assign_type == NET_NAME_ENUM)
log_warning("%-*s: found matching network '%s', based on potentially unpredictable ifname",
IFNAMSIZ, ifname, network->filename);
log_warning("%s: found matching network '%s', based on potentially unpredictable ifname",
ifname, network->filename);
else
log_debug("%-*s: found matching network '%s'", IFNAMSIZ, ifname, network->filename);
log_debug("%s: found matching network '%s'", ifname, network->filename);
} else
log_debug("%-*s: found matching network '%s'", IFNAMSIZ, ifname, network->filename);
log_debug("%s: found matching network '%s'", ifname, network->filename);
*ret = network;
return 0;

View file

@ -26,8 +26,26 @@
#include "networkd.h"
#include "networkd-route.h"
int route_new(Route **ret, unsigned char rtm_protocol) {
_cleanup_route_free_ Route *route = NULL;
route = new0(Route, 1);
if (!route)
return -ENOMEM;
route->family = AF_UNSPEC;
route->scope = RT_SCOPE_UNIVERSE;
route->protocol = rtm_protocol;
*ret = route;
route = NULL;
return 0;
}
int route_new_static(Network *network, unsigned section, Route **ret) {
_cleanup_route_free_ Route *route = NULL;
int r;
if (section) {
route = hashmap_get(network->routes_by_section,
@ -40,13 +58,9 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
}
}
route = new0(Route, 1);
if (!route)
return -ENOMEM;
route->family = AF_UNSPEC;
route->scope = RT_SCOPE_UNIVERSE;
route->protocol = RTPROT_STATIC;
r = route_new(&route, RTPROT_STATIC);
if (r < 0)
return r;
route->network = network;
@ -64,23 +78,6 @@ int route_new_static(Network *network, unsigned section, Route **ret) {
return 0;
}
int route_new_dynamic(Route **ret, unsigned char rtm_protocol) {
_cleanup_route_free_ Route *route = NULL;
route = new0(Route, 1);
if (!route)
return -ENOMEM;
route->family = AF_UNSPEC;
route->scope = RT_SCOPE_UNIVERSE;
route->protocol = rtm_protocol;
*ret = route;
route = NULL;
return 0;
}
void route_free(Route *route) {
if (!route)
return;
@ -96,7 +93,7 @@ void route_free(Route *route) {
free(route);
}
int route_drop(Route *route, Link *link,
int route_remove(Route *route, Link *link,
sd_netlink_message_handler_t callback) {
_cleanup_netlink_message_unref_ sd_netlink_message *req = NULL;
int r;

View file

@ -46,10 +46,10 @@ struct Route {
};
int route_new_static(Network *network, unsigned section, Route **ret);
int route_new_dynamic(Route **ret, unsigned char rtm_protocol);
int route_new(Route **ret, unsigned char rtm_protocol);
void route_free(Route *route);
int route_configure(Route *route, Link *link, sd_netlink_message_handler_t callback);
int route_drop(Route *route, Link *link, sd_netlink_message_handler_t callback);
int route_remove(Route *route, Link *link, sd_netlink_message_handler_t callback);
DEFINE_TRIVIAL_CLEANUP_FUNC(Route*, route_free);
#define _cleanup_route_free_ _cleanup_(route_freep)

View file

@ -80,6 +80,8 @@ bool manager_should_reload(Manager *m);
int manager_rtnl_enumerate_links(Manager *m);
int manager_rtnl_enumerate_addresses(Manager *m);
int manager_rtnl_process_address(sd_netlink *nl, sd_netlink_message *message, void *userdata);
int manager_send_changed(Manager *m, const char *property, ...) _sentinel_;
int manager_save(Manager *m);

View file

@ -143,8 +143,8 @@ static void test_network_get(Manager *manager, struct udev_device *loopback) {
static void test_address_equality(void) {
_cleanup_address_free_ Address *a1 = NULL, *a2 = NULL;
assert_se(address_new_dynamic(&a1) >= 0);
assert_se(address_new_dynamic(&a2) >= 0);
assert_se(address_new(&a1) >= 0);
assert_se(address_new(&a2) >= 0);
assert_se(address_equal(NULL, NULL));
assert_se(!address_equal(a1, NULL));
@ -158,17 +158,18 @@ static void test_address_equality(void) {
assert_se(address_equal(a1, a2));
assert_se(inet_pton(AF_INET, "192.168.3.9", &a1->in_addr.in));
assert_se(address_equal(a1, a2));
assert_se(!address_equal(a1, a2));
assert_se(inet_pton(AF_INET, "192.168.3.9", &a2->in_addr.in));
assert_se(address_equal(a1, a2));
assert_se(inet_pton(AF_INET, "192.168.3.10", &a1->in_addr_peer.in));
assert_se(address_equal(a1, a2));
assert_se(inet_pton(AF_INET, "192.168.3.11", &a2->in_addr_peer.in));
assert_se(address_equal(a1, a2));
a1->prefixlen = 10;
assert_se(!address_equal(a1, a2));
a2->prefixlen = 10;
assert_se(address_equal(a1, a2));
assert_se(inet_pton(AF_INET, "192.168.3.10", &a2->in_addr.in));
assert_se(address_equal(a1, a2));
a1->family = AF_INET6;
assert_se(!address_equal(a1, a2));

View file

@ -43,6 +43,7 @@ int sd_ipv4ll_get_address(sd_ipv4ll *ll, struct in_addr *address);
int sd_ipv4ll_set_callback(sd_ipv4ll *ll, sd_ipv4ll_cb_t cb, void *userdata);
int sd_ipv4ll_set_mac(sd_ipv4ll *ll, const struct ether_addr *addr);
int sd_ipv4ll_set_index(sd_ipv4ll *ll, int interface_index);
int sd_ipv4ll_set_address(sd_ipv4ll *ll, const struct in_addr *address);
int sd_ipv4ll_set_address_seed(sd_ipv4ll *ll, unsigned seed);
bool sd_ipv4ll_is_running(sd_ipv4ll *ll);
int sd_ipv4ll_start(sd_ipv4ll *ll);

View file

@ -137,6 +137,10 @@ int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char
int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char prefixlen);
int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope);
int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family);
int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol);
int sd_rtnl_message_route_get_scope(sd_netlink_message *m, unsigned char *scope);
int sd_rtnl_message_route_get_tos(sd_netlink_message *m, unsigned char *tos);
int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table);
int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char *dst_len);
int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len);