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));
IfacePtr getIface(int ifindex)
Returns interface specified interface index.
IfaceMgr exception thrown thrown when socket opening or configuration failed.
static bool joinMulticast(int sock, const std::string &ifname, const std::string &mcast)
Joins IPv6 multicast group on a socket.
boost::shared_ptr< Iface > IfacePtr
Represents a DHCPv6 packet.
Represents a single network interface.
bool isV6LinkLocal() const
checks whether and address is IPv6 and is link-local
virtual SocketInfo openSocket(const Iface &iface, const isc::asiolink::IOAddress &addr, const uint16_t port, const bool join_multicast)
Opens a socket.
#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.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
isc::asiolink::IOAddress addr_
std::string getName() const
Returns interface name.
bool isV6Multicast() const
checks whether and address is IPv6 and is multicast
IfaceMgr exception thrown thrown when error occurred during reading data from socket.
struct in6_pktinfo * convertPktInfo6(char *pktinfo)
static const uint32_t RCVBUFSIZE
Packet reception buffer size.
Defines the logger used by the top-level component of kea-dhcp-ddns.
std::string toText() const
Convert the address to a string.
virtual int send(const Iface &iface, uint16_t sockfd, const Pkt6Ptr &pkt)
Sends DHCPv6 message through a specified interface and socket.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
The IOAddress class represents an IP addresses (version agnostic)
virtual Pkt6Ptr receive(const SocketInfo &socket_info)
Receives DHCPv6 message on the interface.
IfaceMgr exception thrown thrown when error occurred during sending data through socket.
Holds information about socket.