20 PktFilterInet::PktFilterInet()
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);
60 #ifdef SO_BINDTODEVICE
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));