If config file changed, drop leases and re-disover.

Fix minor issues with IN_IFF_TENTATIVE.
This commit is contained in:
Roy Marples 2015-05-01 12:39:06 +00:00
parent c37a324e88
commit 727d845922
7 changed files with 66 additions and 49 deletions

3
arp.c
View File

@ -41,6 +41,7 @@
#define ELOOP_QUEUE 5
#include "config.h"
#include "arp.h"
#include "if.h"
#include "ipv4.h"
#include "common.h"
#include "dhcp.h"
@ -406,7 +407,7 @@ arp_handleifa(int cmd, struct interface *ifp, const struct in_addr *addr,
if (flags & IN_IFF_DUPLICATED) {
if (astate->conflicted_cb)
astate->conflicted_cb(astate, NULL);
} else if (!(flags & IN_IFF_TENTATIVE)) {
} else if (!(flags & IN_IFF_NOTUSEABLE)) {
if (astate->probed_cb)
astate->probed_cb(astate);
}

59
dhcp.c
View File

@ -1589,6 +1589,9 @@ send_message(struct interface *ifp, uint8_t type,
in_addr_t a = INADDR_ANY;
struct timespec tv;
int s;
#ifdef IN_IFF_NOTUSEABLE
struct ipv4_addr *ia;
#endif
if (!callback)
logger(ifp->ctx, LOG_DEBUG, "%s: sending %s with xid 0x%x",
@ -1621,6 +1624,10 @@ send_message(struct interface *ifp, uint8_t type,
if (state->added && !(state->added & STATE_FAKE) &&
state->addr.s_addr != INADDR_ANY &&
state->new != NULL &&
#ifdef IN_IFF_NOTUSEABLE
((ia = ipv4_iffindaddr(ifp, &state->addr, NULL)) &&
!(ia->addr_flags & IN_IFF_NOTUSEABLE)) &&
#endif
(state->new->cookie == htonl(MAGIC_COOKIE) ||
ifp->options->options & DHCPCD_INFORM))
{
@ -2438,6 +2445,9 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp,
size_t auth_len;
char *msg;
struct arp_state *astate;
#ifdef IN_IFF_DUPLICATED
struct ipv4_addr *ia;
#endif
/* We may have found a BOOTP server */
if (get_option_uint8(ifp->ctx, &type, dhcp, DHO_MESSAGETYPE) == -1)
@ -2648,13 +2658,23 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp,
return;
}
#ifdef IN_IFF_DUPLICATED
ia = ipv4_iffindaddr(ifp, &lease->addr, NULL);
if (ia && ia->addr_flags & IN_IFF_DUPLICATED) {
log_dhcp(LOG_WARNING, "declined duplicate address",
ifp, dhcp, from);
if (type)
dhcp_decline(ifp);
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
eloop_timeout_add_sec(ifp->ctx->eloop,
DHCP_RAND_MAX, dhcp_discover, ifp);
return;
}
#endif
if ((type == 0 || type == DHCP_OFFER) &&
(state->state == DHS_DISCOVER || state->state == DHS_IPV4LL_BOUND))
{
#ifdef IN_IFF_DUPLICATED
struct ipv4_addr *ia;
#endif
lease->frominfo = 0;
lease->addr.s_addr = dhcp->yiaddr;
lease->cookie = dhcp->cookie;
@ -2663,18 +2683,6 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp,
&lease->server, dhcp, DHO_SERVERID) != 0)
lease->server.s_addr = INADDR_ANY;
log_dhcp(LOG_INFO, "offered", ifp, dhcp, from);
#ifdef IN_IFF_DUPLICATED
ia = ipv4_iffindaddr(ifp, &lease->addr, NULL);
if (ia && ia->addr_flags & IN_IFF_DUPLICATED) {
log_dhcp(LOG_WARNING, "declined duplicate address",
ifp, dhcp, from);
dhcp_decline(ifp);
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
eloop_timeout_add_sec(ifp->ctx->eloop,
DHCP_RAND_MAX, dhcp_discover, ifp);
return;
}
#endif
free(state->offer);
state->offer = dhcp;
*dhcpp = NULL;
@ -2739,13 +2747,19 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp,
lease->frominfo = 0;
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
astate = NULL;
if (ifo->options & DHCPCD_ARP &&
state->addr.s_addr != state->offer->yiaddr)
#ifndef IN_IFF_TENTATIVE
if (ifo->options & DHCPCD_ARP
&& state->addr.s_addr != state->offer->yiaddr)
#endif
{
addr.s_addr = state->offer->yiaddr;
#ifndef IN_IFF_TENTATIVE
/* If the interface already has the address configured
* then we can't ARP for duplicate detection. */
addr.s_addr = state->offer->yiaddr;
if (!ipv4_iffindaddr(ifp, &addr, NULL)) {
ia = ipv4_findaddr(ifp->ctx, &addr);
if (ia) {
#endif
astate = arp_new(ifp, &addr);
if (astate) {
astate->probed_cb = dhcp_arp_probed;
@ -2756,8 +2770,8 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp,
}
#ifndef IN_IFF_TENTATIVE
return;
#endif
}
#endif
}
dhcp_bind(ifp, astate);
@ -3141,7 +3155,8 @@ dhcp_start1(void *arg)
/* Don't log an error if some other process
* is handling this. */
if (errno != EADDRINUSE)
logger(ifp->ctx, LOG_ERR, "dhcp_openudp: %m");
logger(ifp->ctx, LOG_ERR,
"%s: dhcp_openudp: %m", __func__);
} else
eloop_event_add(ifp->ctx->eloop,
ifp->ctx->udp_fd, dhcp_handleudp,

View File

@ -350,7 +350,7 @@ stop_interface(struct interface *ifp)
}
static void
configure_interface1(struct interface *ifp, struct if_options *old)
configure_interface1(struct interface *ifp)
{
struct if_options *ifo = ifp->options;
int ra_global, ra_iface;
@ -516,16 +516,6 @@ configure_interface1(struct interface *ifp, struct if_options *old)
/* If we are not sending an authentication option, don't require it */
if (!(ifo->auth.options & DHCPCD_AUTH_SEND))
ifo->auth.options &= ~DHCPCD_AUTH_REQUIRE;
/* If we ARPing something or options have changed,
* drop leases and restart */
if (old) {
/* Remove warning options for a fair comparison */
old->options &= ~(DHCPCD_WARNINGS | DHCPCD_CONF);
if (ifo->arping_len || memcmp(ifo, old, sizeof(*old)))
dhcpcd_drop(ifp, 0);
free(old);
}
}
int
@ -559,16 +549,10 @@ dhcpcd_selectprofile(struct interface *ifp, const char *profile)
} else
*ifp->profile = '\0';
if (profile) {
struct if_options *old;
old = ifp->options;
ifp->options = ifo;
configure_interface1(ifp, old);
} else {
free_options(ifp->options);
ifp->options = ifo;
}
free_options(ifp->options);
ifp->options = ifo;
if (profile)
configure_interface1(ifp);
return 1;
}
@ -576,13 +560,20 @@ static void
configure_interface(struct interface *ifp, int argc, char **argv,
unsigned long long options)
{
struct if_options *old;
time_t old;
old = ifp->options;
old = ifp->options ? ifp->options->mtime : 0;
dhcpcd_selectprofile(ifp, NULL);
add_options(ifp->ctx, ifp->name, ifp->options, argc, argv);
ifp->options->options |= options;
configure_interface1(ifp, old);
configure_interface1(ifp);
/* If the mtime has changed drop any old lease */
if (ifp->options && old != 0 && ifp->options->mtime != old) {
logger(ifp->ctx, LOG_WARNING,
"%s: confile file changed, expiring leases", ifp->name);
dhcpcd_drop(ifp, 0);
}
}
static void

View File

@ -28,6 +28,7 @@
#define _WITH_GETLINE /* Stop FreeBSD bitching */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <arpa/inet.h>
@ -2040,6 +2041,7 @@ read_config(struct dhcpcd_ctx *ctx,
{
struct if_options *ifo;
FILE *fp;
struct stat sb;
char *line, *buf, *option, *p;
size_t buflen;
ssize_t vlen;
@ -2196,6 +2198,8 @@ read_config(struct dhcpcd_ctx *ctx,
free(buf);
return ifo;
}
if (stat(ctx->cffile, &sb) == 0)
ifo->mtime = sb.st_mtime;
ldop = edop = NULL;
while ((line = get_line(&buf, &buflen, fp))) {

View File

@ -144,6 +144,7 @@ struct vivco {
};
struct if_options {
time_t mtime;
uint8_t iaid[4];
int metric;
uint8_t requestmask[256 / NBBY];

4
ipv4.c
View File

@ -987,13 +987,13 @@ ipv4_applyaddr(void *arg)
return;
}
#ifdef IN_IFF_TENTATIVE
#ifdef IN_IFF_NOTUSEABLE
ap = ipv4_iffindaddr(ifp, &lease->addr, NULL);
if (ap == NULL) {
logger(ifp->ctx, LOG_ERR, "%s: added address vanished",
ifp->name);
return;
} else if (ap->addr_flags & IN_IFF_TENTATIVE)
} else if (ap->addr_flags & IN_IFF_NOTUSEABLE)
return;
#endif

5
ipv4.h
View File

@ -30,6 +30,11 @@
#include "dhcpcd.h"
#ifdef IN_IFF_TENTATIVE
#define IN_IFF_NOTUSEABLE \
(IN_IFF_TENTATIVE | IN_IFF_DUPLICATED | IN_IFF_DETACHED)
#endif
struct rt {
TAILQ_ENTRY(rt) next;
struct in_addr dest;