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);
44 if (receive_bcast && iface.flag_broadcast_) {
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);
72 if (receive_bcast && iface.flag_broadcast_) {
74 if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface.getName().c_str(),
75 iface.getName().length() + 1) < 0) {
78 <<
" on socket " << sock);
83 if (send_bcast && iface.flag_broadcast_) {
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));
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.