}
#ifdef HAVE_LINUX_NETWORK
-void bindtodevice(int fd)
+char *whichdevice(void)
{
/* If we are doing DHCP on exactly one interface, and running linux, do SO_BINDTODEVICE
to that device. This is for the use case of (eg) OpenStack, which runs a new
struct irec *iface, *found;
struct iname *if_tmp;
-
+
if (!daemon->if_names)
- return;
-
+ return NULL;
+
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
if (if_tmp->name && (!if_tmp->used || strchr(if_tmp->name, '*')))
- return;
+ return NULL;
for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
if (iface->dhcp_ok)
if (!found)
found = iface;
else if (strcmp(found->name, iface->name) != 0)
- return; /* more than one. */
+ return NULL; /* more than one. */
}
-
+
if (found)
- {
- struct ifreq ifr;
- strcpy(ifr.ifr_name, found->name);
- /* only allowed by root. */
- if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
- errno != EPERM)
- die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
- }
+ return found->name;
+
+ return NULL;
+}
+
+void bindtodevice(char *device, int fd)
+{
+ struct ifreq ifr;
+
+ strcpy(ifr.ifr_name, device);
+ /* only allowed by root. */
+ if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
+ errno != EPERM)
+ die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
}
#endif
#if defined(HAVE_LINUX_NETWORK)
cap_user_header_t hdr = NULL;
cap_user_data_t data = NULL;
+ char *bound_device = NULL;
+ int did_bind = 0;
#endif
#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
struct dhcp_context *context;
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
/* after enumerate_interfaces() */
+ bound_device = whichdevice();
+
if (daemon->dhcp)
{
- if (!daemon->relay4)
- bindtodevice(daemon->dhcpfd);
- if (daemon->enable_pxe)
- bindtodevice(daemon->pxefd);
+ if (!daemon->relay4 && bound_device)
+ {
+ bindtodevice(bound_device, daemon->dhcpfd);
+ did_bind = 1;
+ }
+ if (daemon->enable_pxe && bound_device)
+ {
+ bindtodevice(bound_device, daemon->pxefd);
+ did_bind = 1;
+ }
}
#endif
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
- if (daemon->doing_dhcp6 && !daemon->relay6)
- bindtodevice(daemon->dhcp6fd);
+ if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
+ {
+ bindtodevice(bound_device, daemon->dhcp6fd);
+ did_bind = 1;
+ }
#endif
}
else
my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
# endif
+# ifdef HAVE_LINUX_NETWORK
+ if (did_bind)
+ my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
+# endif
+
/* after dhcp_contruct_contexts */
if (daemon->dhcp || daemon->doing_dhcp6)
lease_find_interfaces(now);
int hw_type, char *hostname);
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
#ifdef HAVE_LINUX_NETWORK
-void bindtodevice(int fd);
+char *whichdevice(void);
+void bindtodevice(char *device, int fd);
#endif
# ifdef HAVE_DHCP6
void display_opts6(void);