20const size_t PktFilterInet::CONTROL_BUF_LEN = 512;
35 const bool receive_bcast,
36 const bool send_bcast) {
37 struct sockaddr_in addr4;
38 memset(&addr4, 0,
sizeof(sockaddr));
39 addr4.sin_family = AF_INET;
40 addr4.sin_port = htons(port);
45 addr4.sin_addr.s_addr = INADDR_ANY;
47 addr4.sin_addr.s_addr = htonl(addr.
toUint32());
50 int sock = socket(AF_INET, SOCK_DGRAM, 0);
56 if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) {
59 <<
" on socket " << sock);
64 if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &enable,
sizeof(enable))) {
65 const char* errmsg = strerror(errno);
67 <<
", error: " << errmsg);
74 if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface.
getName().c_str(),
75 iface.
getName().length() + 1) < 0) {
78 <<
" on socket " << sock);
86 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &flag,
sizeof(flag)) < 0) {
89 <<
" on socket " << sock);
93 if (bind(sock, (
struct sockaddr *)&addr4,
sizeof(addr4)) < 0) {
102#if defined (IP_PKTINFO) && defined (OS_LINUX)
104 if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag,
sizeof(flag)) != 0) {
110#elif defined (IP_RECVDSTADDR) && defined (OS_BSD)
112 if (setsockopt(sock, IPPROTO_IP, IP_RECVDSTADDR, &flag,
sizeof(flag)) != 0) {
123 struct sockaddr_in from_addr;
125 uint8_t control_buf[CONTROL_BUF_LEN];
127 memset(&control_buf[0], 0, CONTROL_BUF_LEN);
128 memset(&from_addr, 0,
sizeof(from_addr));
132 memset(&m, 0,
sizeof(m));
135 m.msg_name = &from_addr;
136 m.msg_namelen =
sizeof(from_addr);
139 v.iov_base =
static_cast<void*
>(buf);
150 m.msg_control = &control_buf[0];
151 m.msg_controllen = CONTROL_BUF_LEN;
153 int result = recvmsg(socket_info.
sockfd_, &m, 0);
161 pkt->updateTimestamp();
163 unsigned int ifindex = iface.
getIndex();
165 IOAddress from(htonl(from_addr.sin_addr.s_addr));
166 uint16_t from_port = htons(from_addr.sin_port);
171 pkt->setIndex(ifindex);
172 pkt->setIface(iface.
getName());
173 pkt->setRemoteAddr(from);
174 pkt->setRemotePort(from_port);
175 pkt->setLocalPort(socket_info.
port_);
180#if defined (IP_PKTINFO) && defined (OS_LINUX)
181 struct in_pktinfo* pktinfo;
182 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
184 while (cmsg != NULL) {
185 if ((cmsg->cmsg_level == IPPROTO_IP) &&
186 (cmsg->cmsg_type == IP_PKTINFO)) {
187 pktinfo =
reinterpret_cast<struct in_pktinfo*
>(CMSG_DATA(cmsg));
189 pkt->setIndex(pktinfo->ipi_ifindex);
190 pkt->setLocalAddr(
IOAddress(htonl(pktinfo->ipi_addr.s_addr)));
203 }
else if ((cmsg->cmsg_level == SOL_SOCKET) &&
204 (cmsg->cmsg_type == SCM_TIMESTAMP)) {
206 struct timeval cmsg_time;
207 memcpy(&cmsg_time, CMSG_DATA(cmsg),
sizeof(cmsg_time));
212 cmsg = CMSG_NXTHDR(&m, cmsg);
215#elif defined (IP_RECVDSTADDR) && defined (OS_BSD)
216 struct in_addr* to_addr;
217 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
219 while (cmsg != NULL) {
220 if ((cmsg->cmsg_level == IPPROTO_IP) &&
221 (cmsg->cmsg_type == IP_RECVDSTADDR)) {
222 to_addr =
reinterpret_cast<struct in_addr*
>(CMSG_DATA(cmsg));
223 pkt->setLocalAddr(
IOAddress(htonl(to_addr->s_addr)));
228 }
else if ((cmsg->cmsg_level == SOL_SOCKET) &&
229 (cmsg->cmsg_type == SCM_TIMESTAMP)) {
231 struct timeval cmsg_time;
232 memcpy(&cmsg_time, CMSG_DATA(cmsg),
sizeof(cmsg_time));
236 cmsg = CMSG_NXTHDR(&m, cmsg);
240 pkt->addPktEvent(PktEvent::BUFFER_READ);
247 uint8_t control_buf[CONTROL_BUF_LEN];
248 memset(&control_buf[0], 0, CONTROL_BUF_LEN);
252 memset(&to, 0,
sizeof(to));
253 to.sin_family = AF_INET;
254 to.sin_port = htons(pkt->getRemotePort());
255 to.sin_addr.s_addr = htonl(pkt->getRemoteAddr().toUint32());
259 memset(&m, 0,
sizeof(m));
261 m.msg_namelen =
sizeof(to);
267 memset(&v, 0,
sizeof(v));
270 v.iov_base =
const_cast<void *
>(pkt->getBuffer().getDataAsVoidPtr());
271 v.iov_len = pkt->getBuffer().getLength();
278#if defined (IP_PKTINFO) && defined (OS_LINUX)
284 m.msg_control = &control_buf[0];
285 m.msg_controllen = CONTROL_BUF_LEN;
286 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
287 cmsg->cmsg_level = IPPROTO_IP;
288 cmsg->cmsg_type = IP_PKTINFO;
289 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_pktinfo));
290 struct in_pktinfo* pktinfo =(
struct in_pktinfo *)CMSG_DATA(cmsg);
291 memset(pktinfo, 0,
sizeof(
struct in_pktinfo));
297 if (pkt->indexSet()) {
298 pktinfo->ipi_ifindex = pkt->getIndex();
303 if (!pkt->getLocalAddr().isV4Zero()) {
304 pktinfo->ipi_spec_dst.s_addr = htonl(pkt->getLocalAddr().toUint32());
307 m.msg_controllen = CMSG_SPACE(
sizeof(
struct in_pktinfo));
310 pkt->updateTimestamp();
314 int result = sendmsg(sockfd, &m, 0);
317 " with an error: " << strerror(errno));
The IOAddress class represents an IP addresses (version agnostic).
std::string toText() const
Convert the address to a string.
uint32_t toUint32() const
Converts IPv4 address to uint32_t.
static const uint32_t RCVBUFSIZE
Packet reception buffer size.
Represents a single network interface.
std::string getName() const
Returns interface name.
unsigned int getIndex() const
Returns interface index.
bool flag_broadcast_
Flag specifies if selected interface is broadcast capable.
Represents DHCPv4 packet.
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.
virtual bool isSocketReceivedTimeSupported() const
Check if the socket received time is supported.
virtual SocketInfo openSocket(Iface &iface, const isc::asiolink::IOAddress &addr, const uint16_t port, const bool receive_bcast, const bool send_bcast)
Open primary and fallback socket.
virtual int send(const Iface &iface, uint16_t sockfd, const Pkt4Ptr &pkt)
Send packet over specified socket.
virtual Pkt4Ptr receive(Iface &iface, const SocketInfo &socket_info)
Receive packet over specified 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 isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< Pkt4 > Pkt4Ptr
A pointer to Pkt4 object.
Defines the logger used by the top-level component of kea-lfc.
Holds information about socket.
int sockfd_
Socket descriptor (a.k.a. primary socket).
uint16_t port_
Socket port.