Merge pull request #1530 from teg/network-fixes-2
networkd/libsystemd-network: collection of trivial patches v2
This commit is contained in:
commit
9ea79b459e
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue