sd-radv: Send Router Advertisments
Create and remove the ICMPv6 Router Advertisement socket file descriptor and implement Router Advertisment sending. As not all options are mandatory, use IO vectors to point to the included options and the prefix information.
This commit is contained in:
parent
e2e8122838
commit
77baf5aee6
|
@ -56,6 +56,7 @@ struct sd_radv {
|
|||
uint32_t mtu;
|
||||
uint16_t lifetime;
|
||||
|
||||
int fd;
|
||||
unsigned ra_sent;
|
||||
sd_event_source *timeout_event_source;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <netinet/icmp6.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/in6.h>
|
||||
|
||||
#include "sd-radv.h"
|
||||
|
||||
|
@ -44,6 +45,7 @@ _public_ int sd_radv_new(sd_radv **ret) {
|
|||
return -ENOMEM;
|
||||
|
||||
ra->n_ref = 1;
|
||||
ra->fd = -1;
|
||||
|
||||
LIST_HEAD_INIT(ra->prefixes);
|
||||
|
||||
|
@ -129,8 +131,71 @@ _public_ sd_radv *sd_radv_unref(sd_radv *ra) {
|
|||
|
||||
static int radv_send(sd_radv *ra, const struct in6_addr *dst,
|
||||
const uint32_t router_lifetime) {
|
||||
static const struct ether_addr mac_zero = {};
|
||||
sd_radv_prefix *p;
|
||||
struct sockaddr_in6 dst_addr = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_addr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
|
||||
};
|
||||
struct nd_router_advert adv = {};
|
||||
struct {
|
||||
struct nd_opt_hdr opthdr;
|
||||
struct ether_addr slladdr;
|
||||
} _packed_ opt_mac = {
|
||||
.opthdr = {
|
||||
.nd_opt_type = ND_OPT_SOURCE_LINKADDR,
|
||||
.nd_opt_len = (sizeof(struct nd_opt_hdr) +
|
||||
sizeof(struct ether_addr) - 1) /8 + 1,
|
||||
},
|
||||
};
|
||||
struct nd_opt_mtu opt_mtu = {
|
||||
.nd_opt_mtu_type = ND_OPT_MTU,
|
||||
.nd_opt_mtu_len = 1,
|
||||
};
|
||||
/* Reserve iov space for RA header, linkaddr, MTU + N prefixes */
|
||||
struct iovec iov[3 + ra->n_prefixes];
|
||||
struct msghdr msg = {
|
||||
.msg_name = &dst_addr,
|
||||
.msg_namelen = sizeof(dst_addr),
|
||||
.msg_iov = iov,
|
||||
};
|
||||
|
||||
return -ENOSYS;
|
||||
if (dst)
|
||||
dst_addr.sin6_addr = *dst;
|
||||
adv.nd_ra_type = ND_ROUTER_ADVERT;
|
||||
adv.nd_ra_curhoplimit = ra->hop_limit;
|
||||
adv.nd_ra_flags_reserved = ra->flags;
|
||||
adv.nd_ra_router_lifetime = htobe16(router_lifetime);
|
||||
iov[msg.msg_iovlen].iov_base = &adv;
|
||||
iov[msg.msg_iovlen].iov_len = sizeof(adv);
|
||||
msg.msg_iovlen++;
|
||||
|
||||
/* MAC address is optional, either because the link does not use L2
|
||||
addresses or load sharing is desired. See RFC 4861, Section 4.2 */
|
||||
if (memcmp(&mac_zero, &ra->mac_addr, sizeof(mac_zero))) {
|
||||
opt_mac.slladdr = ra->mac_addr;
|
||||
iov[msg.msg_iovlen].iov_base = &opt_mac;
|
||||
iov[msg.msg_iovlen].iov_len = sizeof(opt_mac);
|
||||
msg.msg_iovlen++;
|
||||
}
|
||||
|
||||
if (ra->mtu) {
|
||||
opt_mtu.nd_opt_mtu_mtu = htobe32(ra->mtu);
|
||||
iov[msg.msg_iovlen].iov_base = &opt_mtu;
|
||||
iov[msg.msg_iovlen].iov_len = sizeof(opt_mtu);
|
||||
msg.msg_iovlen++;
|
||||
}
|
||||
|
||||
LIST_FOREACH(prefix, p, ra->prefixes) {
|
||||
iov[msg.msg_iovlen].iov_base = &p->opt;
|
||||
iov[msg.msg_iovlen].iov_len = sizeof(p->opt);
|
||||
msg.msg_iovlen++;
|
||||
}
|
||||
|
||||
if (sendmsg(ra->fd, &msg, 0) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static usec_t radv_compute_timeout(usec_t min, usec_t max) {
|
||||
|
@ -213,6 +278,7 @@ _public_ int sd_radv_stop(sd_radv *ra) {
|
|||
log_radv_warning_errno(r, "Unable to send last Router Advertisement with router lifetime set to zero: %m");
|
||||
|
||||
radv_reset(ra);
|
||||
ra->fd = safe_close(ra->fd);
|
||||
ra->state = SD_RADV_STATE_IDLE;
|
||||
|
||||
return 0;
|
||||
|
@ -242,6 +308,13 @@ _public_ int sd_radv_start(sd_radv *ra) {
|
|||
(void) sd_event_source_set_description(ra->timeout_event_source,
|
||||
"radv-timeout");
|
||||
|
||||
r = icmp6_bind_router_advertisement(ra->ifindex);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
ra->fd = r;
|
||||
r = 0;
|
||||
|
||||
ra->state = SD_RADV_STATE_ADVERTISING;
|
||||
|
||||
log_radv("Started IPv6 Router Advertisement daemon");
|
||||
|
|
Loading…
Reference in New Issue