mirror of
https://github.com/systemd/systemd
synced 2024-10-02 22:37:25 +00:00
commit
92939fc4c0
|
@ -33,31 +33,23 @@
|
|||
#include "socket-util.h"
|
||||
|
||||
int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
|
||||
struct in6_pktinfo pktinfo = {
|
||||
.ipi6_ifindex = index,
|
||||
};
|
||||
union sockaddr_union src = {
|
||||
.in6.sin6_family = AF_INET6,
|
||||
.in6.sin6_port = htobe16(DHCP6_PORT_CLIENT),
|
||||
.in6.sin6_addr = IN6ADDR_ANY_INIT,
|
||||
.in6.sin6_scope_id = index,
|
||||
};
|
||||
_cleanup_close_ int s = -1;
|
||||
int r, off = 0, on = 1;
|
||||
|
||||
if (local_address)
|
||||
memcpy(&src.in6.sin6_addr, local_address,
|
||||
sizeof(src.in6.sin6_addr));
|
||||
assert(index > 0);
|
||||
assert(local_address);
|
||||
|
||||
s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
|
||||
IPPROTO_UDP);
|
||||
src.in6.sin6_addr = *local_address;
|
||||
|
||||
s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_UDP);
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
|
||||
r = setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &pktinfo,
|
||||
sizeof(pktinfo));
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
r = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
@ -66,6 +58,10 @@ int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
|
|||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
r = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
r = bind(s, &src.sa, sizeof(src.in6));
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "dhcp6-lease-internal.h"
|
||||
#include "dhcp6-protocol.h"
|
||||
#include "fd-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "network-internal.h"
|
||||
#include "random-util.h"
|
||||
#include "string-table.h"
|
||||
|
@ -46,6 +47,7 @@ struct sd_dhcp6_client {
|
|||
sd_event *event;
|
||||
int event_priority;
|
||||
int index;
|
||||
struct in6_addr local_address;
|
||||
uint8_t mac_addr[MAX_MAC_ADDR_LEN];
|
||||
size_t mac_addr_len;
|
||||
uint16_t arp_type;
|
||||
|
@ -133,6 +135,18 @@ int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address) {
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(local_address, -EINVAL);
|
||||
assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) local_address) > 0, -EINVAL);
|
||||
|
||||
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
|
||||
|
||||
client->local_address = *local_address;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_mac(
|
||||
sd_dhcp6_client *client,
|
||||
const uint8_t *addr, size_t addr_len,
|
||||
|
@ -1135,9 +1149,10 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
|
|||
assert_return(client, -EINVAL);
|
||||
assert_return(client->event, -EINVAL);
|
||||
assert_return(client->index > 0, -EINVAL);
|
||||
assert_return(in_addr_is_link_local(AF_INET6, (const union in_addr_union *) &client->local_address) > 0, -EINVAL);
|
||||
|
||||
if (!IN_SET(client->state, DHCP6_STATE_STOPPED))
|
||||
return -EALREADY;
|
||||
return -EBUSY;
|
||||
|
||||
r = client_reset(client);
|
||||
if (r < 0)
|
||||
|
@ -1151,7 +1166,7 @@ int sd_dhcp6_client_start(sd_dhcp6_client *client) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = dhcp6_network_bind_udp_socket(client->index, NULL);
|
||||
r = dhcp6_network_bind_udp_socket(client->index, &client->local_address);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
|
|
@ -628,7 +628,7 @@ int sd_ndisc_router_discovery_start(sd_ndisc *nd) {
|
|||
assert(nd->event);
|
||||
|
||||
if (nd->state != NDISC_STATE_IDLE)
|
||||
return -EINVAL;
|
||||
return -EBUSY;
|
||||
|
||||
if (nd->index < 1)
|
||||
return -EINVAL;
|
||||
|
|
|
@ -562,6 +562,7 @@ static void test_client_information_cb(sd_dhcp6_client *client, int event,
|
|||
sd_event *e = userdata;
|
||||
sd_dhcp6_lease *lease;
|
||||
struct in6_addr *addrs;
|
||||
struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
|
||||
char **domains;
|
||||
|
||||
assert_se(e);
|
||||
|
@ -590,6 +591,8 @@ static void test_client_information_cb(sd_dhcp6_client *client, int event,
|
|||
assert_se(sd_dhcp6_client_set_callback(client,
|
||||
test_client_solicit_cb, e) >= 0);
|
||||
|
||||
assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0);
|
||||
|
||||
assert_se(sd_dhcp6_client_start(client) >= 0);
|
||||
}
|
||||
|
||||
|
@ -701,6 +704,7 @@ int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
|
|||
static int test_client_solicit(sd_event *e) {
|
||||
sd_dhcp6_client *client;
|
||||
usec_t time_now = now(clock_boottime_or_monotonic());
|
||||
struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
|
||||
int val = true;
|
||||
|
||||
if (verbose)
|
||||
|
@ -729,6 +733,8 @@ static int test_client_solicit(sd_event *e) {
|
|||
time_now + 2 * USEC_PER_SEC, 0,
|
||||
test_hangcheck, NULL) >= 0);
|
||||
|
||||
assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0);
|
||||
|
||||
assert_se(sd_dhcp6_client_start(client) >= 0);
|
||||
|
||||
sd_event_loop(e);
|
||||
|
|
|
@ -347,9 +347,9 @@ int address_update(Address *address, unsigned char flags, unsigned char scope, s
|
|||
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);
|
||||
in_addr_is_link_local(AF_INET6, &address->in_addr) > 0 &&
|
||||
in_addr_is_null(AF_INET6, (const union in_addr_union*) &address->link->ipv6ll_address) > 0) {
|
||||
r = link_ipv6ll_gained(address->link, &address->in_addr.in6);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -211,6 +211,9 @@ int dhcp6_configure(Link *link) {
|
|||
|
||||
assert(link);
|
||||
|
||||
if (link->dhcp6_client)
|
||||
return 0;
|
||||
|
||||
r = sd_dhcp6_client_new(&client);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
|
|
@ -615,7 +615,7 @@ void link_check_ready(Link *link) {
|
|||
return;
|
||||
|
||||
if (link_ipv6ll_enabled(link))
|
||||
if (!link->ipv6ll_address)
|
||||
if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) > 0)
|
||||
return;
|
||||
|
||||
if ((link_dhcp4_enabled(link) && !link_dhcp6_enabled(link) &&
|
||||
|
@ -1260,11 +1260,16 @@ static int link_acquire_ipv6_conf(Link *link) {
|
|||
|
||||
if (link_dhcp6_enabled(link)) {
|
||||
assert(link->dhcp6_client);
|
||||
assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0);
|
||||
|
||||
log_link_debug(link, "Acquiring DHCPv6 lease");
|
||||
|
||||
r = sd_dhcp6_client_set_local_address(link->dhcp6_client, &link->ipv6ll_address);
|
||||
if (r < 0 && r != -EBUSY)
|
||||
return log_link_warning_errno(link, r, "Could not set IPv6LL address in DHCP client: %m");
|
||||
|
||||
r = sd_dhcp6_client_start(link->dhcp6_client);
|
||||
if (r < 0)
|
||||
if (r < 0 && r != -EBUSY)
|
||||
return log_link_warning_errno(link, r, "Could not acquire DHCPv6 lease: %m");
|
||||
}
|
||||
|
||||
|
@ -1274,7 +1279,7 @@ static int link_acquire_ipv6_conf(Link *link) {
|
|||
log_link_debug(link, "Discovering IPv6 routers");
|
||||
|
||||
r = sd_ndisc_router_discovery_start(link->ndisc_router_discovery);
|
||||
if (r < 0)
|
||||
if (r < 0 && r != -EBUSY)
|
||||
return log_link_warning_errno(link, r, "Could not start IPv6 Router Discovery: %m");
|
||||
}
|
||||
|
||||
|
@ -2089,7 +2094,8 @@ static int link_configure(Link *link) {
|
|||
return r;
|
||||
}
|
||||
|
||||
if (link_dhcp6_enabled(link)) {
|
||||
if (link_dhcp6_enabled(link) ||
|
||||
link_ipv6_accept_ra_enabled(link)) {
|
||||
r = dhcp6_configure(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -2121,7 +2127,7 @@ static int link_configure(Link *link) {
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (link->ipv6ll_address) {
|
||||
if (in_addr_is_null(AF_INET6, (const union in_addr_union*) &link->ipv6ll_address) == 0) {
|
||||
r = link_acquire_ipv6_conf(link);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -2472,14 +2478,14 @@ failed:
|
|||
return r;
|
||||
}
|
||||
|
||||
int link_ipv6ll_gained(Link *link) {
|
||||
int link_ipv6ll_gained(Link *link, const struct in6_addr *address) {
|
||||
int r;
|
||||
|
||||
assert(link);
|
||||
|
||||
log_link_info(link, "Gained IPv6LL");
|
||||
|
||||
link->ipv6ll_address = true;
|
||||
link->ipv6ll_address = *address;
|
||||
link_check_ready(link);
|
||||
|
||||
if (!IN_SET(link->state, LINK_STATE_PENDING, LINK_STATE_PENDING, LINK_STATE_UNMANAGED, LINK_STATE_FAILED)) {
|
||||
|
|
|
@ -69,6 +69,7 @@ struct Link {
|
|||
char *ifname;
|
||||
char *state_file;
|
||||
struct ether_addr mac;
|
||||
struct in6_addr ipv6ll_address;
|
||||
uint32_t mtu;
|
||||
struct udev_device *udev_device;
|
||||
|
||||
|
@ -101,7 +102,6 @@ struct Link {
|
|||
sd_ipv4ll *ipv4ll;
|
||||
bool ipv4ll_address:1;
|
||||
bool ipv4ll_route:1;
|
||||
bool ipv6ll_address:1;
|
||||
|
||||
bool static_configured;
|
||||
|
||||
|
@ -144,7 +144,7 @@ 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_ipv6ll_gained(Link *link, const struct in6_addr *address);
|
||||
|
||||
int link_set_mtu(Link *link, uint32_t mtu);
|
||||
int link_set_hostname(Link *link, const char *hostname);
|
||||
|
|
|
@ -75,7 +75,7 @@ static void ndisc_prefix_autonomous_handler(sd_ndisc *nd, const struct in6_addr
|
|||
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);
|
||||
memcpy(((char *)&address->in_addr.in6) + 8, ((char *)&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];
|
||||
|
@ -159,7 +159,7 @@ static void ndisc_router_handler(sd_ndisc *nd, uint8_t flags, const struct in6_a
|
|||
dhcp6_request_address(link);
|
||||
|
||||
r = sd_dhcp6_client_start(link->dhcp6_client);
|
||||
if (r < 0 && r != -EALREADY)
|
||||
if (r < 0 && r != -EBUSY)
|
||||
log_link_warning_errno(link, r, "Starting DHCPv6 client on NDisc request failed: %m");
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,7 @@ static void ndisc_handler(sd_ndisc *nd, int event, void *userdata) {
|
|||
dhcp6_request_address(link);
|
||||
|
||||
r = sd_dhcp6_client_start(link->dhcp6_client);
|
||||
if (r < 0 && r != -EALREADY)
|
||||
if (r < 0 && r != -EBUSY)
|
||||
log_link_warning_errno(link, r, "Starting DHCPv6 client after NDisc timeout failed: %m");
|
||||
|
||||
link->ndisc_configured = true;
|
||||
|
|
|
@ -49,6 +49,7 @@ int sd_dhcp6_client_set_callback(sd_dhcp6_client *client,
|
|||
sd_dhcp6_client_cb_t cb, void *userdata);
|
||||
|
||||
int sd_dhcp6_client_set_index(sd_dhcp6_client *client, int interface_index);
|
||||
int sd_dhcp6_client_set_local_address(sd_dhcp6_client *client, const struct in6_addr *local_address);
|
||||
int sd_dhcp6_client_set_mac(sd_dhcp6_client *client, const uint8_t *addr,
|
||||
size_t addr_len, uint16_t arp_type);
|
||||
int sd_dhcp6_client_set_duid(sd_dhcp6_client *client, uint16_t type, uint8_t *duid,
|
||||
|
|
Loading…
Reference in a new issue