diff options
Diffstat (limited to 'proto/ospf/iface.c')
-rw-r--r-- | proto/ospf/iface.c | 162 |
1 files changed, 89 insertions, 73 deletions
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index ea38461..8db086e 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -59,7 +59,7 @@ rxbufsize(struct ospf_iface *ifa) } static sock * -ospf_open_ip_socket(struct ospf_iface *ifa) +ospf_open_socket(struct ospf_iface *ifa, int mc) { sock *ipsk; struct proto *p = &ifa->oa->po->proto; @@ -67,7 +67,14 @@ ospf_open_ip_socket(struct ospf_iface *ifa) ipsk = sk_new(p->pool); ipsk->type = SK_IP; ipsk->dport = OSPF_PROTO; - ipsk->saddr = ifa->iface->addr->ip; + +#ifdef OSPFv2 + // ipsk->saddr = ifa->iface->addr->ip; + ipsk->saddr = IPA_NONE; +#else /* OSPFv3 */ + ipsk->saddr = ifa->lladdr; +#endif + ipsk->tos = IP_PREC_INTERNET_CONTROL; ipsk->ttl = 1; if (ifa->type == OSPF_IT_VLINK) @@ -80,12 +87,28 @@ ospf_open_ip_socket(struct ospf_iface *ifa) ipsk->tbsize = ifa->iface->mtu; ipsk->data = (void *) ifa; if (sk_open(ipsk) != 0) + goto err; + +#ifdef OSPFv3 + /* 12 is an offset of the checksum in an OSPF packet */ + if (sk_set_ipv6_checksum(ipsk, 12) < 0) + goto err; +#endif + + if (mc) { - DBG("%s: SK_OPEN: ip open failed.\n", p->name); - return (NULL); + if (sk_setup_multicast(ipsk) < 0) + goto err; + + if (sk_join_group(ipsk, AllSPFRouters) < 0) + goto err; } - DBG("%s: SK_OPEN: ip opened.\n", p->name); - return (ipsk); + + return ipsk; + + err: + rfree(ipsk); + return NULL; } @@ -116,7 +139,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state) ifa->vid, ospf_is[oldstate], ospf_is[state]); if (state == OSPF_IS_PTP) { - ifa->ip_sk = ospf_open_ip_socket(ifa); + ifa->sk = ospf_open_socket(ifa, 0); } } else @@ -126,47 +149,28 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state) ifa->iface->name, ospf_is[oldstate], ospf_is[state]); if (ifa->iface->flags & IF_MULTICAST) { - if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR)) + if ((ifa->type != OSPF_IT_NBMA) && (ifa->ioprob == OSPF_I_OK) && + ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))) { - if ((ifa->dr_sk == NULL) && (ifa->type != OSPF_IT_NBMA)) - { - DBG("%s: Adding new multicast socket for (B)DR\n", p->name); - ifa->dr_sk = sk_new(p->pool); - ifa->dr_sk->type = SK_IP_MC; - ifa->dr_sk->sport = 0; - ifa->dr_sk->dport = OSPF_PROTO; - ifa->dr_sk->saddr = AllDRouters; - ifa->dr_sk->daddr = AllDRouters; - ifa->dr_sk->tos = IP_PREC_INTERNET_CONTROL; - ifa->dr_sk->ttl = 1; - ifa->dr_sk->rx_hook = ospf_rx_hook; - ifa->dr_sk->tx_hook = ospf_tx_hook; - ifa->dr_sk->err_hook = ospf_err_hook; - ifa->dr_sk->iface = ifa->iface; - ifa->dr_sk->rbsize = rxbufsize(ifa); - ifa->dr_sk->tbsize = ifa->iface->mtu; - ifa->dr_sk->data = (void *) ifa; - if (sk_open(ifa->dr_sk) != 0) - { - DBG("%s: SK_OPEN: new? mc open failed.\n", p->name); - } - } + /* FIXME some error handing ? */ + sk_join_group(ifa->sk, AllDRouters); + ifa->dr_up = 1; } - else + else if (ifa->dr_up) { - rfree(ifa->dr_sk); - ifa->dr_sk = NULL; + sk_leave_group(ifa->sk, AllDRouters); + ifa->dr_up = 0; } - if ((oldstate == OSPF_IS_DR) && (ifa->nlsa != NULL)) + if ((oldstate == OSPF_IS_DR) && (ifa->net_lsa != NULL)) { - ifa->nlsa->lsa.age = LSA_MAXAGE; + ifa->net_lsa->lsa.age = LSA_MAXAGE; if (state >= OSPF_IS_WAITING) { - ospf_lsupd_flush_nlsa(ifa->nlsa, ifa->oa); + ospf_lsupd_flush_nlsa(po, ifa->net_lsa); } if (can_flush_lsa(po)) - flush_lsa(ifa->nlsa, po); - ifa->nlsa = NULL; + flush_lsa(ifa->net_lsa, po); + ifa->net_lsa = NULL; } } } @@ -196,13 +200,12 @@ ospf_iface_down(struct ospf_iface *ifa) OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip); ospf_neigh_remove(n); } - rfree(ifa->hello_sk); - rfree(ifa->dr_sk); - rfree(ifa->ip_sk); + + rfree(ifa->sk); + ifa->sk = NULL; if (ifa->type == OSPF_IT_VLINK) { - ifa->ip_sk = NULL; ifa->iface = NULL; return; } @@ -260,6 +263,7 @@ ospf_iface_sm(struct ospf_iface *ifa, int event) hello_timer_hook(ifa->hello_timer); } + schedule_link_lsa(ifa); schedule_rt_lsa(ifa->oa); break; case ISM_BACKS: @@ -280,6 +284,7 @@ ospf_iface_sm(struct ospf_iface *ifa, int event) case ISM_DOWN: ospf_iface_chstate(ifa, OSPF_IS_DOWN); ospf_iface_down(ifa); + schedule_link_lsa(ifa); schedule_rt_lsa(oa); break; case ISM_LOOP: /* Useless? */ @@ -298,6 +303,7 @@ ospf_iface_sm(struct ospf_iface *ifa, int event) } +#if 0 static sock * ospf_open_mc_socket(struct ospf_iface *ifa) { @@ -308,7 +314,14 @@ ospf_open_mc_socket(struct ospf_iface *ifa) mcsk->type = SK_IP_MC; mcsk->sport = 0; mcsk->dport = OSPF_PROTO; + +#ifdef OSPFv2 mcsk->saddr = AllSPFRouters; +#else /* OSPFv3 */ + // mcsk->saddr = AllSPFRouters; + mcsk->saddr = ifa->lladdr; +#endif + mcsk->daddr = AllSPFRouters; mcsk->tos = IP_PREC_INTERNET_CONTROL; mcsk->ttl = 1; @@ -327,6 +340,7 @@ ospf_open_mc_socket(struct ospf_iface *ifa) DBG("%s: SK_OPEN: mc opened.\n", p->name); return (mcsk); } +#endif u8 ospf_iface_clasify(struct iface * ifa) @@ -363,20 +377,8 @@ ospf_iface_add(struct object_lock *lock) ifa->ioprob = OSPF_I_OK; - if (ifa->type != OSPF_IT_NBMA) - { - if ((ifa->hello_sk = ospf_open_mc_socket(ifa)) == NULL) - { - log("%s: Huh? could not open mc socket on interface %s?", p->name, - iface->name); - log("%s: Declaring as stub.", p->name); - ifa->stub = 1; - ifa->ioprob += OSPF_I_MC; - } - ifa->dr_sk = NULL; - } - - if ((ifa->ip_sk = ospf_open_ip_socket(ifa)) == NULL) + ifa->sk = ospf_open_socket(ifa, ifa->type != OSPF_IT_NBMA); + if (ifa->sk == NULL) { log("%s: Huh? could not open ip socket on interface %s?", p->name, iface->name); @@ -412,8 +414,33 @@ ospf_iface_new(struct proto_ospf *po, struct iface *iface, ifa->waitint = ip->waitint; ifa->dead = (ip->dead == 0) ? ip->deadc * ifa->helloint : ip->dead; ifa->stub = ip->stub; + +#ifdef OSPFv2 ifa->autype = ip->autype; ifa->passwords = ip->passwords; +#endif + +#ifdef OSPFv3 + ifa->instance_id = ip->instance_id; + + ifa->lladdr = IPA_NONE; + + /* Find link-local address */ + if (ifa->type != OSPF_IT_VLINK) + { + struct ifa *a; + WALK_LIST(a, iface->addrs) + if (a->scope == SCOPE_LINK) + { + ifa->lladdr = a->ip; + break; + } + + if (! ipa_nonzero(ifa->lladdr)) + log(L_WARN "%s: Missing link local address on interface %s", p->name, iface->name); + } +#endif + ifa->rxbuf = ip->rxbuf; if (ip->type == OSPF_IT_UNDEF) @@ -501,23 +528,12 @@ ospf_iface_change_mtu(struct proto_ospf *po, struct ospf_iface *ifa) struct ospf_packet *op; struct ospf_neighbor *n; OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s.", ifa->iface->name); - if (ifa->hello_sk) - { - ifa->hello_sk->rbsize = rxbufsize(ifa); - ifa->hello_sk->tbsize = ifa->iface->mtu; - sk_reallocate(ifa->hello_sk); - } - if (ifa->dr_sk) - { - ifa->dr_sk->rbsize = rxbufsize(ifa); - ifa->dr_sk->tbsize = ifa->iface->mtu; - sk_reallocate(ifa->dr_sk); - } - if (ifa->ip_sk) + + if (ifa->sk) { - ifa->ip_sk->rbsize = rxbufsize(ifa); - ifa->ip_sk->tbsize = ifa->iface->mtu; - sk_reallocate(ifa->ip_sk); + ifa->sk->rbsize = rxbufsize(ifa); + ifa->sk->tbsize = ifa->iface->mtu; + sk_reallocate(ifa->sk); } WALK_LIST(n, ifa->neigh_list) |