16 #include <netinet/in.h>
24 PktFilterInet6::CONTROL_BUF_LEN = CMSG_SPACE(
sizeof(
struct in6_pktinfo));
27 PktFilterInet6::openSocket(
const Iface& iface,
30 const bool join_multicast) {
31 struct sockaddr_in6 addr6;
32 memset(&addr6, 0,
sizeof(addr6));
33 addr6.sin6_family = AF_INET6;
34 addr6.sin6_port = htons(port);
42 addr6.sin6_scope_id = if_nametoindex(iface.
getName().c_str());
47 memcpy(&addr6.sin6_addr, &addr.
toBytes()[0],
sizeof(addr6.sin6_addr));
50 addr6.sin6_len =
sizeof(addr6);
56 int sock = socket(AF_INET6, SOCK_DGRAM, 0);
62 if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) {
65 <<
" on IPv6 socket.");
70 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
71 (
char *)&flag,
sizeof(flag)) < 0) {
85 if ((setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
86 (
char *)&flag,
sizeof(flag)) < 0) &&
87 (errno != ENOPROTOOPT)) {
96 if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
97 (
char *)&flag,
sizeof(flag)) < 0) {
104 if (bind(sock, (
struct sockaddr *)&addr6,
sizeof(addr6)) < 0) {
107 char* errmsg = strerror(errno);
110 << addr.
toText() <<
"/port=" << port
114 #ifdef IPV6_RECVPKTINFO
116 if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
117 &flag,
sizeof(flag)) != 0) {
123 if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO,
124 &flag,
sizeof(flag)) != 0) {
132 if (join_multicast &&
133 !joinMulticast(sock, iface.
getName(),
138 <<
" multicast group.");
147 uint8_t buf[IfaceMgr::RCVBUFSIZE];
148 uint8_t control_buf[CONTROL_BUF_LEN];
149 memset(&control_buf[0], 0, CONTROL_BUF_LEN);
150 struct sockaddr_in6 from;
151 memset(&from, 0,
sizeof(from));
155 memset(&m, 0,
sizeof(m));
159 m.msg_namelen =
sizeof(from);
165 memset(&v, 0,
sizeof(v));
166 v.iov_base =
static_cast<void*
>(buf);
167 v.iov_len = IfaceMgr::RCVBUFSIZE;
177 m.msg_control = &control_buf[0];
178 m.msg_controllen = CONTROL_BUF_LEN;
180 int result = recvmsg(socket_info.
sockfd_, &m, 0);
182 struct in6_addr to_addr;
183 memset(&to_addr, 0,
sizeof(to_addr));
187 struct in6_pktinfo* pktinfo = NULL;
196 bool found_pktinfo =
false;
197 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
198 while (cmsg != NULL) {
199 if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
200 (cmsg->cmsg_type == IPV6_PKTINFO)) {
202 to_addr = pktinfo->ipi6_addr;
203 ifindex = pktinfo->ipi6_ifindex;
204 found_pktinfo =
true;
207 cmsg = CMSG_NXTHDR(&m, cmsg);
209 if (!found_pktinfo) {
221 reinterpret_cast<const uint8_t*>(&to_addr));
231 }
catch (
const std::exception& ex) {
235 pkt->updateTimestamp();
238 reinterpret_cast<const uint8_t*>(&to_addr)));
240 reinterpret_cast<const uint8_t*>(&from.sin6_addr)));
241 pkt->setRemotePort(ntohs(from.sin6_port));
242 pkt->setIndex(ifindex);
244 IfacePtr received = IfaceMgr::instance().getIface(pkt->getIndex());
246 pkt->setIface(received->getName());
249 <<
"(ifindex=" << pkt->getIndex() <<
")");
257 PktFilterInet6::send(
const Iface&, uint16_t sockfd,
const Pkt6Ptr& pkt) {
258 uint8_t control_buf[CONTROL_BUF_LEN];
259 memset(&control_buf[0], 0, CONTROL_BUF_LEN);
263 memset(&to, 0,
sizeof(to));
264 to.sin6_family = AF_INET6;
265 to.sin6_port = htons(pkt->getRemotePort());
266 memcpy(&to.sin6_addr,
267 &pkt->getRemoteAddr().toBytes()[0],
269 to.sin6_scope_id = pkt->getIndex();
273 memset(&m, 0,
sizeof(m));
275 m.msg_namelen =
sizeof(to);
289 memset(&v, 0,
sizeof(v));
290 v.iov_base =
const_cast<void *
>(pkt->getBuffer().getData());
291 v.iov_len = pkt->getBuffer().getLength();
301 m.msg_control = &control_buf[0];
302 m.msg_controllen = CONTROL_BUF_LEN;
303 struct cmsghdr *cmsg = CMSG_FIRSTHDR(&m);
311 cmsg->cmsg_level = IPPROTO_IPV6;
312 cmsg->cmsg_type = IPV6_PKTINFO;
313 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in6_pktinfo));
314 struct in6_pktinfo *pktinfo =
316 memset(pktinfo, 0,
sizeof(
struct in6_pktinfo));
317 pktinfo->ipi6_ifindex = pkt->getIndex();
326 m.msg_controllen = CMSG_SPACE(
sizeof(
struct in6_pktinfo));
328 pkt->updateTimestamp();
330 int result = sendmsg(sockfd, &m, 0);
333 " with an error: " << strerror(errno));
#define isc_throw_assert(expr)
Replacement for assert() that throws if the expression is false.
IfaceMgr exception thrown thrown when socket opening or configuration failed.
boost::shared_ptr< Iface > IfacePtr
Type definition for the pointer to an Iface object.
Represents a DHCPv6 packet.
Represents a single network interface.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
#define ALL_DHCP_RELAY_AGENTS_AND_SERVERS
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
static IOAddress fromBytes(short family, const uint8_t *data)
Creates an address from over wire data.
isc::asiolink::IOAddress addr_
IfaceMgr exception thrown thrown when error occurred during reading data from socket.
struct in6_pktinfo * convertPktInfo6(char *pktinfo)
std::string getName() const
Returns interface name.
Defines the logger used by the top-level component of kea-dhcp-ddns.
std::string toText() const
Convert the address to a string.
bool isV6LinkLocal() const
checks whether and address is IPv6 and is link-local
bool isV6Multicast() const
checks whether and address is IPv6 and is multicast
The IOAddress class represents an IP addresses (version agnostic)
IfaceMgr exception thrown thrown when error occurred during sending data through socket.
Holds information about socket.