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) {
125 struct sockaddr_in from_addr;
127 uint8_t control_buf[CONTROL_BUF_LEN];
129 memset(&control_buf[0], 0, CONTROL_BUF_LEN);
130 memset(&from_addr, 0,
sizeof(from_addr));
134 memset(&m, 0,
sizeof(m));
137 m.msg_name = &from_addr;
138 m.msg_namelen =
sizeof(from_addr);
141 v.iov_base =
static_cast<void*
>(buf);
152 m.msg_control = &control_buf[0];
153 m.msg_controllen = CONTROL_BUF_LEN;
155 int result = recvmsg(socket_info.
sockfd_, &m, 0);
163 pkt->updateTimestamp();
165 unsigned int ifindex = iface.
getIndex();
167 IOAddress from(htonl(from_addr.sin_addr.s_addr));
168 uint16_t from_port = htons(from_addr.sin_port);
173 pkt->setIndex(ifindex);
174 pkt->setIface(iface.
getName());
175 pkt->setRemoteAddr(from);
176 pkt->setRemotePort(from_port);
177 pkt->setLocalPort(socket_info.
port_);
182#if defined (IP_PKTINFO) && defined (OS_LINUX)
183 struct in_pktinfo* pktinfo;
184 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
186 while (cmsg != NULL) {
187 if ((cmsg->cmsg_level == IPPROTO_IP) &&
188 (cmsg->cmsg_type == IP_PKTINFO)) {
189 pktinfo =
reinterpret_cast<struct in_pktinfo*
>(CMSG_DATA(cmsg));
191 pkt->setIndex(pktinfo->ipi_ifindex);
192 pkt->setLocalAddr(
IOAddress(htonl(pktinfo->ipi_addr.s_addr)));
205 }
else if ((cmsg->cmsg_level == SOL_SOCKET) &&
206 (cmsg->cmsg_type == SCM_TIMESTAMP)) {
208 struct timeval cmsg_time;
209 memcpy(&cmsg_time, CMSG_DATA(cmsg),
sizeof(cmsg_time));
214 cmsg = CMSG_NXTHDR(&m, cmsg);
217#elif defined (IP_RECVDSTADDR) && defined (OS_BSD)
218 struct in_addr* to_addr;
219 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
221 while (cmsg != NULL) {
222 if ((cmsg->cmsg_level == IPPROTO_IP) &&
223 (cmsg->cmsg_type == IP_RECVDSTADDR)) {
224 to_addr =
reinterpret_cast<struct in_addr*
>(CMSG_DATA(cmsg));
225 pkt->setLocalAddr(
IOAddress(htonl(to_addr->s_addr)));
230 }
else if ((cmsg->cmsg_level == SOL_SOCKET) &&
231 (cmsg->cmsg_type == SCM_TIMESTAMP)) {
233 struct timeval cmsg_time;
234 memcpy(&cmsg_time, CMSG_DATA(cmsg),
sizeof(cmsg_time));
238 cmsg = CMSG_NXTHDR(&m, cmsg);
242 pkt->addPktEvent(PktEvent::BUFFER_READ);
248PktFilterInet::send(
const Iface&, uint16_t sockfd,
const Pkt4Ptr& pkt) {
249 uint8_t control_buf[CONTROL_BUF_LEN];
250 memset(&control_buf[0], 0, CONTROL_BUF_LEN);
254 memset(&to, 0,
sizeof(to));
255 to.sin_family = AF_INET;
256 to.sin_port = htons(pkt->getRemotePort());
257 to.sin_addr.s_addr = htonl(pkt->getRemoteAddr().toUint32());
261 memset(&m, 0,
sizeof(m));
263 m.msg_namelen =
sizeof(to);
269 memset(&v, 0,
sizeof(v));
272 v.iov_base =
const_cast<void *
>(pkt->getBuffer().getDataAsVoidPtr());
273 v.iov_len = pkt->getBuffer().getLength();
280#if defined (IP_PKTINFO) && defined (OS_LINUX)
286 m.msg_control = &control_buf[0];
287 m.msg_controllen = CONTROL_BUF_LEN;
288 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
289 cmsg->cmsg_level = IPPROTO_IP;
290 cmsg->cmsg_type = IP_PKTINFO;
291 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_pktinfo));
292 struct in_pktinfo* pktinfo =(
struct in_pktinfo *)CMSG_DATA(cmsg);
293 memset(pktinfo, 0,
sizeof(
struct in_pktinfo));
299 if (pkt->indexSet()) {
300 pktinfo->ipi_ifindex = pkt->getIndex();
305 if (!pkt->getLocalAddr().isV4Zero()) {
306 pktinfo->ipi_spec_dst.s_addr = htonl(pkt->getLocalAddr().toUint32());
309 m.msg_controllen = CMSG_SPACE(
sizeof(
struct in_pktinfo));
312 pkt->updateTimestamp();
314 pkt->addPktEvent(PktEvent::RESPONSE_SENT);
316 int result = sendmsg(sockfd, &m, 0);
319 " 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.
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 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.
uint16_t port_
bound address