Commit c7be0164 authored by Simon Kelley's avatar Simon Kelley

Suppress DHCP ping checks when allocating on the loopback interface.

parent d203af4a
...@@ -145,7 +145,7 @@ void dhcp_packet(time_t now, int pxe_fd) ...@@ -145,7 +145,7 @@ void dhcp_packet(time_t now, int pxe_fd)
struct cmsghdr *cmptr; struct cmsghdr *cmptr;
struct iovec iov; struct iovec iov;
ssize_t sz; ssize_t sz;
int iface_index = 0, unicast_dest = 0, is_inform = 0; int iface_index = 0, unicast_dest = 0, is_inform = 0, loopback = 0;
int rcvd_iface_index; int rcvd_iface_index;
struct in_addr iface_addr; struct in_addr iface_addr;
struct iface_param parm; struct iface_param parm;
...@@ -223,9 +223,13 @@ void dhcp_packet(time_t now, int pxe_fd) ...@@ -223,9 +223,13 @@ void dhcp_packet(time_t now, int pxe_fd)
} }
#endif #endif
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name)) if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name) ||
ioctl(daemon->dhcpfd, SIOCGIFFLAGS, &ifr) != -1)
return; return;
mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
loopback = !mess->giaddr.s_addr && (ifr.ifr_flags & IFF_LOOPBACK);
#ifdef HAVE_LINUX_NETWORK #ifdef HAVE_LINUX_NETWORK
/* ARP fiddling uses original interface even if we pretend to use a different one. */ /* ARP fiddling uses original interface even if we pretend to use a different one. */
strncpy(arp_req.arp_dev, ifr.ifr_name, 16); strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
...@@ -331,7 +335,7 @@ void dhcp_packet(time_t now, int pxe_fd) ...@@ -331,7 +335,7 @@ void dhcp_packet(time_t now, int pxe_fd)
/* We're relaying this request */ /* We're relaying this request */
if (parm.relay_local.s_addr != 0 && if (parm.relay_local.s_addr != 0 &&
relay_upstream4(parm.relay, (struct dhcp_packet *)daemon->dhcp_packet.iov_base, (size_t)sz, iface_index)) relay_upstream4(parm.relay, mess, (size_t)sz, iface_index))
return; return;
/* May have configured relay, but not DHCP server */ /* May have configured relay, but not DHCP server */
...@@ -340,7 +344,7 @@ void dhcp_packet(time_t now, int pxe_fd) ...@@ -340,7 +344,7 @@ void dhcp_packet(time_t now, int pxe_fd)
lease_prune(NULL, now); /* lose any expired leases */ lease_prune(NULL, now); /* lose any expired leases */
iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz, iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz,
now, unicast_dest, &is_inform, pxe_fd, iface_addr, recvtime); now, unicast_dest, loopback, &is_inform, pxe_fd, iface_addr, recvtime);
lease_update_file(now); lease_update_file(now);
lease_update_dns(0); lease_update_dns(0);
...@@ -647,7 +651,7 @@ struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct i ...@@ -647,7 +651,7 @@ struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct i
This wrapper handles a cache and load-limiting. This wrapper handles a cache and load-limiting.
Return is NULL is address in use, or a pointer to a cache entry Return is NULL is address in use, or a pointer to a cache entry
recording that it isn't. */ recording that it isn't. */
struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, unsigned int hash) struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, unsigned int hash, int loopback)
{ {
static struct ping_result dummy; static struct ping_result dummy;
struct ping_result *r, *victim = NULL; struct ping_result *r, *victim = NULL;
...@@ -671,9 +675,9 @@ struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, unsigned int h ...@@ -671,9 +675,9 @@ struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, unsigned int h
} }
/* didn't find cached entry */ /* didn't find cached entry */
if ((count >= max) || option_bool(OPT_NO_PING)) if ((count >= max) || option_bool(OPT_NO_PING) || loopback)
{ {
/* overloaded, or configured not to check, return "not in use" */ /* overloaded, or configured not to check, loopback interface, return "not in use" */
dummy.hash = 0; dummy.hash = 0;
return &dummy; return &dummy;
} }
...@@ -705,7 +709,7 @@ struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, unsigned int h ...@@ -705,7 +709,7 @@ struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, unsigned int h
int address_allocate(struct dhcp_context *context, int address_allocate(struct dhcp_context *context,
struct in_addr *addrp, unsigned char *hwaddr, int hw_len, struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
struct dhcp_netid *netids, time_t now) struct dhcp_netid *netids, time_t now, int loopback)
{ {
/* Find a free address: exclude anything in use and anything allocated to /* Find a free address: exclude anything in use and anything allocated to
a particular hwaddr/clientid/hostname in our configuration. a particular hwaddr/clientid/hostname in our configuration.
...@@ -763,7 +767,7 @@ int address_allocate(struct dhcp_context *context, ...@@ -763,7 +767,7 @@ int address_allocate(struct dhcp_context *context,
{ {
struct ping_result *r; struct ping_result *r;
if ((r = do_icmp_ping(now, addr, j))) if ((r = do_icmp_ping(now, addr, j, loopback)))
{ {
/* consec-ip mode: we offered this address for another client /* consec-ip mode: we offered this address for another client
(different hash) recently, don't offer it to this one. */ (different hash) recently, don't offer it to this one. */
......
...@@ -1292,10 +1292,10 @@ struct dhcp_context *narrow_context(struct dhcp_context *context, ...@@ -1292,10 +1292,10 @@ struct dhcp_context *narrow_context(struct dhcp_context *context,
struct in_addr taddr, struct in_addr taddr,
struct dhcp_netid *netids); struct dhcp_netid *netids);
struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, struct ping_result *do_icmp_ping(time_t now, struct in_addr addr,
unsigned int hash); unsigned int hash, int loopback);
int address_allocate(struct dhcp_context *context, int address_allocate(struct dhcp_context *context,
struct in_addr *addrp, unsigned char *hwaddr, int hw_len, struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
struct dhcp_netid *netids, time_t now); struct dhcp_netid *netids, time_t now, int loopback);
void dhcp_read_ethers(void); void dhcp_read_ethers(void);
struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr); struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr);
char *host_from_dns(struct in_addr addr); char *host_from_dns(struct in_addr addr);
...@@ -1344,7 +1344,8 @@ void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data, ...@@ -1344,7 +1344,8 @@ void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data,
/* rfc2131.c */ /* rfc2131.c */
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe_fd, struct in_addr fallback, time_t recvtime); size_t sz, time_t now, int unicast_dest, int loopback,
int *is_inform, int pxe_fd, struct in_addr fallback, time_t recvtime);
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr, unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
int clid_len, unsigned char *clid, int *len_out); int clid_len, unsigned char *clid, int *len_out);
#endif #endif
......
...@@ -67,7 +67,8 @@ static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dh ...@@ -67,7 +67,8 @@ static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dh
static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid); static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid);
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe, struct in_addr fallback, time_t recvtime) size_t sz, time_t now, int unicast_dest, int loopback,
int *is_inform, int pxe, struct in_addr fallback, time_t recvtime)
{ {
unsigned char *opt, *clid = NULL; unsigned char *opt, *clid = NULL;
struct dhcp_lease *ltmp, *lease = NULL; struct dhcp_lease *ltmp, *lease = NULL;
...@@ -575,7 +576,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, ...@@ -575,7 +576,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
lease_prune(lease, now); lease_prune(lease, now);
lease = NULL; lease = NULL;
} }
if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now)) if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now, loopback))
message = _("no address available"); message = _("no address available");
} }
else else
...@@ -1036,7 +1037,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, ...@@ -1036,7 +1037,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
else if (have_config(config, CONFIG_DECLINED) && else if (have_config(config, CONFIG_DECLINED) &&
difftime(now, config->decline_time) < (float)DECLINE_BACKOFF) difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs); my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), addrs);
else if (!do_icmp_ping(now, config->addr, 0)) else if (!do_icmp_ping(now, config->addr, 0, loopback))
my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by another host"), addrs); my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by another host"), addrs);
else else
conf = config->addr; conf = config->addr;
...@@ -1050,11 +1051,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, ...@@ -1050,11 +1051,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
!config_find_by_address(daemon->dhcp_conf, lease->addr)) !config_find_by_address(daemon->dhcp_conf, lease->addr))
mess->yiaddr = lease->addr; mess->yiaddr = lease->addr;
else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) && else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) &&
!config_find_by_address(daemon->dhcp_conf, addr) && do_icmp_ping(now, addr, 0)) !config_find_by_address(daemon->dhcp_conf, addr) && do_icmp_ping(now, addr, 0, loopback))
mess->yiaddr = addr; mess->yiaddr = addr;
else if (emac_len == 0) else if (emac_len == 0)
message = _("no unique-id"); message = _("no unique-id");
else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now)) else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now, loopback))
message = _("no address available"); message = _("no address available");
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment