-/* SPDX-License-Identifier: LGPL-2.1+ */
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
/***
Copyright © 2014 Intel Corporation. All rights reserved.
***/
#include <netinet/ip6.h>
#include <stdio.h>
#include <string.h>
-#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <net/if.h>
static int icmp6_bind_router_message(const struct icmp6_filter *filter,
const struct ipv6_mreq *mreq) {
- int index = mreq->ipv6mr_interface;
+ int ifindex = mreq->ipv6mr_interface;
_cleanup_close_ int s = -1;
- char ifname[IF_NAMESIZE] = "";
int r;
s = socket(AF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_ICMPV6);
IPV6_PKTINFO socket option also applies for ICMPv6 multicast.
Empirical experiments indicates otherwise and therefore an
IPV6_MULTICAST_IF socket option is used here instead */
- r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, index);
+ r = setsockopt_int(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, ifindex);
if (r < 0)
return r;
if (r < 0)
return r;
- if (if_indextoname(index, ifname) == 0)
- return -errno;
-
- r = setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname));
+ r = socket_bind_to_ifindex(s, ifindex);
if (r < 0)
- return -errno;
+ return r;
return TAKE_FD(s);
}
-int icmp6_bind_router_solicitation(int index) {
+int icmp6_bind_router_solicitation(int ifindex) {
struct icmp6_filter filter = {};
struct ipv6_mreq mreq = {
.ipv6mr_multiaddr = IN6ADDR_ALL_NODES_MULTICAST_INIT,
- .ipv6mr_interface = index,
+ .ipv6mr_interface = ifindex,
};
ICMP6_FILTER_SETBLOCKALL(&filter);
return icmp6_bind_router_message(&filter, &mreq);
}
-int icmp6_bind_router_advertisement(int index) {
+int icmp6_bind_router_advertisement(int ifindex) {
struct icmp6_filter filter = {};
struct ipv6_mreq mreq = {
.ipv6mr_multiaddr = IN6ADDR_ALL_ROUTERS_MULTICAST_INIT,
- .ipv6mr_interface = index,
+ .ipv6mr_interface = ifindex,
};
ICMP6_FILTER_SETBLOCKALL(&filter);
return 0;
}
-int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *dst,
- triple_timestamp *timestamp) {
- union {
- struct cmsghdr cmsghdr;
- uint8_t buf[CMSG_SPACE(sizeof(int)) + /* ttl */
- CMSG_SPACE(sizeof(struct timeval))];
- } control = {};
+int icmp6_receive(int fd, void *buffer, size_t size, struct in6_addr *ret_dst,
+ triple_timestamp *ret_timestamp) {
+
+ CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(int)) + /* ttl */
+ CMSG_SPACE(sizeof(struct timeval))) control;
struct iovec iov = {};
union sockaddr_union sa = {};
struct msghdr msg = {
.msg_controllen = sizeof(control),
};
struct cmsghdr *cmsg;
+ struct in6_addr addr = {};
+ triple_timestamp t;
ssize_t len;
iov = IOVEC_MAKE(buffer, size);
- len = recvmsg(fd, &msg, MSG_DONTWAIT);
+ len = recvmsg_safe(fd, &msg, MSG_DONTWAIT);
if (len < 0)
- return -errno;
+ return (int) len;
if ((size_t) len != size)
return -EINVAL;
if (msg.msg_namelen == sizeof(struct sockaddr_in6) &&
sa.in6.sin6_family == AF_INET6) {
- *dst = sa.in6.sin6_addr;
- if (in_addr_is_link_local(AF_INET6, (union in_addr_union*) dst) <= 0)
+ addr = sa.in6.sin6_addr;
+ if (!in6_addr_is_link_local(&addr))
return -EADDRNOTAVAIL;
} else if (msg.msg_namelen > 0)
if (cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SO_TIMESTAMP &&
cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
- triple_timestamp_from_realtime(timestamp, timeval_load((struct timeval*) CMSG_DATA(cmsg)));
+ triple_timestamp_from_realtime(&t, timeval_load((struct timeval*) CMSG_DATA(cmsg)));
}
- if (!triple_timestamp_is_set(timestamp))
- triple_timestamp_get(timestamp);
+ if (!triple_timestamp_is_set(&t))
+ triple_timestamp_get(&t);
+ *ret_dst = addr;
+ *ret_timestamp = t;
return 0;
}