15 #include <netinet/in.h>
22 PktFilterInet6::PktFilterInet6()
23 : recv_control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
24 send_control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
25 recv_control_buf_(new char[recv_control_buf_len_]),
26 send_control_buf_(new char[send_control_buf_len_]) {
33 const bool join_multicast) {
34 struct sockaddr_in6 addr6;
35 memset(&addr6, 0,
sizeof(addr6));
36 addr6.sin6_family = AF_INET6;
37 addr6.sin6_port = htons(port);
45 addr6.sin6_scope_id = if_nametoindex(iface.
getName().c_str());
50 memcpy(&addr6.sin6_addr, &addr.
toBytes()[0],
sizeof(addr6.sin6_addr));
53 addr6.sin6_len =
sizeof(addr6);
59 int sock = socket(AF_INET6, SOCK_DGRAM, 0);
65 if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) {
68 <<
" on IPv6 socket.");
73 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
74 (
char *)&flag,
sizeof(flag)) < 0) {
88 if ((setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
89 (
char *)&flag,
sizeof(flag)) < 0) &&
90 (errno != ENOPROTOOPT)) {
97 if (bind(sock, (
struct sockaddr *)&addr6,
sizeof(addr6)) < 0) {
100 char* errmsg = strerror(errno);
103 << addr.
toText() <<
"/port=" << port
106 #ifdef IPV6_RECVPKTINFO
108 if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
109 &flag,
sizeof(flag)) != 0) {
115 if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO,
116 &flag,
sizeof(flag)) != 0) {
124 if (join_multicast &&
130 <<
" multicast group.");
140 memset(&recv_control_buf_[0], 0, recv_control_buf_len_);
141 struct sockaddr_in6 from;
142 memset(&from, 0,
sizeof(from));
146 memset(&m, 0,
sizeof(m));
150 m.msg_namelen =
sizeof(from);
156 memset(&v, 0,
sizeof(v));
157 v.iov_base =
static_cast<void*
>(buf);
168 m.msg_control = &recv_control_buf_[0];
169 m.msg_controllen = recv_control_buf_len_;
171 int result = recvmsg(socket_info.
sockfd_, &m, 0);
173 struct in6_addr to_addr;
174 memset(&to_addr, 0,
sizeof(to_addr));
178 struct in6_pktinfo* pktinfo = NULL;
187 bool found_pktinfo =
false;
188 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
189 while (cmsg != NULL) {
190 if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
191 (cmsg->cmsg_type == IPV6_PKTINFO)) {
193 to_addr = pktinfo->ipi6_addr;
194 ifindex = pktinfo->ipi6_ifindex;
195 found_pktinfo =
true;
198 cmsg = CMSG_NXTHDR(&m, cmsg);
200 if (!found_pktinfo) {
212 reinterpret_cast<const uint8_t*
>(&to_addr));
222 }
catch (
const std::exception& ex) {
226 pkt->updateTimestamp();
229 reinterpret_cast<const uint8_t*
>(&to_addr)));
231 reinterpret_cast<const uint8_t*
>(&from.sin6_addr)));
232 pkt->setRemotePort(ntohs(from.sin6_port));
233 pkt->setIndex(ifindex);
237 pkt->setIface(received->getName());
240 <<
"(ifindex=" << pkt->getIndex() <<
")");
250 memset(&send_control_buf_[0], 0, send_control_buf_len_);
254 memset(&to, 0,
sizeof(to));
255 to.sin6_family = AF_INET6;
256 to.sin6_port = htons(pkt->getRemotePort());
257 memcpy(&to.sin6_addr,
258 &pkt->getRemoteAddr().toBytes()[0],
260 to.sin6_scope_id = pkt->getIndex();
264 memset(&m, 0,
sizeof(m));
266 m.msg_namelen =
sizeof(to);
280 memset(&v, 0,
sizeof(v));
281 v.iov_base =
const_cast<void *
>(pkt->getBuffer().getData());
282 v.iov_len = pkt->getBuffer().getLength();
292 m.msg_control = &send_control_buf_[0];
293 m.msg_controllen = send_control_buf_len_;
294 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&m);
300 assert(cmsg != NULL);
302 cmsg->cmsg_level = IPPROTO_IPV6;
303 cmsg->cmsg_type = IPV6_PKTINFO;
304 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in6_pktinfo));
305 struct in6_pktinfo *pktinfo =
307 memset(pktinfo, 0,
sizeof(
struct in6_pktinfo));
308 pktinfo->ipi6_ifindex = pkt->getIndex();
317 m.msg_controllen = CMSG_SPACE(
sizeof(
struct in6_pktinfo));
319 pkt->updateTimestamp();
321 int result = sendmsg(sockfd, &m, 0);
324 " with an error: " << strerror(errno));