16#include <netinet/in.h> 
   23const size_t PktFilterInet6::CONTROL_BUF_LEN = 512;
 
   38                           const bool join_multicast) {
 
   39    struct sockaddr_in6 addr6;
 
   40    memset(&addr6, 0, 
sizeof(addr6));
 
   41    addr6.sin6_family = AF_INET6;
 
   42    addr6.sin6_port = htons(port);
 
   50        addr6.sin6_scope_id = if_nametoindex(iface.
getName().c_str());
 
   55        memcpy(&addr6.sin6_addr, &addr.
toBytes()[0], 
sizeof(addr6.sin6_addr));
 
   58    addr6.sin6_len = 
sizeof(addr6);
 
   64    int sock = socket(AF_INET6, SOCK_DGRAM, 0);
 
   70    if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) {
 
   73                  << 
" on IPv6 socket.");
 
   78    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
 
   79                   (
char *)&flag, 
sizeof(flag)) < 0) {
 
   93    if ((setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
 
   94                    (
char *)&flag, 
sizeof(flag)) < 0) &&
 
   95        (errno != ENOPROTOOPT)) {
 
  104    if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &enable, 
sizeof(enable))) {
 
  105        const char* errmsg = strerror(errno);
 
  107                  << 
", error: " << errmsg);
 
  113    if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
 
  114                   (
char *)&flag, 
sizeof(flag)) < 0) {
 
  121    if (bind(sock, (
struct sockaddr *)&addr6, 
sizeof(addr6)) < 0) {
 
  124        char* errmsg = strerror(errno);
 
  127                  << addr.
toText() << 
"/port=" << port
 
  131#ifdef IPV6_RECVPKTINFO 
  133    if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
 
  134                   &flag, 
sizeof(flag)) != 0) {
 
  140    if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO,
 
  141                   &flag, 
sizeof(flag)) != 0) {
 
  149    if (join_multicast &&
 
  155                  << 
" multicast group.");
 
 
  165    uint8_t control_buf[CONTROL_BUF_LEN];
 
  166    memset(&control_buf[0], 0, CONTROL_BUF_LEN);
 
  167    struct sockaddr_in6 from;
 
  168    memset(&from, 0, 
sizeof(from));
 
  171    struct timeval so_rcv_timestamp;
 
  172    memset(&so_rcv_timestamp, 0, 
sizeof(so_rcv_timestamp));
 
  177    memset(&m, 0, 
sizeof(m));
 
  181    m.msg_namelen = 
sizeof(from);
 
  187    memset(&v, 0, 
sizeof(v));
 
  188    v.iov_base = 
static_cast<void*
>(buf);
 
  199    m.msg_control = &control_buf[0];
 
  200    m.msg_controllen = CONTROL_BUF_LEN;
 
  202    int result = recvmsg(socket_info.
sockfd_, &m, 0);
 
  204    struct in6_addr to_addr;
 
  205    memset(&to_addr, 0, 
sizeof(to_addr));
 
  209        struct in6_pktinfo* pktinfo = NULL;
 
  218        bool found_pktinfo = 
false;
 
  219        struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
 
  220        while (cmsg != NULL) {
 
  221            if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
 
  222                (cmsg->cmsg_type == IPV6_PKTINFO)) {
 
  224                to_addr = pktinfo->ipi6_addr;
 
  225                ifindex = pktinfo->ipi6_ifindex;
 
  226                found_pktinfo = 
true;
 
  231            } 
else if ((cmsg->cmsg_level == SOL_SOCKET) &&
 
  232                       (cmsg->cmsg_type  == SCM_TIMESTAMP)) {
 
  233                memcpy(&so_rcv_timestamp, CMSG_DATA(cmsg), 
sizeof(so_rcv_timestamp));
 
  236            cmsg = CMSG_NXTHDR(&m, cmsg);
 
  238        if (!found_pktinfo) {
 
  250                      reinterpret_cast<const uint8_t*
>(&to_addr));
 
  251    if ((socket_info.addr_ == 
IOAddress(
"::")) &&
 
  259        pkt = 
Pkt6Ptr(
new Pkt6(buf, result));
 
  260    } 
catch (
const std::exception& ex) {
 
  264    pkt->updateTimestamp();
 
  273                      reinterpret_cast<const uint8_t*
>(&to_addr)));
 
  275                       reinterpret_cast<const uint8_t*
>(&from.sin6_addr)));
 
  276    pkt->setRemotePort(ntohs(from.sin6_port));
 
  277    pkt->setIndex(ifindex);
 
  281        pkt->setIface(received->getName());
 
  284                  << 
