diff options
author | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2017-12-07 13:06:01 +0100 |
---|---|---|
committer | Ondrej Zajicek (work) <santiago@crfreenet.org> | 2017-12-07 13:06:01 +0100 |
commit | 153f02da3bce1f3f1a99295648679c71327e8319 (patch) | |
tree | b7b7acf8026ba182f3a81f2d6da975b0b1524972 /proto | |
parent | 4ae3ee1200b386219673c2168eae996c6207b077 (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.c | 47 | ||||
-rw-r--r-- | proto/babel/packets.c | 3 | ||||
-rw-r--r-- | proto/bgp/bgp.c | 15 | ||||
-rw-r--r-- | proto/radv/packets.c | 2 | ||||
-rw-r--r-- | proto/radv/radv.c | 41 | ||||
-rw-r--r-- | proto/rip/packets.c | 12 | ||||
-rw-r--r-- | proto/rip/rip.c | 18 |
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); |