for IPv4LL.
Call IPV4LL instead of EXPIRE when removing the IPV4LL address,
which is similar to how ROUTERADVERT works.
#include <sys/socket.h>
#include <sys/types.h>
+#include <arpa/inet.h>
+
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include "if.h"
#include "ipv4.h"
#include "common.h"
-#include "dhcp.h"
#include "dhcpcd.h"
#include "eloop.h"
#include "if.h"
if (bytes == -1) {
logger(ifp->ctx, LOG_ERR,
"%s: arp if_readrawpacket: %m", ifp->name);
- dhcp_close(ifp);
+ arp_close(ifp);
return;
}
/* We must have a full ARP header */
#ifdef IN_IFF_DUPLICATED
ia = ipv4_iffindaddr(ifp, &astate->addr, NULL);
if (ia)
- ipv4_deladdr(ifp, &ia->addr, &ia->net);
+ ipv4_deladdr(ifp, &ia->addr, &ia->net, 1);
#endif
arp_free(astate);
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
ifp, dhcp, from);
if (type)
dhcp_decline(ifp);
- ipv4_deladdr(ifp, &ia->addr, &ia->net);
+ ipv4_deladdr(ifp, &ia->addr, &ia->net, 0);
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
eloop_timeout_add_sec(ifp->ctx->eloop,
DHCP_RAND_MAX, dhcp_discover, ifp);
const struct iarp_state *istate;
istate = ARP_CSTATE(ifp);
+ assert(istate != NULL);
return istate->fd;
} else {
const struct dhcp_state *dstate;
dstate = D_CSTATE(ifp);
+ assert(dstate != NULL);
return dstate->raw_fd;
}
}
int
ipv4_deladdr(struct interface *ifp,
- const struct in_addr *addr, const struct in_addr *net)
+ const struct in_addr *addr, const struct in_addr *net, int keeparp)
{
struct dhcp_state *dstate;
int r;
errno != ENODEV)
logger(ifp->ctx, LOG_ERR, "%s: %s: %m", ifp->name, __func__);
- if ((astate = arp_find(ifp, addr)) != NULL)
+ if (!keeparp && (astate = arp_find(ifp, addr)) != NULL)
arp_free(astate);
state = IPV4_STATE(ifp);
if (ifo->options & DHCPCD_INFORM ||
(ifo->options & DHCPCD_STATIC && ifo->req_addr.s_addr == 0))
return 0;
- r = ipv4_deladdr(ifp, &state->addr, &state->net);
+ r = ipv4_deladdr(ifp, &state->addr, &state->net, 0);
return r;
}
TAILQ_FOREACH_SAFE(ia, &state->addrs, next, ian) {
if (ia->addr.s_addr != addr->s_addr)
- ipv4_deladdr(ifp, &ia->addr, &ia->net);
+ ipv4_deladdr(ifp, &ia->addr, &ia->net, 0);
}
}
ifn->name,
inet_ntoa(lease->addr),
ifp->name);
- ipv4_deladdr(ifn, &nstate->addr, &nstate->net);
+ ipv4_deladdr(ifn, &nstate->addr, &nstate->net, 0);
break;
}
}
continue;
ap = ipv4_iffindaddr(ifn, &lease->addr, NULL);
if (ap)
- ipv4_deladdr(ifn, &ap->addr, &ap->net);
+ ipv4_deladdr(ifn, &ap->addr, &ap->net, 0);
}
}
/* If the netmask is different, delete the addresss */
ap = ipv4_iffindaddr(ifp, &lease->addr, NULL);
if (ap && ap->net.s_addr != lease->net.s_addr)
- ipv4_deladdr(ifp, &ap->addr, &ap->net);
+ ipv4_deladdr(ifp, &ap->addr, &ap->net, 0);
if (ipv4_iffindaddr(ifp, &lease->addr, &lease->net))
logger(ifp->ctx, LOG_DEBUG,
void ipv4_buildroutes(struct dhcpcd_ctx *);
int ipv4_deladdr(struct interface *, const struct in_addr *,
- const struct in_addr *);
+ const struct in_addr *, int);
int ipv4_preferanother(struct interface *);
struct ipv4_addr *ipv4_addaddr(struct interface *,
const struct in_addr *, const struct in_addr *, const struct in_addr *);
* SUCH DAMAGE.
*/
+#include <arpa/inet.h>
+
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include "config.h"
#include "arp.h"
#include "common.h"
-#include "dhcp.h"
#include "eloop.h"
#include "if.h"
#include "if-options.h"
static void
ipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
{
+ struct interface *ifp;
struct ipv4ll_state *state;
in_addr_t fail;
assert(astate != NULL);
assert(astate->iface != NULL);
- state = IPV4LL_STATE(astate->iface);
+ ifp = astate->iface;
+ state = IPV4LL_STATE(ifp);
assert(state != NULL);
fail = 0;
defend.tv_nsec = state->defend.tv_nsec;
clock_gettime(CLOCK_MONOTONIC, &now);
if (timespeccmp(&defend, &now, >)) {
- logger(astate->iface->ctx, LOG_WARNING,
+ logger(ifp->ctx, LOG_WARNING,
"%s: IPv4LL %d second defence failed for %s",
- astate->iface->name, DEFEND_INTERVAL,
+ ifp->name, DEFEND_INTERVAL,
inet_ntoa(state->addr));
- dhcp_drop(astate->iface, "EXPIRE");
+ ipv4_deladdr(ifp, &state->addr, &inaddr_llmask, 1);
+ state->addr.s_addr = INADDR_ANY;
+ script_runreason(ifp, "IPV4LL");
} else {
- logger(astate->iface->ctx, LOG_DEBUG,
+ logger(ifp->ctx, LOG_DEBUG,
"%s: defended IPv4LL address %s",
- astate->iface->name, inet_ntoa(state->addr));
+ ifp->name, inet_ntoa(state->addr));
state->defend = now;
return;
}
arp_cancel(astate);
if (++state->conflicts == MAX_CONFLICTS)
- logger(astate->iface->ctx, LOG_ERR,
+ logger(ifp->ctx, LOG_ERR,
"%s: failed to acquire an IPv4LL address",
- astate->iface->name);
+ ifp->name);
astate->addr.s_addr = ipv4ll_pick_addr(astate);
- eloop_timeout_add_sec(astate->iface->ctx->eloop,
+ eloop_timeout_add_sec(ifp->ctx->eloop,
state->conflicts >= MAX_CONFLICTS ?
RATE_LIMIT_INTERVAL : PROBE_WAIT,
ipv4ll_probe, astate);
ia = ipv4_iffindlladdr(ifp);
#ifdef IN_IFF_TENTATIVE
if (ia != NULL && ia->addr_flags & IN_IFF_DUPLICATED) {
- ipv4_deladdr(ifp, &ia->addr, &ia->net);
+ ipv4_deladdr(ifp, &ia->addr, &ia->net, 0);
ia = NULL;
}
#endif
state->arp = NULL;
}
- /* Unlike other protocols, we don't run a script on stopping IPv4LL
- * because we piggy back on the state of DHCP. */
if (drop && (ifp->options->options & DHCPCD_NODROP) != DHCPCD_NODROP) {
struct ipv4_state *istate;
if (state && state->addr.s_addr != INADDR_ANY) {
- ipv4_deladdr(ifp, &state->addr, &inaddr_llmask);
+ ipv4_deladdr(ifp, &state->addr, &inaddr_llmask, 1);
state->addr.s_addr = INADDR_ANY;
}
TAILQ_FOREACH_SAFE(ia, &istate->addrs, next, ian) {
if (IN_LINKLOCAL(ntohl(ia->addr.s_addr)))
- ipv4_deladdr(ifp, &ia->addr, &ia->net);
+ ipv4_deladdr(ifp, &ia->addr,
+ &ia->net, 0);
}
}
+ script_runreason(ifp, "IPV4LL");
}
if (state) {