mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 10:18:25 +00:00
import of dnsmasq-2.35.tar.gz
This commit is contained in:
75
src/dhcp.c
75
src/dhcp.c
@@ -31,7 +31,7 @@ void dhcp_init(struct daemon *daemon)
|
||||
if (fd == -1)
|
||||
die (_("cannot create DHCP socket : %s"), NULL);
|
||||
|
||||
if (!fix_fd(fd) ||
|
||||
if (!fix_fd(fd) ||
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 ||
|
||||
#elif defined(IP_RECVIF)
|
||||
@@ -41,11 +41,24 @@ void dhcp_init(struct daemon *daemon)
|
||||
die(_("failed to set options on DHCP socket: %s"), NULL);
|
||||
|
||||
/* When bind-interfaces is set, there might be more than one dnmsasq
|
||||
instance binding port 67. That's Ok if they serve different networks.
|
||||
Need to set REUSEADDR to make this posible. */
|
||||
if ((daemon->options & OPT_NOWILD) &&
|
||||
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt)) == -1)
|
||||
die(_("failed to set SO_REUSEADDR on DHCP socket: %s"), NULL);
|
||||
instance binding port 67. That's OK if they serve different networks.
|
||||
Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD.
|
||||
OpenBSD <= 4.0 screws up IP_RECVIF when SO_REUSEPORT is set, but
|
||||
OpenBSD <= 3.9 doesn't have IP_RECVIF anyway, so we just have to elide
|
||||
this for OpenBSD 4.0, if you want more than one instance on oBSD4.0, tough. */
|
||||
|
||||
#ifndef OpenBSD4_0
|
||||
if (daemon->options & OPT_NOWILD)
|
||||
{
|
||||
#ifdef SO_REUSEPORT
|
||||
int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt));
|
||||
#else
|
||||
int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
|
||||
#endif
|
||||
if (rc == -1)
|
||||
die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
saddr.sin_family = AF_INET;
|
||||
@@ -116,8 +129,8 @@ void dhcp_packet(struct daemon *daemon, time_t now)
|
||||
#endif
|
||||
} control_u;
|
||||
|
||||
msg.msg_control = control_u.control;
|
||||
msg.msg_controllen = sizeof(control_u);
|
||||
msg.msg_control = NULL;
|
||||
msg.msg_controllen = 0;
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = &daemon->dhcp_packet;
|
||||
@@ -134,42 +147,48 @@ void dhcp_packet(struct daemon *daemon, time_t now)
|
||||
/* expand_buf may have moved buffer */
|
||||
mess = daemon->dhcp_packet.iov_base;
|
||||
msg.msg_controllen = sizeof(control_u);
|
||||
msg.msg_control = control_u.control;
|
||||
msg.msg_flags = 0;
|
||||
msg.msg_name = &dest;
|
||||
msg.msg_namelen = sizeof(dest);
|
||||
|
||||
while ((sz = recvmsg(daemon->dhcpfd, &msg, 0)) == -1 && errno == EINTR);
|
||||
|
||||
if ((msg.msg_flags & MSG_TRUNC) ||
|
||||
sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))
|
||||
if (sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))
|
||||
return;
|
||||
|
||||
#if defined (HAVE_LINUX_NETWORK)
|
||||
if (msg.msg_controllen < sizeof(struct cmsghdr))
|
||||
return;
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
|
||||
{
|
||||
iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
|
||||
if (((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_addr.s_addr != INADDR_BROADCAST)
|
||||
unicast_dest = 1;
|
||||
}
|
||||
|
||||
if (msg.msg_controllen >= sizeof(struct cmsghdr))
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO)
|
||||
{
|
||||
iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex;
|
||||
if (((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_addr.s_addr != INADDR_BROADCAST)
|
||||
unicast_dest = 1;
|
||||
}
|
||||
|
||||
if (!(ifr.ifr_ifindex = iface_index) ||
|
||||
ioctl(daemon->dhcpfd, SIOCGIFNAME, &ifr) == -1)
|
||||
return;
|
||||
|
||||
#elif defined(IP_RECVIF)
|
||||
if (msg.msg_controllen < sizeof(struct cmsghdr))
|
||||
return;
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
|
||||
iface_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
|
||||
|
||||
if (msg.msg_controllen >= sizeof(struct cmsghdr))
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
|
||||
iface_index = ((struct sockaddr_dl *)CMSG_DATA(cmptr))->sdl_index;
|
||||
|
||||
if (!iface_index || !if_indextoname(iface_index, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
|
||||
#ifdef MSG_BCAST
|
||||
/* OpenBSD tells us when a packet was broadcast */
|
||||
if (!(msg.msg_flags & MSG_BCAST))
|
||||
unicast_dest = 1;
|
||||
#endif
|
||||
|
||||
#else
|
||||
/* fallback for systems without IP_RECVIF - allow only one interface
|
||||
and assume packets arrive from it - yuk. */
|
||||
{
|
||||
struct iname *name;
|
||||
for (name = daemon->if_names; name->isloop; name = name->next);
|
||||
@@ -179,7 +198,7 @@ void dhcp_packet(struct daemon *daemon, time_t now)
|
||||
#endif
|
||||
|
||||
ifr.ifr_addr.sa_family = AF_INET;
|
||||
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) < 0 )
|
||||
if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1 )
|
||||
return;
|
||||
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user