mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-08 21:17:47 +03:00
commit
3116c225d2
@ -227,7 +227,14 @@
|
||||
<literal>yes</literal>, <literal>no</literal>,
|
||||
<literal>ipv4</literal>, or <literal>ipv6</literal>.</para>
|
||||
|
||||
<para>Please note that, by default, the domain name
|
||||
<para>Note that DHCPv6 will by default be triggered by Router
|
||||
Advertisment, if that is enabled, regardless of this parameter.
|
||||
By enabling DHCPv6 support explicitly, the DHCPv6 client will
|
||||
be started regardless of the presence of routers on the link,
|
||||
or what flags the routers pass. See
|
||||
<literal>IPv6AcceptRouterAdvertisements=</literal>.</para>
|
||||
|
||||
<para>Furthermore, note that by default the domain name
|
||||
specified through DHCP is not used for name resolution.
|
||||
See option <option>UseDomains=</option> below.</para>
|
||||
</listitem>
|
||||
@ -414,6 +421,9 @@
|
||||
When unset, the kernel default is used, and router
|
||||
advertisements are accepted only when local forwarding
|
||||
is disabled for that interface.
|
||||
When router advertisements are accepted, they will
|
||||
trigger the start of the DHCPv6 client if the relevant
|
||||
flags are passed, or if no routers are found on the link.
|
||||
Takes a boolean. If true, router advertisements are
|
||||
accepted, when false, router advertisements are ignored,
|
||||
independently of the local forwarding state.</para>
|
||||
|
@ -23,19 +23,20 @@
|
||||
|
||||
/* Missing glibc definitions to access certain kernel APIs */
|
||||
|
||||
#include <sys/resource.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <linux/oom.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/loop.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/audit.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/loop.h>
|
||||
#include <linux/neighbour.h>
|
||||
#include <linux/oom.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_AUDIT
|
||||
#include <libaudit.h>
|
||||
@ -900,6 +901,10 @@ static inline int setns(int fd, int nstype) {
|
||||
#define NDA_MAX (__NDA_MAX - 1)
|
||||
#endif
|
||||
|
||||
#ifndef RTA_PREF
|
||||
#define RTA_PREF 20
|
||||
#endif
|
||||
|
||||
#ifndef IPV6_UNICAST_IF
|
||||
#define IPV6_UNICAST_IF 76
|
||||
#endif
|
||||
|
@ -1115,11 +1115,19 @@ static int client_start(sd_dhcp6_client *client, enum DHCP6State state) {
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_stop(sd_dhcp6_client *client) {
|
||||
assert_return(client, -EINVAL);
|
||||
|
||||
client_stop(client, SD_DHCP6_CLIENT_EVENT_STOP);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_is_running(sd_dhcp6_client *client) {
|
||||
assert_return(client, -EINVAL);
|
||||
|
||||
return client->state != DHCP6_STATE_STOPPED;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_start(sd_dhcp6_client *client) {
|
||||
int r = 0;
|
||||
enum DHCP6State state = DHCP6_STATE_SOLICITATION;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "async.h"
|
||||
#include "icmp6-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "list.h"
|
||||
#include "socket-util.h"
|
||||
|
||||
@ -47,6 +48,12 @@ enum NDiscState {
|
||||
#define ICMP6_RECV_SIZE (IP6_MIN_MTU - sizeof(struct ip6_hdr))
|
||||
#define NDISC_OPT_LEN_UNITS 8
|
||||
|
||||
#define ND_RA_FLAG_PREF 0x18
|
||||
#define ND_RA_FLAG_PREF_LOW 0x03
|
||||
#define ND_RA_FLAG_PREF_MEDIUM 0x0
|
||||
#define ND_RA_FLAG_PREF_HIGH 0x1
|
||||
#define ND_RA_FLAG_PREF_INVALID 0x2
|
||||
|
||||
typedef struct NDiscPrefix NDiscPrefix;
|
||||
|
||||
struct NDiscPrefix {
|
||||
@ -75,6 +82,9 @@ struct sd_ndisc {
|
||||
sd_event_source *recv;
|
||||
sd_event_source *timeout;
|
||||
int nd_sent;
|
||||
sd_ndisc_router_callback_t router_callback;
|
||||
sd_ndisc_prefix_autonomous_callback_t prefix_autonomous_callback;
|
||||
sd_ndisc_prefix_onlink_callback_t prefix_onlink_callback;
|
||||
sd_ndisc_callback_t callback;
|
||||
void *userdata;
|
||||
};
|
||||
@ -119,15 +129,17 @@ static int ndisc_prefix_new(sd_ndisc *nd, NDiscPrefix **ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ndisc_notify(sd_ndisc *nd, int event) {
|
||||
if (nd->callback)
|
||||
nd->callback(nd, event, nd->userdata);
|
||||
}
|
||||
|
||||
int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_callback_t callback,
|
||||
void *userdata) {
|
||||
int sd_ndisc_set_callback(sd_ndisc *nd,
|
||||
sd_ndisc_router_callback_t router_callback,
|
||||
sd_ndisc_prefix_onlink_callback_t prefix_onlink_callback,
|
||||
sd_ndisc_prefix_autonomous_callback_t prefix_autonomous_callback,
|
||||
sd_ndisc_callback_t callback,
|
||||
void *userdata) {
|
||||
assert(nd);
|
||||
|
||||
nd->router_callback = router_callback;
|
||||
nd->prefix_onlink_callback = prefix_onlink_callback;
|
||||
nd->prefix_autonomous_callback = prefix_autonomous_callback;
|
||||
nd->callback = callback;
|
||||
nd->userdata = userdata;
|
||||
|
||||
@ -320,7 +332,7 @@ static int ndisc_prefix_match(sd_ndisc *nd, const struct in6_addr *addr,
|
||||
static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len,
|
||||
const struct nd_opt_prefix_info *prefix_opt) {
|
||||
NDiscPrefix *prefix;
|
||||
uint32_t lifetime;
|
||||
uint32_t lifetime_valid, lifetime_preferred;
|
||||
usec_t time_now;
|
||||
char time_string[FORMAT_TIMESPAN_MAX];
|
||||
int r;
|
||||
@ -331,10 +343,17 @@ static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len,
|
||||
if (len < prefix_opt->nd_opt_pi_len)
|
||||
return -ENOMSG;
|
||||
|
||||
if (!(prefix_opt->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK))
|
||||
if (!(prefix_opt->nd_opt_pi_flags_reserved & (ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO)))
|
||||
return 0;
|
||||
|
||||
lifetime = be32toh(prefix_opt->nd_opt_pi_valid_time);
|
||||
if (in_addr_is_link_local(AF_INET6, (const union in_addr_union *) &prefix_opt->nd_opt_pi_prefix) > 0)
|
||||
return 0;
|
||||
|
||||
lifetime_valid = be32toh(prefix_opt->nd_opt_pi_valid_time);
|
||||
lifetime_preferred = be32toh(prefix_opt->nd_opt_pi_preferred_time);
|
||||
|
||||
if (lifetime_valid < lifetime_preferred)
|
||||
return 0;
|
||||
|
||||
r = ndisc_prefix_match(nd, &prefix_opt->nd_opt_pi_prefix,
|
||||
prefix_opt->nd_opt_pi_prefix_len, &prefix);
|
||||
@ -357,8 +376,8 @@ static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len,
|
||||
|
||||
log_ndisc(nd, "New prefix "SD_NDISC_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
|
||||
SD_NDISC_ADDRESS_FORMAT_VAL(prefix->addr),
|
||||
prefix->len, lifetime,
|
||||
format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime * USEC_PER_SEC, USEC_PER_SEC));
|
||||
prefix->len, lifetime_valid,
|
||||
format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_valid * USEC_PER_SEC, USEC_PER_SEC));
|
||||
|
||||
LIST_PREPEND(prefixes, nd->prefixes, prefix);
|
||||
|
||||
@ -378,17 +397,24 @@ static int ndisc_prefix_update(sd_ndisc *nd, ssize_t len,
|
||||
|
||||
log_ndisc(nd, "Update prefix "SD_NDISC_ADDRESS_FORMAT_STR"/%d lifetime %d expires in %s",
|
||||
SD_NDISC_ADDRESS_FORMAT_VAL(prefix->addr),
|
||||
prefix->len, lifetime,
|
||||
format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime * USEC_PER_SEC, USEC_PER_SEC));
|
||||
prefix->len, lifetime_valid,
|
||||
format_timespan(time_string, FORMAT_TIMESPAN_MAX, lifetime_valid * USEC_PER_SEC, USEC_PER_SEC));
|
||||
}
|
||||
|
||||
r = sd_event_now(nd->event, clock_boottime_or_monotonic(), &time_now);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
prefix->valid_until = time_now + lifetime * USEC_PER_SEC;
|
||||
prefix->valid_until = time_now + lifetime_valid * USEC_PER_SEC;
|
||||
|
||||
return r;
|
||||
if ((prefix_opt->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) && nd->prefix_onlink_callback)
|
||||
nd->prefix_onlink_callback(nd, &prefix->addr, prefix->len, prefix->valid_until, nd->userdata);
|
||||
|
||||
if ((prefix_opt->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) && nd->prefix_autonomous_callback)
|
||||
nd->prefix_autonomous_callback(nd, &prefix->addr, prefix->len, lifetime_preferred, lifetime_valid,
|
||||
nd->userdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ndisc_ra_parse(sd_ndisc *nd, struct nd_router_advert *ra,
|
||||
@ -453,11 +479,13 @@ static int ndisc_ra_parse(sd_ndisc *nd, struct nd_router_advert *ra,
|
||||
}
|
||||
|
||||
static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
|
||||
sd_ndisc *nd = userdata;
|
||||
int r, buflen = 0;
|
||||
ssize_t len;
|
||||
_cleanup_free_ struct nd_router_advert *ra = NULL;
|
||||
int event = SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE;
|
||||
sd_ndisc *nd = userdata;
|
||||
int r, buflen = 0, pref, stateful;
|
||||
union sockaddr_union router = {};
|
||||
socklen_t router_len = sizeof(router);
|
||||
unsigned lifetime;
|
||||
ssize_t len;
|
||||
|
||||
assert(s);
|
||||
assert(nd);
|
||||
@ -471,9 +499,12 @@ static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
|
||||
if (!ra)
|
||||
return -ENOMEM;
|
||||
|
||||
len = read(fd, ra, buflen);
|
||||
len = recvfrom(fd, ra, buflen, 0, &router.sa, &router_len);
|
||||
if (len < 0) {
|
||||
log_ndisc(nd, "Could not receive message from UDP socket: %m");
|
||||
log_ndisc(nd, "Could not receive message from ICMPv6 socket: %m");
|
||||
return 0;
|
||||
} else if (router_len != sizeof(router.in6) && router_len != 0) {
|
||||
log_ndisc(nd, "Received invalid source address size from ICMPv6 socket: %zu bytes", (size_t)router_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -487,26 +518,33 @@ static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
|
||||
|
||||
nd->state = NDISC_STATE_ADVERTISMENT_LISTEN;
|
||||
|
||||
if (ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER )
|
||||
event = SD_NDISC_EVENT_ROUTER_ADVERTISMENT_OTHER;
|
||||
stateful = ra->nd_ra_flags_reserved & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER);
|
||||
pref = ra->nd_ra_flags_reserved & ND_RA_FLAG_PREF >> 3;
|
||||
|
||||
if (ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
|
||||
event = SD_NDISC_EVENT_ROUTER_ADVERTISMENT_MANAGED;
|
||||
|
||||
log_ndisc(nd, "Received Router Advertisement flags %s/%s",
|
||||
ra->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED? "MANAGED": "none",
|
||||
ra->nd_ra_flags_reserved & ND_RA_FLAG_OTHER? "OTHER": "none");
|
||||
|
||||
if (event != SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE) {
|
||||
r = ndisc_ra_parse(nd, ra, len);
|
||||
if (r < 0) {
|
||||
log_ndisc(nd, "Could not parse Router Advertisement: %s",
|
||||
strerror(-r));
|
||||
return 0;
|
||||
}
|
||||
switch (pref) {
|
||||
case ND_RA_FLAG_PREF_LOW:
|
||||
case ND_RA_FLAG_PREF_HIGH:
|
||||
break;
|
||||
default:
|
||||
pref = ND_RA_FLAG_PREF_MEDIUM;
|
||||
break;
|
||||
}
|
||||
|
||||
ndisc_notify(nd, event);
|
||||
lifetime = be16toh(ra->nd_ra_router_lifetime);
|
||||
|
||||
log_ndisc(nd, "Received Router Advertisement: flags %s preference %s lifetime %u sec",
|
||||
stateful & ND_RA_FLAG_MANAGED ? "MANAGED" : stateful & ND_RA_FLAG_OTHER ? "OTHER" : "none",
|
||||
pref == ND_RA_FLAG_PREF_HIGH ? "high" : pref == ND_RA_FLAG_PREF_LOW ? "low" : "medium",
|
||||
lifetime);
|
||||
|
||||
r = ndisc_ra_parse(nd, ra, len);
|
||||
if (r < 0) {
|
||||
log_ndisc(nd, "Could not parse Router Advertisement: %s", strerror(-r));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nd->router_callback)
|
||||
nd->router_callback(nd, stateful, router_len != 0 ? &router.in6.sin6_addr : NULL, lifetime, pref, nd->userdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -525,7 +563,8 @@ static int ndisc_router_solicitation_timeout(sd_event_source *s, uint64_t usec,
|
||||
nd->timeout = sd_event_source_unref(nd->timeout);
|
||||
|
||||
if (nd->nd_sent >= NDISC_MAX_ROUTER_SOLICITATIONS) {
|
||||
ndisc_notify(nd, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_TIMEOUT);
|
||||
if (nd->callback)
|
||||
nd->callback(nd, SD_NDISC_EVENT_TIMEOUT, nd->userdata);
|
||||
nd->state = NDISC_STATE_ADVERTISMENT_LISTEN;
|
||||
} else {
|
||||
if (memcmp(&nd->mac_addr, &unset, sizeof(struct ether_addr)))
|
||||
@ -549,7 +588,8 @@ static int ndisc_router_solicitation_timeout(sd_event_source *s, uint64_t usec,
|
||||
next_timeout, 0,
|
||||
ndisc_router_solicitation_timeout, nd);
|
||||
if (r < 0) {
|
||||
ndisc_notify(nd, r);
|
||||
/* we cannot continue if we are unable to rearm the timer */
|
||||
sd_ndisc_stop(nd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -575,6 +615,9 @@ int sd_ndisc_stop(sd_ndisc *nd) {
|
||||
|
||||
nd->state = NDISC_STATE_IDLE;
|
||||
|
||||
if (nd->callback)
|
||||
nd->callback(nd, SD_NDISC_EVENT_STOP, nd->userdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -85,29 +85,28 @@ int icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr) {
|
||||
return send_ra_function(0);
|
||||
}
|
||||
|
||||
static void test_rs_done(sd_ndisc *nd, int event, void *userdata) {
|
||||
static void test_rs_done(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata) {
|
||||
sd_event *e = userdata;
|
||||
static int idx = 0;
|
||||
struct {
|
||||
uint8_t flag;
|
||||
int event;
|
||||
} flag_event[] = {
|
||||
{ 0, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE },
|
||||
{ ND_RA_FLAG_OTHER, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_OTHER },
|
||||
{ ND_RA_FLAG_MANAGED, SD_NDISC_EVENT_ROUTER_ADVERTISMENT_MANAGED }
|
||||
static unsigned idx = 0;
|
||||
uint8_t flags_array[] = {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
ND_RA_FLAG_OTHER,
|
||||
ND_RA_FLAG_MANAGED
|
||||
};
|
||||
uint32_t mtu;
|
||||
|
||||
assert_se(nd);
|
||||
|
||||
assert_se(event == flag_event[idx].event);
|
||||
assert_se(flags == flags_array[idx]);
|
||||
idx++;
|
||||
|
||||
if (verbose)
|
||||
printf(" got event %d\n", event);
|
||||
printf(" got event 0x%02x\n", flags);
|
||||
|
||||
if (idx < 3) {
|
||||
send_ra(flag_event[idx].flag);
|
||||
if (idx < ELEMENTSOF(flags_array)) {
|
||||
send_ra(flags_array[idx]);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -135,7 +134,7 @@ static void test_rs(void) {
|
||||
|
||||
assert_se(sd_ndisc_set_index(nd, 42) >= 0);
|
||||
assert_se(sd_ndisc_set_mac(nd, &mac_addr) >= 0);
|
||||
assert_se(sd_ndisc_set_callback(nd, test_rs_done, e) >= 0);
|
||||
assert_se(sd_ndisc_set_callback(nd, test_rs_done, NULL, NULL, NULL, e) >= 0);
|
||||
|
||||
assert_se(sd_event_add_time(e, &test_hangcheck, clock_boottime_or_monotonic(),
|
||||
time_now + 2 *USEC_PER_SEC, 0,
|
||||
|
@ -83,20 +83,20 @@ static const NLTypeSystem empty_type_system = {
|
||||
.types = empty_types,
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_veth_types[VETH_INFO_MAX + 1] = {
|
||||
static const NLType rtnl_link_info_data_veth_types[] = {
|
||||
[VETH_INFO_PEER] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_ipvlan_types[IFLA_IPVLAN_MAX + 1] = {
|
||||
static const NLType rtnl_link_info_data_ipvlan_types[] = {
|
||||
[IFLA_IPVLAN_MODE] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_macvlan_types[IFLA_MACVLAN_MAX + 1] = {
|
||||
static const NLType rtnl_link_info_data_macvlan_types[] = {
|
||||
[IFLA_MACVLAN_MODE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_MACVLAN_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_bridge_management_types[IFLA_BRIDGE_MAX + 1] = {
|
||||
static const NLType rtnl_link_bridge_management_types[] = {
|
||||
[IFLA_BRIDGE_FLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_BRIDGE_MODE] = { .type = NETLINK_TYPE_U16 },
|
||||
/*
|
||||
@ -105,7 +105,7 @@ static const NLType rtnl_link_bridge_management_types[IFLA_BRIDGE_MAX + 1] = {
|
||||
*/
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_bridge_types[IFLA_BR_MAX + 1] = {
|
||||
static const NLType rtnl_link_info_data_bridge_types[] = {
|
||||
[IFLA_BR_FORWARD_DELAY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_HELLO_TIME] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BR_MAX_AGE] = { .type = NETLINK_TYPE_U32 },
|
||||
@ -114,7 +114,7 @@ static const NLType rtnl_link_info_data_bridge_types[IFLA_BR_MAX + 1] = {
|
||||
[IFLA_BR_PRIORITY] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_vlan_types[IFLA_VLAN_MAX + 1] = {
|
||||
static const NLType rtnl_link_info_data_vlan_types[] = {
|
||||
[IFLA_VLAN_ID] = { .type = NETLINK_TYPE_U16 },
|
||||
/*
|
||||
[IFLA_VLAN_FLAGS] = { .len = sizeof(struct ifla_vlan_flags) },
|
||||
@ -124,7 +124,7 @@ static const NLType rtnl_link_info_data_vlan_types[IFLA_VLAN_MAX + 1] = {
|
||||
[IFLA_VLAN_PROTOCOL] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_vxlan_types[IFLA_VXLAN_MAX+1] = {
|
||||
static const NLType rtnl_link_info_data_vxlan_types[] = {
|
||||
[IFLA_VXLAN_ID] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VXLAN_GROUP] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_VXLAN_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
@ -151,7 +151,7 @@ static const NLType rtnl_link_info_data_vxlan_types[IFLA_VXLAN_MAX+1] = {
|
||||
[IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NETLINK_TYPE_FLAG },
|
||||
};
|
||||
|
||||
static const NLType rtnl_bond_arp_target_types[BOND_ARP_TARGETS_MAX + 1] = {
|
||||
static const NLType rtnl_bond_arp_target_types[] = {
|
||||
[BOND_ARP_TARGETS_0] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_1] = { .type = NETLINK_TYPE_U32 },
|
||||
[BOND_ARP_TARGETS_2] = { .type = NETLINK_TYPE_U32 },
|
||||
@ -175,7 +175,7 @@ static const NLTypeSystem rtnl_bond_arp_type_system = {
|
||||
.types = rtnl_bond_arp_target_types,
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_bond_types[IFLA_BOND_MAX + 1] = {
|
||||
static const NLType rtnl_link_info_data_bond_types[] = {
|
||||
[IFLA_BOND_MODE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BOND_ACTIVE_SLAVE] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BOND_MIIMON] = { .type = NETLINK_TYPE_U32 },
|
||||
@ -201,7 +201,7 @@ static const NLType rtnl_link_info_data_bond_types[IFLA_BOND_MAX + 1] = {
|
||||
[IFLA_BOND_AD_INFO] = { .type = NETLINK_TYPE_NESTED },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_iptun_types[IFLA_IPTUN_MAX + 1] = {
|
||||
static const NLType rtnl_link_info_data_iptun_types[] = {
|
||||
[IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
@ -220,7 +220,7 @@ static const NLType rtnl_link_info_data_iptun_types[IFLA_IPTUN_MAX + 1] = {
|
||||
[IFLA_IPTUN_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_ipgre_types[IFLA_GRE_MAX + 1] = {
|
||||
static const NLType rtnl_link_info_data_ipgre_types[] = {
|
||||
[IFLA_GRE_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_GRE_IFLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
[IFLA_GRE_OFLAGS] = { .type = NETLINK_TYPE_U16 },
|
||||
@ -239,7 +239,7 @@ static const NLType rtnl_link_info_data_ipgre_types[IFLA_GRE_MAX + 1] = {
|
||||
[IFLA_GRE_ENCAP_DPORT] = { .type = NETLINK_TYPE_U16 },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_ipvti_types[IFLA_VTI_MAX + 1] = {
|
||||
static const NLType rtnl_link_info_data_ipvti_types[] = {
|
||||
[IFLA_VTI_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VTI_IKEY] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_VTI_OKEY] = { .type = NETLINK_TYPE_U32 },
|
||||
@ -247,7 +247,7 @@ static const NLType rtnl_link_info_data_ipvti_types[IFLA_VTI_MAX + 1] = {
|
||||
[IFLA_VTI_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_data_ip6tnl_types[IFLA_IPTUN_MAX + 1] = {
|
||||
static const NLType rtnl_link_info_data_ip6tnl_types[] = {
|
||||
[IFLA_IPTUN_LINK] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_IPTUN_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFLA_IPTUN_REMOTE] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
@ -259,7 +259,7 @@ static const NLType rtnl_link_info_data_ip6tnl_types[IFLA_IPTUN_MAX + 1] = {
|
||||
};
|
||||
|
||||
/* these strings must match the .kind entries in the kernel */
|
||||
static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_MAX] = {
|
||||
static const char* const nl_union_link_info_data_table[] = {
|
||||
[NL_UNION_LINK_INFO_DATA_BOND] = "bond",
|
||||
[NL_UNION_LINK_INFO_DATA_BRIDGE] = "bridge",
|
||||
[NL_UNION_LINK_INFO_DATA_VLAN] = "vlan",
|
||||
@ -282,7 +282,7 @@ static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
|
||||
|
||||
static const NLTypeSystem rtnl_link_info_data_type_systems[_NL_UNION_LINK_INFO_DATA_MAX] = {
|
||||
static const NLTypeSystem rtnl_link_info_data_type_systems[] = {
|
||||
[NL_UNION_LINK_INFO_DATA_BOND] = { .count = ELEMENTSOF(rtnl_link_info_data_bond_types),
|
||||
.types = rtnl_link_info_data_bond_types },
|
||||
[NL_UNION_LINK_INFO_DATA_BRIDGE] = { .count = ELEMENTSOF(rtnl_link_info_data_bridge_types),
|
||||
@ -328,7 +328,7 @@ static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
|
||||
.match = IFLA_INFO_KIND,
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_info_types[IFLA_INFO_MAX + 1] = {
|
||||
static const NLType rtnl_link_info_types[] = {
|
||||
[IFLA_INFO_KIND] = { .type = NETLINK_TYPE_STRING },
|
||||
[IFLA_INFO_DATA] = { .type = NETLINK_TYPE_UNION, .type_system_union = &rtnl_link_info_data_type_system_union},
|
||||
/*
|
||||
@ -343,7 +343,7 @@ static const NLTypeSystem rtnl_link_info_type_system = {
|
||||
.types = rtnl_link_info_types,
|
||||
};
|
||||
|
||||
static const struct NLType rtnl_prot_info_bridge_port_types[IFLA_BRPORT_MAX + 1] = {
|
||||
static const struct NLType rtnl_prot_info_bridge_port_types[] = {
|
||||
[IFLA_BRPORT_STATE] = { .type = NETLINK_TYPE_U8 },
|
||||
[IFLA_BRPORT_COST] = { .type = NETLINK_TYPE_U32 },
|
||||
[IFLA_BRPORT_PRIORITY] = { .type = NETLINK_TYPE_U16 },
|
||||
@ -357,7 +357,7 @@ static const struct NLType rtnl_prot_info_bridge_port_types[IFLA_BRPORT_MAX + 1]
|
||||
[IFLA_BRPORT_LEARNING_SYNC] = { .type = NETLINK_TYPE_U8 },
|
||||
};
|
||||
|
||||
static const NLTypeSystem rtnl_prot_info_type_systems[AF_MAX] = {
|
||||
static const NLTypeSystem rtnl_prot_info_type_systems[] = {
|
||||
[AF_BRIDGE] = { .count = ELEMENTSOF(rtnl_prot_info_bridge_port_types),
|
||||
.types = rtnl_prot_info_bridge_port_types },
|
||||
};
|
||||
@ -368,7 +368,7 @@ static const NLTypeSystemUnion rtnl_prot_info_type_system_union = {
|
||||
.match_type = NL_MATCH_PROTOCOL,
|
||||
};
|
||||
|
||||
static const struct NLType rtnl_af_spec_inet6_types[IFLA_INET6_MAX + 1] = {
|
||||
static const struct NLType rtnl_af_spec_inet6_types[] = {
|
||||
[IFLA_INET6_FLAGS] = { .type = NETLINK_TYPE_U32 },
|
||||
/*
|
||||
IFLA_INET6_CONF,
|
||||
@ -386,7 +386,7 @@ static const NLTypeSystem rtnl_af_spec_inet6_type_system = {
|
||||
.types = rtnl_af_spec_inet6_types,
|
||||
};
|
||||
|
||||
static const NLType rtnl_af_spec_types[AF_MAX + 1] = {
|
||||
static const NLType rtnl_af_spec_types[] = {
|
||||
[AF_INET6] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_af_spec_inet6_type_system },
|
||||
};
|
||||
|
||||
@ -395,7 +395,7 @@ static const NLTypeSystem rtnl_af_spec_type_system = {
|
||||
.types = rtnl_af_spec_types,
|
||||
};
|
||||
|
||||
static const NLType rtnl_link_types[IFLA_MAX + 1 ] = {
|
||||
static const NLType rtnl_link_types[] = {
|
||||
[IFLA_ADDRESS] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[IFLA_BROADCAST] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[IFLA_IFNAME] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
|
||||
@ -454,7 +454,7 @@ static const NLTypeSystem rtnl_link_type_system = {
|
||||
|
||||
/* IFA_FLAGS was defined in kernel 3.14, but we still support older
|
||||
* kernels where IFA_MAX is lower. */
|
||||
static const NLType rtnl_address_types[CONST_MAX(IFA_MAX, IFA_FLAGS) + 1] = {
|
||||
static const NLType rtnl_address_types[] = {
|
||||
[IFA_ADDRESS] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFA_LOCAL] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[IFA_LABEL] = { .type = NETLINK_TYPE_STRING, .size = IFNAMSIZ - 1 },
|
||||
@ -472,7 +472,7 @@ static const NLTypeSystem rtnl_address_type_system = {
|
||||
.types = rtnl_address_types,
|
||||
};
|
||||
|
||||
static const NLType rtnl_route_types[RTA_MAX + 1] = {
|
||||
static const NLType rtnl_route_types[] = {
|
||||
[RTA_DST] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
|
||||
[RTA_SRC] = { .type = NETLINK_TYPE_IN_ADDR }, /* 6? */
|
||||
[RTA_IIF] = { .type = NETLINK_TYPE_U32 },
|
||||
@ -490,7 +490,11 @@ static const NLType rtnl_route_types[RTA_MAX + 1] = {
|
||||
RTA_TABLE,
|
||||
RTA_MARK,
|
||||
RTA_MFC_STATS,
|
||||
RTA_VIA,
|
||||
RTA_NEWDST,
|
||||
*/
|
||||
[RTA_PREF] = { .type = NETLINK_TYPE_U8 },
|
||||
|
||||
};
|
||||
|
||||
static const NLTypeSystem rtnl_route_type_system = {
|
||||
@ -498,7 +502,7 @@ static const NLTypeSystem rtnl_route_type_system = {
|
||||
.types = rtnl_route_types,
|
||||
};
|
||||
|
||||
static const NLType rtnl_neigh_types[NDA_MAX + 1] = {
|
||||
static const NLType rtnl_neigh_types[] = {
|
||||
[NDA_DST] = { .type = NETLINK_TYPE_IN_ADDR },
|
||||
[NDA_LLADDR] = { .type = NETLINK_TYPE_ETHER_ADDR },
|
||||
[NDA_CACHEINFO] = { .type = NETLINK_TYPE_CACHE_INFO, .size = sizeof(struct nda_cacheinfo) },
|
||||
@ -514,7 +518,7 @@ static const NLTypeSystem rtnl_neigh_type_system = {
|
||||
.types = rtnl_neigh_types,
|
||||
};
|
||||
|
||||
static const NLType rtnl_types[RTM_MAX + 1] = {
|
||||
static const NLType rtnl_types[] = {
|
||||
[NLMSG_DONE] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = 0 },
|
||||
[NLMSG_ERROR] = { .type = NETLINK_TYPE_NESTED, .type_system = &empty_type_system, .size = sizeof(struct nlmsgerr) },
|
||||
[RTM_NEWLINK] = { .type = NETLINK_TYPE_NESTED, .type_system = &rtnl_link_type_system, .size = sizeof(struct ifinfomsg) },
|
||||
|
@ -84,6 +84,35 @@ int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags) {
|
||||
struct rtmsg *rtm;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->hdr, -EINVAL);
|
||||
assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
|
||||
|
||||
rtm = NLMSG_DATA(m->hdr);
|
||||
|
||||
rtm->rtm_flags = flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_route_get_flags(sd_netlink_message *m, unsigned *flags) {
|
||||
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(flags, -EINVAL);
|
||||
|
||||
rtm = NLMSG_DATA(m->hdr);
|
||||
|
||||
*flags = rtm->rtm_flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family) {
|
||||
struct rtmsg *rtm;
|
||||
|
||||
|
@ -248,6 +248,8 @@ static int address_add_internal(Link *link, Set **addresses,
|
||||
address->family = family;
|
||||
address->in_addr = *in_addr;
|
||||
address->prefixlen = prefixlen;
|
||||
/* Consider address tentative until we get the real flags from the kernel */
|
||||
address->flags = IFA_F_TENTATIVE;
|
||||
|
||||
r = set_ensure_allocated(addresses, &address_hash_ops);
|
||||
if (r < 0)
|
||||
@ -327,13 +329,13 @@ static int address_release(Address *address) {
|
||||
|
||||
int address_update(Address *address, unsigned char flags, unsigned char scope, struct ifa_cacheinfo *cinfo) {
|
||||
bool ready;
|
||||
int r;
|
||||
|
||||
assert(address);
|
||||
assert(cinfo);
|
||||
|
||||
ready = address_is_ready(address);
|
||||
|
||||
address->added = true;
|
||||
address->flags = flags;
|
||||
address->scope = scope;
|
||||
address->cinfo = *cinfo;
|
||||
@ -341,8 +343,17 @@ int address_update(Address *address, unsigned char flags, unsigned char scope, s
|
||||
if (address->link) {
|
||||
link_update_operstate(address->link);
|
||||
|
||||
if (!ready && address_is_ready(address))
|
||||
if (!ready && address_is_ready(address)) {
|
||||
link_check_ready(address->link);
|
||||
|
||||
if (address->family == AF_INET6 &&
|
||||
in_addr_is_link_local(AF_INET6, &address->in_addr) &&
|
||||
!address->link->ipv6ll_address) {
|
||||
r = link_ipv6ll_gained(address->link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -769,5 +780,5 @@ int config_parse_label(const char *unit,
|
||||
bool address_is_ready(const Address *a) {
|
||||
assert(a);
|
||||
|
||||
return a->added && !(a->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED));
|
||||
return !(a->flags & (IFA_F_TENTATIVE | IFA_F_DEPRECATED));
|
||||
}
|
||||
|
@ -52,7 +52,6 @@ struct Address {
|
||||
union in_addr_union in_addr;
|
||||
union in_addr_union in_addr_peer;
|
||||
|
||||
bool added:1;
|
||||
bool ip_masquerade_done:1;
|
||||
|
||||
LIST_FIELDS(Address, addresses);
|
||||
|
@ -34,7 +34,7 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->dhcp4_messages);
|
||||
assert(link->dhcp4_messages > 0);
|
||||
|
||||
link->dhcp4_messages --;
|
||||
|
||||
@ -44,7 +44,7 @@ static int dhcp4_route_handler(sd_netlink *rtnl, sd_netlink_message *m,
|
||||
link_enter_failed(link);
|
||||
}
|
||||
|
||||
if (!link->dhcp4_messages) {
|
||||
if (link->dhcp4_messages == 0) {
|
||||
link->dhcp4_configured = true;
|
||||
link_check_ready(link);
|
||||
}
|
||||
|
@ -165,83 +165,82 @@ static void dhcp6_handler(sd_dhcp6_client *client, int event, void *userdata) {
|
||||
link_check_ready(link);
|
||||
}
|
||||
|
||||
int dhcp6_configure(Link *link, bool inf_req) {
|
||||
int r, information_request;
|
||||
int dhcp6_request_address(Link *link) {
|
||||
int r, inf_req;
|
||||
bool running;
|
||||
|
||||
assert_return(link, -EINVAL);
|
||||
|
||||
link->dhcp6_configured = false;
|
||||
|
||||
if (link->dhcp6_client) {
|
||||
r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &information_request);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Could not get DHCPv6 Information request setting: %m");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (information_request && !inf_req) {
|
||||
r = sd_dhcp6_client_stop(link->dhcp6_client);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Could not stop DHCPv6 while setting Managed mode: %m");
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = sd_dhcp6_client_set_information_request(link->dhcp6_client, false);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Could not unset DHCPv6 Information request: %m");
|
||||
goto error;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
r = sd_dhcp6_client_start(link->dhcp6_client);
|
||||
if (r < 0 && r != -EALREADY) {
|
||||
log_link_warning_errno(link, r, "Could not restart DHCPv6: %m");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (r == -EALREADY)
|
||||
link->dhcp6_configured = true;
|
||||
assert(link);
|
||||
assert(link->dhcp6_client);
|
||||
|
||||
r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!inf_req)
|
||||
return 0;
|
||||
|
||||
r = sd_dhcp6_client_is_running(link->dhcp6_client);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else
|
||||
running = !!r;
|
||||
|
||||
if (running) {
|
||||
r = sd_dhcp6_client_stop(link->dhcp6_client);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_dhcp6_client_new(&link->dhcp6_client);
|
||||
r = sd_dhcp6_client_set_information_request(link->dhcp6_client, false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (running) {
|
||||
r = sd_dhcp6_client_start(link->dhcp6_client);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp6_configure(Link *link) {
|
||||
sd_dhcp6_client *client = NULL;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
r = sd_dhcp6_client_new(&client);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_dhcp6_client_attach_event(client, NULL, 0);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0);
|
||||
r = sd_dhcp6_client_set_information_request(client, true);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
return r;
|
||||
|
||||
r = sd_dhcp6_client_set_mac(link->dhcp6_client,
|
||||
r = sd_dhcp6_client_set_mac(client,
|
||||
(const uint8_t *) &link->mac,
|
||||
sizeof (link->mac), ARPHRD_ETHER);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_dhcp6_client_set_index(link->dhcp6_client, link->ifindex);
|
||||
r = sd_dhcp6_client_set_index(client, link->ifindex);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler,
|
||||
link);
|
||||
r = sd_dhcp6_client_set_callback(client, dhcp6_handler, link);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
if (inf_req) {
|
||||
r = sd_dhcp6_client_set_information_request(link->dhcp6_client, true);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
}
|
||||
link->dhcp6_client = client;
|
||||
|
||||
r = sd_dhcp6_client_start(link->dhcp6_client);
|
||||
if (r < 0)
|
||||
goto error;
|
||||
return 0;
|
||||
|
||||
return r;
|
||||
|
||||
error:
|
||||
link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client);
|
||||
error:
|
||||
sd_dhcp6_client_unref(client);
|
||||
return r;
|
||||
}
|
||||
|
@ -124,6 +124,28 @@ static bool link_ipv6_forward_enabled(Link *link) {
|
||||
return link->network->ip_forward & ADDRESS_FAMILY_IPV6;
|
||||
}
|
||||
|
||||
bool link_ipv6_accept_ra_enabled(Link *link) {
|
||||
if (link->flags & IFF_LOOPBACK)
|
||||
return false;
|
||||
|
||||
if (!link->network)
|
||||
return false;
|
||||
|
||||
/* If unset use system default (enabled if local forwarding is disabled.
|
||||
* disabled if local forwarding is enabled).
|
||||
* If set, ignore or enforce RA independent of local forwarding state.
|
||||
*/
|
||||
if (link->network->ipv6_accept_ra < 0)
|
||||
/* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
|
||||
return !link_ipv6_forward_enabled(link);
|
||||
else if (link->network->ipv6_accept_ra > 0)
|
||||
/* accept RA even if ip_forward is enabled */
|
||||
return true;
|
||||
else
|
||||
/* ignore RA */
|
||||
return false;
|
||||
}
|
||||
|
||||
static IPv6PrivacyExtensions link_ipv6_privacy_extensions(Link *link) {
|
||||
if (link->flags & IFF_LOOPBACK)
|
||||
return _IPV6_PRIVACY_EXTENSIONS_INVALID;
|
||||
@ -485,13 +507,13 @@ static int link_stop_clients(Link *link) {
|
||||
r = log_link_warning_errno(link, r, "Could not stop IPv4 link-local: %m");
|
||||
}
|
||||
|
||||
if(link->ndisc_router_discovery) {
|
||||
if (link->dhcp6_client) {
|
||||
k = sd_dhcp6_client_stop(link->dhcp6_client);
|
||||
if (k < 0)
|
||||
r = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
|
||||
}
|
||||
if (link->dhcp6_client) {
|
||||
k = sd_dhcp6_client_stop(link->dhcp6_client);
|
||||
if (k < 0)
|
||||
r = log_link_warning_errno(link, r, "Could not stop DHCPv6 client: %m");
|
||||
}
|
||||
|
||||
if (link->ndisc_router_discovery) {
|
||||
k = sd_ndisc_stop(link->ndisc_router_discovery);
|
||||
if (k < 0)
|
||||
r = log_link_warning_errno(link, r, "Could not stop IPv6 Router Discovery: %m");
|
||||
@ -581,6 +603,10 @@ void link_check_ready(Link *link) {
|
||||
!link->ipv4ll_route)
|
||||
return;
|
||||
|
||||
if (link_ipv6ll_enabled(link))
|
||||
if (!link->ipv6ll_address)
|
||||
return;
|
||||
|
||||
if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) &&
|
||||
!link->dhcp4_configured) ||
|
||||
(link_dhcp6_enabled(link) && !link_dhcp4_enabled(link) &&
|
||||
@ -589,6 +615,9 @@ void link_check_ready(Link *link) {
|
||||
!link->dhcp4_configured && !link->dhcp6_configured))
|
||||
return;
|
||||
|
||||
if (link_ipv6_accept_ra_enabled(link) && !link->ndisc_configured)
|
||||
return;
|
||||
|
||||
SET_FOREACH(a, link->addresses, i)
|
||||
if (!address_is_ready(a))
|
||||
return;
|
||||
@ -1213,6 +1242,34 @@ static void lldp_handler(sd_lldp *lldp, int event, void *userdata) {
|
||||
}
|
||||
}
|
||||
|
||||
static int link_acquire_ipv6_conf(Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (link_dhcp6_enabled(link)) {
|
||||
assert(link->dhcp6_client);
|
||||
|
||||
log_link_debug(link, "Acquiring DHCPv6 lease");
|
||||
|
||||
r = sd_dhcp6_client_start(link->dhcp6_client);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m");
|
||||
}
|
||||
|
||||
if (link_ipv6_accept_ra_enabled(link)) {
|
||||
assert(link->ndisc_router_discovery);
|
||||
|
||||
log_link_debug(link, "Discovering IPv6 routers");
|
||||
|
||||
r = sd_ndisc_router_discovery_start(link->ndisc_router_discovery);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_acquire_conf(Link *link) {
|
||||
int r;
|
||||
|
||||
@ -1241,16 +1298,6 @@ static int link_acquire_conf(Link *link) {
|
||||
return log_link_warning_errno(link, r, "Could not acquire DHCPv4 lease: %m");
|
||||
}
|
||||
|
||||
if (link_dhcp6_enabled(link)) {
|
||||
assert(link->ndisc_router_discovery);
|
||||
|
||||
log_link_debug(link, "Discovering IPv6 routers");
|
||||
|
||||
r = sd_ndisc_router_discovery_start(link->ndisc_router_discovery);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
|
||||
}
|
||||
|
||||
if (link_lldp_enabled(link)) {
|
||||
assert(link->lldp);
|
||||
|
||||
@ -1883,7 +1930,7 @@ static int link_set_ipv6_privacy_extensions(Link *link) {
|
||||
}
|
||||
|
||||
static int link_set_ipv6_accept_ra(Link *link) {
|
||||
const char *p = NULL, *v = NULL;
|
||||
const char *p = NULL;
|
||||
int r;
|
||||
|
||||
/* Make this a NOP if IPv6 is not available */
|
||||
@ -1893,29 +1940,16 @@ static int link_set_ipv6_accept_ra(Link *link) {
|
||||
if (link->flags & IFF_LOOPBACK)
|
||||
return 0;
|
||||
|
||||
/* If unset use system default (enabled if local forwarding is disabled.
|
||||
* disabled if local forwarding is enabled).
|
||||
* If set, ignore or enforce RA independent of local forwarding state.
|
||||
*/
|
||||
if (link->network->ipv6_accept_ra < 0)
|
||||
/* default to accept RA if ip_forward is disabled and ignore RA if ip_forward is enabled */
|
||||
v = "1";
|
||||
else if (link->network->ipv6_accept_ra > 0)
|
||||
/* "2" means accept RA even if ip_forward is enabled */
|
||||
v = "2";
|
||||
else
|
||||
/* "0" means ignore RA */
|
||||
v = "0";
|
||||
|
||||
p = strjoina("/proc/sys/net/ipv6/conf/", link->ifname, "/accept_ra");
|
||||
|
||||
r = write_string_file(p, v, 0);
|
||||
/* we handle router advertisments ourselves, tell the kernel to GTFO */
|
||||
r = write_string_file(p, "0", 0);
|
||||
if (r < 0) {
|
||||
/* If the right value is set anyway, don't complain */
|
||||
if (verify_one_line_file(p, v) > 0)
|
||||
if (verify_one_line_file(p, "0") > 0)
|
||||
return 0;
|
||||
|
||||
log_link_warning_errno(link, r, "Cannot configure IPv6 accept_ra for interface: %m");
|
||||
log_link_warning_errno(link, r, "Cannot disable kernel IPv6 accept_ra for interface: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2041,6 +2075,12 @@ static int link_configure(Link *link) {
|
||||
}
|
||||
|
||||
if (link_dhcp6_enabled(link)) {
|
||||
r = dhcp6_configure(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (link_ipv6_accept_ra_enabled(link)) {
|
||||
r = ndisc_configure(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -2065,6 +2105,12 @@ static int link_configure(Link *link) {
|
||||
r = link_acquire_conf(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (link->ipv6ll_address) {
|
||||
r = link_acquire_ipv6_conf(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return link_enter_join_netdev(link);
|
||||
@ -2411,6 +2457,27 @@ failed:
|
||||
return r;
|
||||
}
|
||||
|
||||
int link_ipv6ll_gained(Link *link) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
log_link_info(link, "Gained IPv6LL");
|
||||
|
||||
link->ipv6ll_address = true;
|
||||
link_check_ready(link);
|
||||
|
||||
if (link->network) {
|
||||
r = link_acquire_ipv6_conf(link);
|
||||
if (r < 0) {
|
||||
link_enter_failed(link);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int link_carrier_gained(Link *link) {
|
||||
int r;
|
||||
|
||||
@ -2639,9 +2706,8 @@ int link_save(Link *link) {
|
||||
sd_dhcp6_lease *dhcp6_lease = NULL;
|
||||
|
||||
if (link->dhcp6_client) {
|
||||
r = sd_dhcp6_client_get_lease(link->dhcp6_client,
|
||||
&dhcp6_lease);
|
||||
if (r < 0)
|
||||
r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease);
|
||||
if (r < 0 && r != -ENOMSG)
|
||||
log_link_debug(link, "No DHCPv6 lease");
|
||||
}
|
||||
|
||||
|
@ -95,10 +95,13 @@ struct Link {
|
||||
unsigned dhcp4_messages;
|
||||
bool dhcp4_configured;
|
||||
bool dhcp6_configured;
|
||||
unsigned ndisc_messages;
|
||||
bool ndisc_configured;
|
||||
|
||||
sd_ipv4ll *ipv4ll;
|
||||
bool ipv4ll_address;
|
||||
bool ipv4ll_route;
|
||||
bool ipv4ll_address:1;
|
||||
bool ipv4ll_route:1;
|
||||
bool ipv6ll_address:1;
|
||||
|
||||
bool static_configured;
|
||||
|
||||
@ -141,13 +144,16 @@ int link_save(Link *link);
|
||||
int link_carrier_reset(Link *link);
|
||||
bool link_has_carrier(Link *link);
|
||||
|
||||
int link_ipv6ll_gained(Link *link);
|
||||
|
||||
int link_set_mtu(Link *link, uint32_t mtu);
|
||||
int link_set_hostname(Link *link, const char *hostname);
|
||||
int link_set_timezone(Link *link, const char *timezone);
|
||||
|
||||
int ipv4ll_configure(Link *link);
|
||||
int dhcp4_configure(Link *link);
|
||||
int dhcp6_configure(Link *link, bool information_request);
|
||||
int dhcp6_configure(Link *link);
|
||||
int dhcp6_request_address(Link *link);
|
||||
int ndisc_configure(Link *link);
|
||||
|
||||
bool link_lldp_enabled(Link *link);
|
||||
@ -156,6 +162,7 @@ bool link_ipv6ll_enabled(Link *link);
|
||||
bool link_dhcp4_server_enabled(Link *link);
|
||||
bool link_dhcp4_enabled(Link *link);
|
||||
bool link_dhcp6_enabled(Link *link);
|
||||
bool link_ipv6_accept_ra_enabled(Link *link);
|
||||
|
||||
const char* link_state_to_string(LinkState s) _const_;
|
||||
LinkState link_state_from_string(const char *s) _pure_;
|
||||
|
@ -577,9 +577,7 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
||||
|
||||
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
|
||||
if (cinfo.ifa_valid != CACHE_INFO_INFINITY_LIFE_TIME)
|
||||
valid_str = format_timespan(valid_buf, FORMAT_TIMESPAN_MAX,
|
||||
cinfo.ifa_valid * USEC_PER_SEC,
|
||||
USEC_PER_SEC);
|
||||
@ -590,7 +588,8 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
||||
switch (type) {
|
||||
case RTM_NEWADDR:
|
||||
if (address)
|
||||
log_link_debug(link, "Updating address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
|
||||
log_link_debug(link, "Updating address: %s/%u (valid %s%s)", buf, prefixlen,
|
||||
valid_str ? "for " : "forever", valid_str ?: "");
|
||||
else {
|
||||
/* An address appeared that we did not request */
|
||||
r = address_add_foreign(link, family, &in_addr, prefixlen, &address);
|
||||
@ -598,7 +597,8 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
||||
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);
|
||||
log_link_debug(link, "Adding address: %s/%u (valid %s%s)", buf, prefixlen,
|
||||
valid_str ? "for " : "forever", valid_str ?: "");
|
||||
}
|
||||
|
||||
address_update(address, flags, scope, &cinfo);
|
||||
@ -608,10 +608,12 @@ int manager_rtnl_process_address(sd_netlink *rtnl, sd_netlink_message *message,
|
||||
case RTM_DELADDR:
|
||||
|
||||
if (address) {
|
||||
log_link_debug(link, "Removing address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
|
||||
log_link_debug(link, "Removing address: %s/%u (valid %s%s)", buf, prefixlen,
|
||||
valid_str ? "for " : "forever", valid_str ?: "");
|
||||
address_drop(address);
|
||||
} else
|
||||
log_link_warning(link, "Removing non-existent address: %s/%u (valid for %s)", buf, prefixlen, valid_str);
|
||||
log_link_warning(link, "Removing non-existent address: %s/%u (valid %s%s)", buf, prefixlen,
|
||||
valid_str ? "for " : "forever", valid_str ?: "");
|
||||
|
||||
break;
|
||||
default:
|
||||
@ -1091,7 +1093,8 @@ static bool manager_check_idle(void *userdata) {
|
||||
link_ipv4ll_enabled(link) ||
|
||||
link_dhcp4_server_enabled(link) ||
|
||||
link_dhcp4_enabled(link) ||
|
||||
link_dhcp6_enabled(link))
|
||||
link_dhcp6_enabled(link) ||
|
||||
link_ipv6_accept_ra_enabled(link))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -20,14 +20,132 @@
|
||||
***/
|
||||
|
||||
#include <netinet/ether.h>
|
||||
#include <netinet/icmp6.h>
|
||||
#include <linux/if.h>
|
||||
|
||||
#include "sd-ndisc.h"
|
||||
|
||||
#include "networkd-link.h"
|
||||
|
||||
static void ndisc_router_handler(sd_ndisc *nd, int event, void *userdata) {
|
||||
static int ndisc_netlink_handler(sd_netlink *rtnl, sd_netlink_message *m, void *userdata) {
|
||||
_cleanup_link_unref_ Link *link = userdata;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->ndisc_messages > 0);
|
||||
|
||||
link->ndisc_messages --;
|
||||
|
||||
r = sd_netlink_message_get_errno(m);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
log_link_error_errno(link, r, "Could not set NDisc route or address: %m");
|
||||
link_enter_failed(link);
|
||||
}
|
||||
|
||||
if (link->ndisc_messages == 0) {
|
||||
link->ndisc_configured = true;
|
||||
link_check_ready(link);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void ndisc_prefix_autonomous_handler(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen,
|
||||
unsigned lifetime_preferred, unsigned lifetime_valid, void *userdata) {
|
||||
_cleanup_address_free_ Address *address = NULL;
|
||||
Link *link = userdata;
|
||||
usec_t time_now;
|
||||
int r;
|
||||
|
||||
assert(nd);
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return;
|
||||
|
||||
r = address_new(&address);
|
||||
if (r < 0) {
|
||||
log_link_error_errno(link, r, "Could not allocate address: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
assert_se(sd_event_now(link->manager->event, clock_boottime_or_monotonic(), &time_now) >= 0);
|
||||
|
||||
address->family = AF_INET6;
|
||||
address->in_addr.in6 = *prefix;
|
||||
if (in_addr_is_null(AF_INET6, (const union in_addr_union *) &link->network->ipv6_token) == 0)
|
||||
memcpy(&address->in_addr.in6 + 8, &link->network->ipv6_token + 8, 8);
|
||||
else {
|
||||
/* see RFC4291 section 2.5.1 */
|
||||
address->in_addr.in6.__in6_u.__u6_addr8[8] = link->mac.ether_addr_octet[0];
|
||||
address->in_addr.in6.__in6_u.__u6_addr8[8] ^= 1 << 1;
|
||||
address->in_addr.in6.__in6_u.__u6_addr8[9] = link->mac.ether_addr_octet[1];
|
||||
address->in_addr.in6.__in6_u.__u6_addr8[10] = link->mac.ether_addr_octet[2];
|
||||
address->in_addr.in6.__in6_u.__u6_addr8[11] = 0xff;
|
||||
address->in_addr.in6.__in6_u.__u6_addr8[12] = 0xfe;
|
||||
address->in_addr.in6.__in6_u.__u6_addr8[13] = link->mac.ether_addr_octet[3];
|
||||
address->in_addr.in6.__in6_u.__u6_addr8[14] = link->mac.ether_addr_octet[4];
|
||||
address->in_addr.in6.__in6_u.__u6_addr8[15] = link->mac.ether_addr_octet[5];
|
||||
}
|
||||
address->prefixlen = prefixlen;
|
||||
address->flags = IFA_F_NOPREFIXROUTE;
|
||||
address->cinfo.ifa_prefered = lifetime_preferred;
|
||||
address->cinfo.ifa_valid = lifetime_valid;
|
||||
|
||||
r = address_configure(address, link, ndisc_netlink_handler, true);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Could not set SLAAC address: %m");
|
||||
link_enter_failed(link);
|
||||
return;
|
||||
}
|
||||
|
||||
link->ndisc_messages ++;
|
||||
}
|
||||
|
||||
static void ndisc_prefix_onlink_handler(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen, unsigned lifetime, void *userdata) {
|
||||
_cleanup_route_free_ Route *route = NULL;
|
||||
Link *link = userdata;
|
||||
usec_t time_now;
|
||||
int r;
|
||||
|
||||
assert(nd);
|
||||
assert(link);
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return;
|
||||
|
||||
r = route_new(&route);
|
||||
if (r < 0) {
|
||||
log_link_error_errno(link, r, "Could not allocate route: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
assert_se(sd_event_now(link->manager->event, clock_boottime_or_monotonic(), &time_now) >= 0);
|
||||
|
||||
route->family = AF_INET6;
|
||||
route->table = RT_TABLE_MAIN;
|
||||
route->protocol = RTPROT_RA;
|
||||
route->flags = RTM_F_PREFIX;
|
||||
route->dst.in6 = *prefix;
|
||||
route->dst_prefixlen = prefixlen;
|
||||
route->lifetime = time_now + lifetime * USEC_PER_SEC;
|
||||
|
||||
r = route_configure(route, link, ndisc_netlink_handler);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Could not set prefix route: %m");
|
||||
link_enter_failed(link);
|
||||
return;
|
||||
}
|
||||
|
||||
link->ndisc_messages ++;
|
||||
}
|
||||
|
||||
static void ndisc_router_handler(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata) {
|
||||
_cleanup_route_free_ Route *route = NULL;
|
||||
Link *link = userdata;
|
||||
usec_t time_now;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
assert(link->network);
|
||||
@ -36,27 +154,64 @@ static void ndisc_router_handler(sd_ndisc *nd, int event, void *userdata) {
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return;
|
||||
|
||||
switch(event) {
|
||||
case SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE:
|
||||
if (flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER)) {
|
||||
if (flags & ND_RA_FLAG_MANAGED)
|
||||
dhcp6_request_address(link);
|
||||
|
||||
r = sd_dhcp6_client_start(link->dhcp6_client);
|
||||
if (r < 0 && r != -EALREADY)
|
||||
log_link_warning_errno(link, r, "Starting DHCPv6 client on NDisc request failed: %m");
|
||||
}
|
||||
|
||||
if (!gateway)
|
||||
return;
|
||||
|
||||
case SD_NDISC_EVENT_ROUTER_ADVERTISMENT_OTHER:
|
||||
dhcp6_configure(link, true);
|
||||
r = route_new(&route);
|
||||
if (r < 0) {
|
||||
log_link_error_errno(link, r, "Could not allocate route: %m");
|
||||
return;
|
||||
}
|
||||
|
||||
assert_se(sd_event_now(link->manager->event, clock_boottime_or_monotonic(), &time_now) >= 0);
|
||||
|
||||
route->family = AF_INET6;
|
||||
route->table = RT_TABLE_MAIN;
|
||||
route->protocol = RTPROT_RA;
|
||||
route->pref = pref;
|
||||
route->gw.in6 = *gateway;
|
||||
route->lifetime = time_now + lifetime * USEC_PER_SEC;
|
||||
|
||||
r = route_configure(route, link, ndisc_netlink_handler);
|
||||
if (r < 0) {
|
||||
log_link_warning_errno(link, r, "Could not set default route: %m");
|
||||
link_enter_failed(link);
|
||||
return;
|
||||
}
|
||||
|
||||
link->ndisc_messages ++;
|
||||
}
|
||||
|
||||
static void ndisc_handler(sd_ndisc *nd, int event, void *userdata) {
|
||||
Link *link = userdata;
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
|
||||
return;
|
||||
|
||||
switch (event) {
|
||||
case SD_NDISC_EVENT_TIMEOUT:
|
||||
dhcp6_request_address(link);
|
||||
|
||||
r = sd_dhcp6_client_start(link->dhcp6_client);
|
||||
if (r < 0 && r != -EALREADY)
|
||||
log_link_warning_errno(link, r, "Starting DHCPv6 client after NDisc timeout failed: %m");
|
||||
break;
|
||||
case SD_NDISC_EVENT_ROUTER_ADVERTISMENT_TIMEOUT:
|
||||
case SD_NDISC_EVENT_ROUTER_ADVERTISMENT_MANAGED:
|
||||
dhcp6_configure(link, false);
|
||||
|
||||
case SD_NDISC_EVENT_STOP:
|
||||
break;
|
||||
|
||||
default:
|
||||
if (event < 0)
|
||||
log_link_warning_errno(link, event, "IPv6 Neighbor Discover error: %m");
|
||||
else
|
||||
log_link_warning(link, "IPv6 Neighbor Discovery unknown event: %d", event);
|
||||
|
||||
break;
|
||||
log_link_warning(link, "IPv6 Neighbor Discovery unknown event: %d", event);
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +237,11 @@ int ndisc_configure(Link *link) {
|
||||
return r;
|
||||
|
||||
r = sd_ndisc_set_callback(link->ndisc_router_discovery,
|
||||
ndisc_router_handler, link);
|
||||
ndisc_router_handler,
|
||||
ndisc_prefix_onlink_handler,
|
||||
ndisc_prefix_autonomous_handler,
|
||||
ndisc_handler,
|
||||
link);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -494,10 +494,18 @@ int route_configure(Route *route, Link *link,
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not set scope: %m");
|
||||
|
||||
r = sd_rtnl_message_route_set_flags(req, route->flags);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Colud not set flags: %m");
|
||||
|
||||
r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");
|
||||
|
||||
r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not append RTA_PREF attribute: %m");
|
||||
|
||||
r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not append RTA_OIF attribute: %m");
|
||||
|
@ -40,6 +40,8 @@ struct Route {
|
||||
unsigned char tos;
|
||||
uint32_t priority; /* note that ip(8) calls this 'metric' */
|
||||
unsigned char table;
|
||||
unsigned char pref;
|
||||
unsigned flags;
|
||||
|
||||
union in_addr_union gw;
|
||||
union in_addr_union dst;
|
||||
|
@ -62,6 +62,7 @@ int sd_dhcp6_client_get_lease(sd_dhcp6_client *client, sd_dhcp6_lease **ret);
|
||||
|
||||
int sd_dhcp6_client_stop(sd_dhcp6_client *client);
|
||||
int sd_dhcp6_client_start(sd_dhcp6_client *client);
|
||||
int sd_dhcp6_client_is_running(sd_dhcp6_client *client);
|
||||
int sd_dhcp6_client_attach_event(sd_dhcp6_client *client, sd_event *event,
|
||||
int priority);
|
||||
int sd_dhcp6_client_detach_event(sd_dhcp6_client *client);
|
||||
|
@ -31,19 +31,25 @@
|
||||
_SD_BEGIN_DECLARATIONS;
|
||||
|
||||
enum {
|
||||
SD_NDISC_EVENT_ROUTER_ADVERTISMENT_NONE = 0,
|
||||
SD_NDISC_EVENT_ROUTER_ADVERTISMENT_TIMEOUT = 1,
|
||||
SD_NDISC_EVENT_ROUTER_ADVERTISMENT_OTHER = 2,
|
||||
SD_NDISC_EVENT_ROUTER_ADVERTISMENT_MANAGED = 3,
|
||||
SD_NDISC_EVENT_STOP = 0,
|
||||
SD_NDISC_EVENT_TIMEOUT = 1,
|
||||
};
|
||||
|
||||
typedef struct sd_ndisc sd_ndisc;
|
||||
|
||||
typedef void(*sd_ndisc_callback_t)(sd_ndisc *nd, int event,
|
||||
void *userdata);
|
||||
typedef void(*sd_ndisc_router_callback_t)(sd_ndisc *nd, uint8_t flags, const struct in6_addr *gateway, unsigned lifetime, int pref, void *userdata);
|
||||
typedef void(*sd_ndisc_prefix_onlink_callback_t)(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen,
|
||||
unsigned lifetime, void *userdata);
|
||||
typedef void(*sd_ndisc_prefix_autonomous_callback_t)(sd_ndisc *nd, const struct in6_addr *prefix, unsigned prefixlen,
|
||||
unsigned lifetime_prefered, unsigned lifetime_valid, void *userdata);
|
||||
typedef void(*sd_ndisc_callback_t)(sd_ndisc *nd, int event, void *userdata);
|
||||
|
||||
int sd_ndisc_set_callback(sd_ndisc *nd, sd_ndisc_callback_t cb,
|
||||
void *userdata);
|
||||
int sd_ndisc_set_callback(sd_ndisc *nd,
|
||||
sd_ndisc_router_callback_t rcb,
|
||||
sd_ndisc_prefix_onlink_callback_t plcb,
|
||||
sd_ndisc_prefix_autonomous_callback_t pacb,
|
||||
sd_ndisc_callback_t cb,
|
||||
void *userdata);
|
||||
int sd_ndisc_set_index(sd_ndisc *nd, int interface_index);
|
||||
int sd_ndisc_set_mac(sd_ndisc *nd, const struct ether_addr *mac_addr);
|
||||
|
||||
|
@ -136,6 +136,8 @@ int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned *type);
|
||||
int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char prefixlen);
|
||||
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_set_flags(sd_netlink_message *m, unsigned flags);
|
||||
int sd_rtnl_message_route_get_flags(sd_netlink_message *m, unsigned *flags);
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user