21 : recv_control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
22 send_control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
23 recv_control_buf_(new char[recv_control_buf_len_]),
24 send_control_buf_(new char[send_control_buf_len_])
32 const bool receive_bcast,
33 const bool send_bcast) {
35 struct sockaddr_in addr4;
36 memset(&addr4, 0,
sizeof(sockaddr));
37 addr4.sin_family = AF_INET;
38 addr4.sin_port = htons(port);
43 addr4.sin_addr.s_addr = INADDR_ANY;
45 addr4.sin_addr.s_addr = htonl(addr.
toUint32());
48 int sock = socket(AF_INET, SOCK_DGRAM, 0);
54 if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) {
57 <<
" on socket " << sock);
63 if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface.
getName().c_str(),
64 iface.
getName().length() + 1) < 0) {
67 <<
" on socket " << sock);
75 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &flag,
sizeof(flag)) < 0) {
78 <<
" on socket " << sock);
82 if (bind(sock, (
struct sockaddr *)&addr4,
sizeof(addr4)) < 0) {
91#if defined (IP_PKTINFO) && defined (OS_LINUX)
93 if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag,
sizeof(flag)) != 0) {
99#elif defined (IP_RECVDSTADDR) && defined (OS_BSD)
101 if (setsockopt(sock, IPPROTO_IP, IP_RECVDSTADDR, &flag,
sizeof(flag)) != 0) {
114 struct sockaddr_in from_addr;
117 memset(&recv_control_buf_[0], 0, recv_control_buf_len_);
118 memset(&from_addr, 0,
sizeof(from_addr));
122 memset(&m, 0,
sizeof(m));
125 m.msg_name = &from_addr;
126 m.msg_namelen =
sizeof(from_addr);
129 v.iov_base =
static_cast<void*
>(buf);
140 m.msg_control = &recv_control_buf_[0];
141 m.msg_controllen = recv_control_buf_len_;
143 int result = recvmsg(socket_info.
sockfd_, &m, 0);
151 pkt->updateTimestamp();
153 unsigned int ifindex = iface.
getIndex();
155 IOAddress from(htonl(from_addr.sin_addr.s_addr));
156 uint16_t from_port = htons(from_addr.sin_port);
161 pkt->setIndex(ifindex);
162 pkt->setIface(iface.
getName());
163 pkt->setRemoteAddr(from);
164 pkt->setRemotePort(from_port);
165 pkt->setLocalPort(socket_info.
port_);
170#if defined (IP_PKTINFO) && defined (OS_LINUX)
171 struct in_pktinfo* pktinfo;
172 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
174 while (cmsg != NULL) {
175 if ((cmsg->cmsg_level == IPPROTO_IP) &&
176 (cmsg->cmsg_type == IP_PKTINFO)) {
177 pktinfo =
reinterpret_cast<struct in_pktinfo*
>(CMSG_DATA(cmsg));
179 pkt->setIndex(pktinfo->ipi_ifindex);
180 pkt->setLocalAddr(
IOAddress(htonl(pktinfo->ipi_addr.s_addr)));
191 cmsg = CMSG_NXTHDR(&m, cmsg);
194#elif defined (IP_RECVDSTADDR) && defined (OS_BSD)
195 struct in_addr* to_addr;
196 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
198 while (cmsg != NULL) {
199 if ((cmsg->cmsg_level == IPPROTO_IP) &&
200 (cmsg->cmsg_type == IP_RECVDSTADDR)) {
201 to_addr =
reinterpret_cast<struct in_addr*
>(CMSG_DATA(cmsg));
202 pkt->setLocalAddr(
IOAddress(htonl(to_addr->s_addr)));
205 cmsg = CMSG_NXTHDR(&m, cmsg);
216 memset(&send_control_buf_[0], 0, send_control_buf_len_);
220 memset(&to, 0,
sizeof(to));
221 to.sin_family = AF_INET;
222 to.sin_port = htons(pkt->getRemotePort());
223 to.sin_addr.s_addr = htonl(pkt->getRemoteAddr().toUint32());
227 memset(&m, 0,
sizeof(m));
229 m.msg_namelen =
sizeof(to);
235 memset(&v, 0,
sizeof(v));
238 v.iov_base =
const_cast<void *
>(pkt->getBuffer().getData());
239 v.iov_len = pkt->getBuffer().getLength();
246#if defined (IP_PKTINFO) && defined (OS_LINUX)
252 m.msg_control = &send_control_buf_[0];
253 m.msg_controllen = send_control_buf_len_;
254 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
255 cmsg->cmsg_level = IPPROTO_IP;
256 cmsg->cmsg_type = IP_PKTINFO;
257 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_pktinfo));
258 struct in_pktinfo* pktinfo =(
struct in_pktinfo *)CMSG_DATA(cmsg);
259 memset(pktinfo, 0,
sizeof(
struct in_pktinfo));
265 if (pkt->indexSet()) {
266 pktinfo->ipi_ifindex = pkt->getIndex();
271 if (!pkt->getLocalAddr().isV4Zero()) {
272 pktinfo->ipi_spec_dst.s_addr = htonl(pkt->getLocalAddr().toUint32());
275 m.msg_controllen = CMSG_SPACE(
sizeof(
struct in_pktinfo));
278 pkt->updateTimestamp();
280 int result = sendmsg(sockfd, &m, 0);
283 " with an error: " << strerror(errno));
The IOAddress class represents an IP addresses (version agnostic)
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.
bool flag_broadcast_
Flag specifies if selected interface is broadcast capable.
uint16_t getIndex() const
Returns interface index.
Represents DHCPv4 packet.
PktFilterInet()
Constructor.
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-dhcp-ddns.
Holds information about socket.
uint16_t port_
bound address