"(ifindex=" << pkt->getIndex() << 
")");
 
 
  293    uint8_t control_buf[CONTROL_BUF_LEN];
 
  294    memset(&control_buf[0], 0, CONTROL_BUF_LEN);
 
  298    memset(&to, 0, 
sizeof(to));
 
  299    to.sin6_family = AF_INET6;
 
  300    to.sin6_port = htons(pkt->getRemotePort());
 
  301    memcpy(&to.sin6_addr,
 
  302           &pkt->getRemoteAddr().toBytes()[0],
 
  304    to.sin6_scope_id = pkt->getIndex();
 
  308    memset(&m, 0, 
sizeof(m));
 
  310    m.msg_namelen = 
sizeof(to);
 
  324    memset(&v, 0, 
sizeof(v));
 
  325    v.iov_base = 
const_cast<void *
>(pkt->getBuffer().getDataAsVoidPtr());
 
  326    v.iov_len = pkt->getBuffer().getLength();
 
  336    m.msg_control = &control_buf[0];
 
  337    m.msg_controllen = CONTROL_BUF_LEN;
 
  338    struct cmsghdr *cmsg = CMSG_FIRSTHDR(&m);
 
  346    cmsg->cmsg_level = IPPROTO_IPV6;
 
  347    cmsg->cmsg_type = IPV6_PKTINFO;
 
  348    cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in6_pktinfo));
 
  349    struct in6_pktinfo *pktinfo =
 
  351    memset(pktinfo, 0, 
sizeof(
struct in6_pktinfo));
 
  352    pktinfo->ipi6_ifindex = pkt->getIndex();
 
  360    m.msg_controllen = CMSG_SPACE(
sizeof(
struct in6_pktinfo));
 
  362    pkt->updateTimestamp();
 
  366    int result = sendmsg(sockfd, &m, 0);
 
  369                  " 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.
IfacePtr getIface(const unsigned int ifindex)
Returns interface specified interface index.
static IfaceMgr & instance()
IfaceMgr is a singleton class.
static const uint32_t RCVBUFSIZE
Packet reception buffer size.
Represents a single network interface.
std::string getName() const
Returns interface name.
static const std::string BUFFER_READ
Event that marks when a packet is read from the socket buffer by application.
static const std::string SOCKET_RECEIVED
Event that marks when a packet is placed in the socket buffer by the kernel.
static const std::string RESPONSE_SENT
Event that marks when a packet is been written to the socket by application.
static bool joinMulticast(int sock, const std::string &ifname, const std::string &mcast)
Joins IPv6 multicast group on a socket.
virtual int send(const Iface &iface, uint16_t sockfd, const Pkt6Ptr &pkt)
Sends DHCPv6 message through a specified interface and socket.
virtual bool isSocketReceivedTimeSupported() const
Check if the socket received time is supported.
virtual Pkt6Ptr receive(const SocketInfo &socket_info)
Receives DHCPv6 message on the interface.
virtual SocketInfo openSocket(const Iface &iface, const isc::asiolink::IOAddress &addr, const uint16_t port, const bool join_multicast)
Opens a socket.
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.
constexpr unsigned int UNSET_IFINDEX
A value used to signal that the interface index was not set.
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.