21 PktFilterInet::CONTROL_BUF_LEN = CMSG_SPACE(
sizeof(
struct in6_pktinfo));
24 PktFilterInet::openSocket(
Iface& iface,
27 const bool receive_bcast,
28 const bool send_bcast) {
29 struct sockaddr_in addr4;
30 memset(&addr4, 0,
sizeof(sockaddr));
31 addr4.sin_family = AF_INET;
32 addr4.sin_port = htons(port);
37 addr4.sin_addr.s_addr = INADDR_ANY;
39 addr4.sin_addr.s_addr = htonl(addr.
toUint32());
42 int sock = socket(AF_INET, SOCK_DGRAM, 0);
48 if (fcntl(sock, F_SETFD, FD_CLOEXEC) < 0) {
51 <<
" on socket " << sock);
54 #ifdef SO_BINDTODEVICE
57 if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface.
getName().c_str(),
58 iface.
getName().length() + 1) < 0) {
61 <<
" on socket " << sock);
69 if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &flag,
sizeof(flag)) < 0) {
72 <<
" on socket " << sock);
76 if (bind(sock, (
struct sockaddr *)&addr4,
sizeof(addr4)) < 0) {
85 #if defined (IP_PKTINFO) && defined (OS_LINUX)
87 if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag,
sizeof(flag)) != 0) {
93 #elif defined (IP_RECVDSTADDR) && defined (OS_BSD)
95 if (setsockopt(sock, IPPROTO_IP, IP_RECVDSTADDR, &flag,
sizeof(flag)) != 0) {
108 struct sockaddr_in from_addr;
109 uint8_t buf[IfaceMgr::RCVBUFSIZE];
110 uint8_t control_buf[CONTROL_BUF_LEN];
112 memset(&control_buf[0], 0, CONTROL_BUF_LEN);
113 memset(&from_addr, 0,
sizeof(from_addr));
117 memset(&m, 0,
sizeof(m));
120 m.msg_name = &from_addr;
121 m.msg_namelen =
sizeof(from_addr);
124 v.iov_base =
static_cast<void*
>(buf);
125 v.iov_len = IfaceMgr::RCVBUFSIZE;
135 m.msg_control = &control_buf[0];
136 m.msg_controllen = CONTROL_BUF_LEN;
138 int result = recvmsg(socket_info.
sockfd_, &m, 0);
146 pkt->updateTimestamp();
148 unsigned int ifindex = iface.
getIndex();
150 IOAddress from(htonl(from_addr.sin_addr.s_addr));
151 uint16_t from_port = htons(from_addr.sin_port);
156 pkt->setIndex(ifindex);
157 pkt->setIface(iface.
getName());
158 pkt->setRemoteAddr(from);
159 pkt->setRemotePort(from_port);
160 pkt->setLocalPort(socket_info.
port_);
165 #if defined (IP_PKTINFO) && defined (OS_LINUX)
166 struct in_pktinfo* pktinfo;
167 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
169 while (cmsg != NULL) {
170 if ((cmsg->cmsg_level == IPPROTO_IP) &&
171 (cmsg->cmsg_type == IP_PKTINFO)) {
172 pktinfo =
reinterpret_cast<struct in_pktinfo*
>(CMSG_DATA(cmsg));
174 pkt->setIndex(pktinfo->ipi_ifindex);
175 pkt->setLocalAddr(
IOAddress(htonl(pktinfo->ipi_addr.s_addr)));
186 cmsg = CMSG_NXTHDR(&m, cmsg);
189 #elif defined (IP_RECVDSTADDR) && defined (OS_BSD)
190 struct in_addr* to_addr;
191 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
193 while (cmsg != NULL) {
194 if ((cmsg->cmsg_level == IPPROTO_IP) &&
195 (cmsg->cmsg_type == IP_RECVDSTADDR)) {
196 to_addr =
reinterpret_cast<struct in_addr*
>(CMSG_DATA(cmsg));
197 pkt->setLocalAddr(
IOAddress(htonl(to_addr->s_addr)));
200 cmsg = CMSG_NXTHDR(&m, cmsg);
209 PktFilterInet::send(
const Iface&, uint16_t sockfd,
const Pkt4Ptr& pkt) {
210 uint8_t control_buf[CONTROL_BUF_LEN];
211 memset(&control_buf[0], 0, CONTROL_BUF_LEN);
215 memset(&to, 0,
sizeof(to));
216 to.sin_family = AF_INET;
217 to.sin_port = htons(pkt->getRemotePort());
218 to.sin_addr.s_addr = htonl(pkt->getRemoteAddr().toUint32());
222 memset(&m, 0,
sizeof(m));
224 m.msg_namelen =
sizeof(to);
230 memset(&v, 0,
sizeof(v));
233 v.iov_base =
const_cast<void *
>(pkt->getBuffer().getData());
234 v.iov_len = pkt->getBuffer().getLength();
241 #if defined (IP_PKTINFO) && defined (OS_LINUX)
247 m.msg_control = &control_buf[0];
248 m.msg_controllen = CONTROL_BUF_LEN;
249 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
250 cmsg->cmsg_level = IPPROTO_IP;
251 cmsg->cmsg_type = IP_PKTINFO;
252 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_pktinfo));
253 struct in_pktinfo* pktinfo =(
struct in_pktinfo *)CMSG_DATA(cmsg);
254 memset(pktinfo, 0,
sizeof(
struct in_pktinfo));
260 if (pkt->indexSet()) {
261 pktinfo->ipi_ifindex = pkt->getIndex();
266 if (!pkt->getLocalAddr().isV4Zero()) {
267 pktinfo->ipi_spec_dst.s_addr = htonl(pkt->getLocalAddr().toUint32());
270 m.msg_controllen = CMSG_SPACE(
sizeof(
struct in_pktinfo));
273 pkt->updateTimestamp();
275 int result = sendmsg(sockfd, &m, 0);
278 " with an error: " << strerror(errno));
uint32_t toUint32() const
Converts IPv4 address to uint32_t.
IfaceMgr exception thrown thrown when socket opening or configuration failed.
uint32_t getIndex() const
Returns interface index.
Represents a single network interface.
#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.
uint16_t port_
bound address
IfaceMgr exception thrown thrown when error occurred during reading data from socket.
bool flag_broadcast_
Flag specifies if selected interface is broadcast capable.
std::string getName() const
Returns interface name.
Defines the logger used by the top-level component of kea-dhcp-ddns.
Represents DHCPv4 packet.
The IOAddress class represents an IP addresses (version agnostic)
IfaceMgr exception thrown thrown when error occurred during sending data through socket.
Holds information about socket.