summaryrefslogtreecommitdiff
path: root/proto
diff options
context:
space:
mode:
authorOndrej Zajicek (work) <santiago@crfreenet.org>2017-12-07 13:06:01 +0100
committerOndrej Zajicek (work) <santiago@crfreenet.org>2017-12-07 13:06:01 +0100
commit153f02da3bce1f3f1a99295648679c71327e8319 (patch)
treeb7b7acf8026ba182f3a81f2d6da975b0b1524972 /proto
parent4ae3ee1200b386219673c2168eae996c6207b077 (diff)
Nest: Maintain separate IPv4, IPv6 and LLv6 preferred addresses
Also redesign preferred address selection and update protocols to use appropriate preferred address. Based on a previous work by Jan Maria Matejka.
Diffstat (limited to 'proto')
-rw-r--r--proto/babel/babel.c47
-rw-r--r--proto/babel/packets.c3
-rw-r--r--proto/bgp/bgp.c15
-rw-r--r--proto/radv/packets.c2
-rw-r--r--proto/radv/radv.c41
-rw-r--r--proto/rip/packets.c12
-rw-r--r--proto/rip/rip.c18
7 files changed, 61 insertions, 77 deletions
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index a0ec3629..23746155 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -1501,26 +1501,14 @@ babel_add_iface(struct babel_proto *p, struct iface *new, struct babel_iface_con
ifa->cf = ic;
ifa->pool = pool;
ifa->ifname = new->name;
+ ifa->addr = new->llv6->ip;
add_tail(&p->interfaces, NODE ifa);
- ip_addr addr4 = IPA_NONE;
- struct ifa *addr;
- WALK_LIST(addr, new->addrs)
- {
- if (ipa_is_link_local(addr->ip))
- ifa->addr = addr->ip;
-
- if (ipa_zero(addr4) && ipa_is_ip4(addr->ip))
- addr4 = addr->ip;
- }
-
+ ip_addr addr4 = new->addr4 ? new->addr4->ip : IPA_NONE;
ifa->next_hop_ip4 = ipa_nonzero(ic->next_hop_ip4) ? ic->next_hop_ip4 : addr4;
ifa->next_hop_ip6 = ipa_nonzero(ic->next_hop_ip6) ? ic->next_hop_ip6 : ifa->addr;
- if (ipa_zero(ifa->addr))
- log(L_WARN "%s: Cannot find link-local addr on %s", p->p.name, new->name);
-
if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel)
log(L_WARN "%s: Cannot find IPv4 next hop addr on %s", p->p.name, new->name);
@@ -1576,6 +1564,10 @@ babel_if_notify(struct proto *P, unsigned flags, struct iface *iface)
if (!(iface->flags & IF_MULTICAST))
return;
+ /* Ignore ifaces without link-local address */
+ if (!iface->llv6)
+ return;
+
if (ic)
babel_add_iface(p, iface, ic);
@@ -1615,21 +1607,8 @@ babel_reconfigure_iface(struct babel_proto *p, struct babel_iface *ifa, struct b
ifa->cf = new;
- if (ipa_nonzero(new->next_hop_ip4))
- ifa->next_hop_ip4 = new->next_hop_ip4;
- else
- {
- ifa->next_hop_ip4 = IPA_NONE;
-
- struct ifa *addr;
- WALK_LIST(addr, ifa->iface->addrs)
- if (ipa_is_ip4(addr->ip))
- {
- ifa->next_hop_ip4 = addr->ip;
- break;
- }
- }
-
+ ip_addr addr4 = ifa->iface->addr4 ? ifa->iface->addr4->ip : IPA_NONE;
+ ifa->next_hop_ip4 = ipa_nonzero(new->next_hop_ip4) ? new->next_hop_ip4 : addr4;
ifa->next_hop_ip6 = ipa_nonzero(new->next_hop_ip6) ? new->next_hop_ip6 : ifa->addr;
if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel)
@@ -1660,7 +1639,15 @@ babel_reconfigure_ifaces(struct babel_proto *p, struct babel_config *cf)
WALK_LIST(iface, iface_list)
{
- if (! (iface->flags & IF_UP))
+ if (!(iface->flags & IF_UP))
+ continue;
+
+ /* Ignore non-multicast ifaces */
+ if (!(iface->flags & IF_MULTICAST))
+ continue;
+
+ /* Ignore ifaces without link-local address */
+ if (!iface->llv6)
continue;
struct babel_iface *ifa = babel_find_iface(p, iface);
diff --git a/proto/babel/packets.c b/proto/babel/packets.c
index 78c133e0..d136efe8 100644
--- a/proto/babel/packets.c
+++ b/proto/babel/packets.c
@@ -1294,7 +1294,7 @@ babel_rx_hook(sock *sk, uint len)
sk->iface->name, sk->faddr, sk->laddr);
/* Silently ignore my own packets */
- if (ipa_equal(ifa->iface->addr->ip, sk->faddr))
+ if (ipa_equal(sk->faddr, sk->saddr))
return 1;
if (!ipa_is_link_local(sk->faddr))
@@ -1329,6 +1329,7 @@ babel_open_socket(struct babel_iface *ifa)
sk->sport = ifa->cf->port;
sk->dport = ifa->cf->port;
sk->iface = ifa->iface;
+ sk->saddr = ifa->addr;
sk->rx_hook = babel_rx_hook;
sk->tx_hook = babel_tx_hook;
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index cccced57..a8d5cf9d 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -1094,19 +1094,8 @@ bgp_start_neighbor(struct bgp_proto *p)
if (ipa_is_link_local(p->source_addr))
p->link_addr = p->source_addr;
- else
- {
- /* Find some link-local address for given iface */
- struct ifa *a;
- WALK_LIST(a, p->neigh->iface->addrs)
- if (a->scope == SCOPE_LINK)
- {
- p->link_addr = a->ip;
- break;
- }
-
- DBG("%s: Selected link-local address %I\n", p->p.name, p->link_addr);
- }
+ else if (p->neigh->iface->llv6)
+ p->link_addr = p->neigh->iface->llv6->ip;
bgp_initiate(p);
}
diff --git a/proto/radv/packets.c b/proto/radv/packets.c
index 15ca5738..9ea8feee 100644
--- a/proto/radv/packets.c
+++ b/proto/radv/packets.c
@@ -358,7 +358,7 @@ radv_rx_hook(sock *sk, uint size)
if (sk->lifindex != sk->iface->index)
return 1;
- if (ipa_equal(sk->faddr, ifa->addr->ip))
+ if (ipa_equal(sk->faddr, sk->saddr))
return 1;
if (size < 8)
diff --git a/proto/radv/radv.c b/proto/radv/radv.c
index b4b1bc58..2c0a23ad 100644
--- a/proto/radv/radv.c
+++ b/proto/radv/radv.c
@@ -138,17 +138,6 @@ radv_iface_add(struct object_lock *lock)
radv_iface_notify(ifa, RA_EV_INIT);
}
-static inline struct ifa *
-find_lladdr(struct iface *iface)
-{
- struct ifa *a;
- WALK_LIST(a, iface->addrs)
- if ((a->prefix.type == NET_IP6) && (a->scope == SCOPE_LINK))
- return a;
-
- return NULL;
-}
-
static void
radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_config *cf)
{
@@ -161,16 +150,10 @@ radv_iface_new(struct radv_proto *p, struct iface *iface, struct radv_iface_conf
ifa->ra = p;
ifa->cf = cf;
ifa->iface = iface;
+ ifa->addr = iface->llv6;
add_tail(&p->iface_list, NODE ifa);
- ifa->addr = find_lladdr(iface);
- if (!ifa->addr)
- {
- log(L_ERR "%s: Missing link-local address on interface %s", p->p.name, iface->name);
- return;
- }
-
timer *tm = tm_new(pool);
tm->hook = radv_timer;
tm->data = ifa;
@@ -216,8 +199,15 @@ radv_if_notify(struct proto *P, unsigned flags, struct iface *iface)
if (flags & IF_CHANGE_UP)
{
- struct radv_iface_config *ic = (struct radv_iface_config *)
- iface_patt_find(&cf->patt_list, iface, NULL);
+ struct radv_iface_config *ic = (void *) iface_patt_find(&cf->patt_list, iface, NULL);
+
+ /* Ignore non-multicast ifaces */
+ if (!(iface->flags & IF_MULTICAST))
+ return;
+
+ /* Ignore ifaces without link-local address */
+ if (!iface->llv6)
+ return;
if (ic)
radv_iface_new(p, iface, ic);
@@ -395,6 +385,17 @@ radv_reconfigure(struct proto *P, struct proto_config *CF)
struct iface *iface;
WALK_LIST(iface, iface_list)
{
+ if (!(iface->flags & IF_UP))
+ continue;
+
+ /* Ignore non-multicast ifaces */
+ if (!(iface->flags & IF_MULTICAST))
+ continue;
+
+ /* Ignore ifaces without link-local address */
+ if (!iface->llv6)
+ continue;
+
struct radv_iface *ifa = radv_iface_find(p, iface);
struct radv_iface_config *ic = (struct radv_iface_config *)
iface_patt_find(&new->patt_list, iface, NULL);
diff --git a/proto/rip/packets.c b/proto/rip/packets.c
index e97809c8..de48fd0a 100644
--- a/proto/rip/packets.c
+++ b/proto/rip/packets.c
@@ -669,8 +669,7 @@ rip_rx_hook(sock *sk, uint len)
sk->iface->name, sk->faddr, sk->laddr);
/* Silently ignore my own packets */
- /* FIXME: Better local address check */
- if (ipa_equal(ifa->iface->addr->ip, sk->faddr))
+ if (ipa_equal(sk->faddr, sk->saddr))
return 1;
if (rip_is_ng(p) && !ipa_is_link_local(sk->faddr))
@@ -742,14 +741,7 @@ rip_open_socket(struct rip_iface *ifa)
sk->sport = ifa->cf->port;
sk->dport = ifa->cf->port;
sk->iface = ifa->iface;
-
- /*
- * For RIPv2, we explicitly choose a primary address, mainly to ensure that
- * RIP and BFD uses the same one. For RIPng, we left it to kernel, which
- * should choose some link-local address based on the same scope rule.
- */
- if (rip_is_v2(p))
- sk->saddr = ifa->iface->addr->ip;
+ sk->saddr = rip_is_v2(p) ? ifa->iface->addr4->ip : ifa->iface->llv6->ip;
sk->rx_hook = rip_rx_hook;
sk->tx_hook = rip_tx_hook;
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index 55fb47c5..820c5117 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -630,7 +630,13 @@ rip_add_iface(struct rip_proto *p, struct iface *iface, struct rip_iface_config
else if (ic->mode == RIP_IM_MULTICAST)
ifa->addr = rip_is_v2(p) ? IP4_RIP_ROUTERS : IP6_RIP_ROUTERS;
else /* Broadcast */
- ifa->addr = iface->addr->brd;
+ ifa->addr = iface->addr4->brd;
+ /*
+ * The above is just a workaround for BSD as it can't send broadcasts
+ * to 255.255.255.255. BSD systems need the network broadcast address instead.
+ *
+ * TODO: move this to sysdep code
+ */
init_list(&ifa->neigh_list);
@@ -706,7 +712,11 @@ rip_reconfigure_ifaces(struct rip_proto *p, struct rip_config *cf)
WALK_LIST(iface, iface_list)
{
- if (! (iface->flags & IF_UP))
+ if (!(iface->flags & IF_UP))
+ continue;
+
+ /* Ignore ifaces without appropriate address */
+ if (rip_is_v2(p) ? !iface->addr4 : !iface->llv6)
continue;
struct rip_iface *ifa = rip_find_iface(p, iface);
@@ -744,6 +754,10 @@ rip_if_notify(struct proto *P, unsigned flags, struct iface *iface)
{
struct rip_iface_config *ic = (void *) iface_patt_find(&cf->patt_list, iface, NULL);
+ /* Ignore ifaces without appropriate address */
+ if (rip_is_v2(p) ? !iface->addr4 : !iface->llv6)
+ return;
+
if (ic)
rip_add_iface(p, iface, ic);