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));
The IOAddress class represents an IP addresses (version agnostic)
std::string toText() const
Convert the address to a string.
std::vector< uint8_t > toBytes() const
Return address as set of bytes.
bool isV6Multicast() const
checks whether and address is IPv6 and is multicast
bool isV6LinkLocal() const
checks whether and address is IPv6 and is link-local
static IOAddress fromBytes(short family, const uint8_t *data)
Creates an address from over wire data.
Represents a single network interface.
std::string getName() const
Returns interface name.
Represents a DHCPv6 packet.
IfaceMgr exception thrown thrown when socket opening or configuration failed.
IfaceMgr exception thrown thrown when error occurred during reading data from socket.
IfaceMgr exception thrown thrown when error occurred during sending data through socket.
#define ALL_DHCP_RELAY_AGENTS_AND_SERVERS
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define isc_throw_assert(expr)
Replacement for assert() that throws if the expression is false.
boost::shared_ptr< Iface > IfacePtr
Type definition for the pointer to an Iface object.
boost::shared_ptr< Pkt6 > Pkt6Ptr
A pointer to Pkt6 packet.
struct in6_pktinfo * convertPktInfo6(char *pktinfo)
Defines the logger used by the top-level component of kea-lfc.
Holds information about socket.
isc::asiolink::IOAddress addr_