fake add the routes so the lease can be cleaned up if needed.
dhcp_auth_reset(&state->auth);
dhcp_close(ifp);
}
+
if (ifp->options->options & DHCPCD_RELEASE) {
unlink(state->leasefile);
if (ifp->carrier != LINK_DOWN &&
#endif
}
}
+
free(state->old);
state->old = state->new;
state->new = NULL;
if (state->offer) {
get_lease(ifp->ctx, &state->lease, state->offer);
state->lease.frominfo = 1;
+ if (state->new == NULL &&
+ ipv4_iffindaddr(ifp, &state->lease.addr, &state->lease.net))
+ {
+ /* We still have the IP address from the last lease.
+ * Fake add the address and routes from it so the lease
+ * can be cleaned up. */
+ state->new = malloc(sizeof(*state->new));
+ if (state->new) {
+ memcpy(state->new, state->offer,
+ sizeof(*state->new));
+ state->addr = state->lease.addr;
+ state->net = state->lease.net;
+ state->added |= STATE_ADDED | STATE_FAKE;
+ ipv4_buildroutes(ifp->ctx);
+ } else
+ syslog(LOG_ERR, "%s: %m", __func__);
+ }
if (state->offer->cookie == 0) {
if (state->offer->yiaddr == state->addr.s_addr) {
free(state->offer);
free(state->offer);
state->offer = NULL;
state->lease.addr.s_addr = 0;
+ if (state->new)
+ dhcp_drop(ifp, "EXPIRE");
} else {
l = (uint32_t)(now.tv_sec - st.st_mtime);
state->lease.leasetime -= l;
struct rt_head *nrs, *dnr;
struct rt *or, *rt, *rtn;
struct interface *ifp;
- const struct dhcp_state *state;
+ const struct dhcp_state *state, *ostate;
nrs = malloc(sizeof(*nrs));
if (nrs == NULL) {
rt->src.s_addr = state->addr.s_addr;
/* Do we already manage it? */
if ((or = find_route(ctx->ipv4_routes, rt, NULL))) {
+ if (state->added & STATE_FAKE)
+ continue;
+ ostate = D_CSTATE(or->iface);
+ if (ostate->added & STATE_FAKE)
+ goto remroute;
if (or->iface != ifp ||
or->src.s_addr != state->addr.s_addr ||
rt->gate.s_addr != or->gate.s_addr ||
if (c_route(or, rt) != 0)
continue;
}
+remroute:
TAILQ_REMOVE(ctx->ipv4_routes, or, next);
free(or);
} else {
- if (n_route(rt) != 0)
+ if (!(state->added & STATE_FAKE) &&
+ n_route(rt) != 0)
continue;
}
TAILQ_REMOVE(dnr, rt, next);
} else {
ipv4_addaddr(ifn,
&nstate->lease);
- nstate->added = 1;
+ nstate->added =
+ STATE_ADDED;
}
break;
}
state->addr.s_addr != 0)
delete_address(ifp);
- state->added = 1;
+ state->added = STATE_ADDED;
state->defend = 0;
state->addr.s_addr = lease->addr.s_addr;
state->net.s_addr = lease->net.s_addr;
uint32_t ipv4_getnetmask(uint32_t);
int ipv4_addrexists(struct dhcpcd_ctx *, const struct in_addr *);
+#define STATE_ADDED 0x01
+#define STATE_FAKE 0x02
+
void ipv4_buildroutes(struct dhcpcd_ctx *);
void ipv4_applyaddr(void *);
int ipv4_routedeleted(struct dhcpcd_ctx *, const struct rt *);