#include "if.h"
#include "if-options.h"
#include "ipv4.h"
+#include "ipv4ll.h"
#include "ipv6.h"
#include "ipv6nd.h"
if_route(unsigned char cmd, const struct rt *rt)
{
const struct dhcp_state *state;
+ const struct ipv4ll_state *istate;
union sockunion {
struct sockaddr sa;
struct sockaddr_in sin;
ADDSU; \
}
- if (cmd != RTM_DELETE)
+ if (cmd != RTM_DELETE) {
state = D_CSTATE(rt->iface);
- else /* appease GCC */
+ istate = IPV4LL_DSTATE(rt->iface);
+ } else {
+ /* appease GCC */
state = NULL;
+ istate = NULL;
+ }
memset(&rtm, 0, sizeof(rtm));
rtm.hdr.rtm_version = RTM_VERSION;
rtm.hdr.rtm_seq = 1;
if (cmd != RTM_DELETE) {
rtm.hdr.rtm_addrs |= RTA_IFA | RTA_IFP;
/* None interface subnet routes are static. */
- if (rt->gate.s_addr != INADDR_ANY ||
+ if ((rt->gate.s_addr != INADDR_ANY ||
rt->net.s_addr != state->net.s_addr ||
- rt->dest.s_addr != (state->addr.s_addr & state->net.s_addr))
+ rt->dest.s_addr !=
+ (state->addr.s_addr & state->net.s_addr)) &&
+ (istate == NULL ||
+ rt->dest.s_addr !=
+ (istate->addr.s_addr & inaddr_llmask.s_addr) ||
+ rt->net.s_addr != inaddr_llmask.s_addr))
rtm.hdr.rtm_flags |= RTF_STATIC;
else {
#ifdef RTF_CLONING
}
if (rtm.hdr.rtm_addrs & RTA_IFA)
- ADDADDR(&state->addr);
+ ADDADDR(istate == NULL ? &state->addr : &istate->addr);
if (rt->mtu) {
rtm.hdr.rtm_inits |= RTV_MTU;
#include "dhcp.h"
#include "if.h"
#include "ipv4.h"
+#include "ipv4ll.h"
#include "ipv6.h"
#include "ipv6nd.h"
{
struct nlmr nlm;
int retval = 0;
- struct dhcp_state *state;
+ const struct dhcp_state *state;
+ const struct ipv4ll_state *istate;
memset(&nlm, 0, sizeof(nlm));
nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
nlm.rt.rtm_family = AF_INET;
nlm.rt.rtm_table = RT_TABLE_MAIN;
- state = D_STATE(rt->iface);
+ state = D_CSTATE(rt->iface);
+ istate = IPV4LL_CSTATE(rt->iface);
if (cmd == RTM_DELETE)
nlm.rt.rtm_scope = RT_SCOPE_NOWHERE;
else {
/* We only change route metrics for kernel routes */
- if (rt->dest.s_addr ==
+ if ((rt->dest.s_addr ==
(state->addr.s_addr & state->net.s_addr) &&
- rt->net.s_addr == state->net.s_addr)
+ rt->net.s_addr == state->net.s_addr) ||
+ (istate && rt->dest.s_addr ==
+ (istate->addr.s_addr & inaddr_llmask.s_addr) &&
+ rt->net.s_addr == inaddr_llmask.s_addr))
nlm.rt.rtm_protocol = RTPROT_KERNEL;
else
nlm.rt.rtm_protocol = RTPROT_BOOT;
&rt->dest.s_addr, sizeof(rt->dest.s_addr));
if (nlm.rt.rtm_protocol == RTPROT_KERNEL) {
add_attr_l(&nlm.hdr, sizeof(nlm), RTA_PREFSRC,
- &state->addr.s_addr, sizeof(state->addr.s_addr));
+ istate == NULL ? &state->addr.s_addr : &istate->addr.s_addr,
+ sizeof(state->addr.s_addr));
}
/* If a host route then don't add the gateway */
if ((cmd == RTM_ADD || cmd == RTM_CHANGE) &&
#ifdef HAVE_ROUTE_METRIC
/* With route metrics, we can safely add the new route before
* deleting the old route. */
- if (if_route(RTM_ADD, nrt) == 0) {
+ if (if_route(RTM_ADD, nrt) == 0) {
if (ort && if_route(RTM_DELETE, ort) == -1 && errno != ESRCH)
logger(nrt->iface->ctx, LOG_ERR, "if_route (DEL): %m");
return 0;
#include "ipv4ll.h"
#include "script.h"
-static const struct in_addr inaddr_llmask = { HTONL(LINKLOCAL_MASK) };
-static const struct in_addr inaddr_llbcast = { HTONL(LINKLOCAL_BRDC) };
+const struct in_addr inaddr_llmask = { HTONL(LINKLOCAL_MASK) };
+const struct in_addr inaddr_llbcast = { HTONL(LINKLOCAL_BRDC) };
static in_addr_t
ipv4ll_pick_addr(const struct arp_state *astate)
#endif
state->addr = astate->addr;
timespecclear(&state->defend);
+ if_initrt(ifp);
ipv4_buildroutes(ifp->ctx);
arp_announce(astate);
script_runreason(ifp, "IPV4LL");
#include "arp.h"
+extern const struct in_addr inaddr_llmask;
+extern const struct in_addr inaddr_llbcast;
+
#define LINKLOCAL_ADDR 0xa9fe0000
#define LINKLOCAL_MASK IN_CLASSB_NET
#define LINKLOCAL_BRDC (LINKLOCAL_ADDR | ~LINKLOCAL_MASK)