diff options
| -rw-r--r-- | ospfd/ChangeLog | 15 | ||||
| -rw-r--r-- | ospfd/ospf_neighbor.c | 105 | ||||
| -rw-r--r-- | ospfd/ospf_neighbor.h | 12 | ||||
| -rw-r--r-- | ospfd/ospf_packet.c | 144 | 
4 files changed, 181 insertions, 95 deletions
diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog index 39a18879..6b15fe64 100644 --- a/ospfd/ChangeLog +++ b/ospfd/ChangeLog @@ -1,3 +1,18 @@ +2004-05-05 Paul Jakma <paul@dishone.st> + +	* ospf_packet.c:  (ospf_associate_packet_vl) cleanup, move  +	  some of the checks up to ospf_read, return either a  +	  virtual link oi, or NULL.  +	  (ospf_read) Cleanup, make it responsible for checks. Remove +	  the nbr lookup - moved to ospf_neighbor. Adjust all nbr +	  lookups to use new wrappers exported by ospf_neighbor. +	* ospf_neighbor.h: Add ospf_neigbour_get and ospf_nbr_lookup. +	* ospf_neighbor.c: (ospf_neigbour_get) Index ospf_interface  +	  neighbour table by router-id for virtual-link ospf_interfaces,  +	  not by peer_addr (which breaks for asymmetric vlinks) +	  (ospf_nbr_lookup) add a wrapper for nbr lookups to deal with +	  above. +  2004-04-22 Hasso Tepper <hasso@estpak.ee>  	* ospf_zebra.c: Don't ignore reject/bh routes, it's the only way diff --git a/ospfd/ospf_neighbor.c b/ospfd/ospf_neighbor.c index ccef0559..6f2d4a05 100644 --- a/ospfd/ospf_neighbor.c +++ b/ospfd/ospf_neighbor.c @@ -138,6 +138,11 @@ ospf_nbr_delete (struct ospf_neighbor *nbr)    /* Unlink ospf neighbor from the interface. */    p.family = AF_INET;    p.prefixlen = IPV4_MAX_BITLEN; + +  /* vlinks are indexed by router-id */ +  if (oi->type == OSPF_IFTYPE_VIRTUALLINK) +    p.u.prefix4 = nbr->router_id; +  else    p.u.prefix4 = nbr->src;    rn = route_node_lookup (oi->nbrs, &p); @@ -236,6 +241,10 @@ ospf_nbr_count_opaque_capable (struct ospf_interface *oi)  }  #endif /* HAVE_OPAQUE_LSA */ +/* lookup nbr by address - use this only if you know you must + * otherwise use the ospf_nbr_lookup() wrapper, which deals  + * with virtual link neighbours + */  struct ospf_neighbor *  ospf_nbr_lookup_by_addr (struct route_table *nbrs,  			 struct in_addr *addr) @@ -317,3 +326,99 @@ ospf_renegotiate_optional_capabilities (struct ospf *top)    return;  } + + +struct ospf_neighbor * +ospf_nbr_lookup (struct ospf_interface *oi, struct ip *iph, +                 struct ospf_header *ospfh) +{ +  if (oi->type == OSPF_IFTYPE_VIRTUALLINK) +    return (ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id)); +  else +    return (ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src)); +} + +struct ospf_neighbor * +ospf_nbr_add (struct ospf_interface *oi, struct ospf_header *ospfh, +              struct prefix *p) +{ +  struct ospf_neighbor *nbr; +   +  nbr = ospf_nbr_new (oi); +  nbr->state = NSM_Down; +  nbr->src = p->u.prefix4; +  memcpy (&nbr->address, p, sizeof (struct prefix)); + +  nbr->nbr_nbma = NULL; +  if (oi->type == OSPF_IFTYPE_NBMA) +    { +      struct ospf_nbr_nbma *nbr_nbma; +      listnode node; + +      for (node = listhead (oi->nbr_nbma); node; nextnode (node)) +        { +          nbr_nbma = getdata (node); +          assert (nbr_nbma); + +          if (IPV4_ADDR_SAME(&nbr_nbma->addr, &nbr->src)) +            { +              nbr_nbma->nbr = nbr; +              nbr->nbr_nbma = nbr_nbma; + +              if (nbr_nbma->t_poll) +                OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll); + +              nbr->state_change = nbr_nbma->state_change + 1; +            } +        } +    } +       +  /* New nbr, save the crypto sequence number if necessary */ +  if (ntohs (ospfh->auth_type) == OSPF_AUTH_CRYPTOGRAPHIC) +    nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum; +   +  if (IS_DEBUG_OSPF_EVENT) +    zlog_info ("NSM[%s:%s]: start", IF_NAME (nbr->oi), +               inet_ntoa (nbr->router_id)); +   +  return nbr; +} + +struct ospf_neighbor * +ospf_nbr_get (struct ospf_interface *oi, struct ospf_header *ospfh, +              struct ip *iph, struct prefix *p) +{ +  struct route_node *rn; +  struct prefix key; +  struct ospf_neighbor *nbr; +   +  key.family = AF_INET; +  key.prefixlen = IPV4_MAX_BITLEN; + +  if (oi->type == OSPF_IFTYPE_VIRTUALLINK) +    key.u.prefix4 = ospfh->router_id;   /* index vlink nbrs by router-id */ +  else +    key.u.prefix4 = iph->ip_src; + +  rn = route_node_get (oi->nbrs, &key); +  if (rn->info) +    { +      route_unlock_node (rn); +      nbr = rn->info; +       +      if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) +        { +          nbr->src = iph->ip_src; +          memcpy (&nbr->address, p, sizeof (struct prefix)); +        } +    } +  else +    { +      rn->info = nbr = ospf_nbr_add (oi, ospfh, p); +    } +   +  nbr->router_id = ospfh->router_id; + +  return nbr; +} +   diff --git a/ospfd/ospf_neighbor.h b/ospfd/ospf_neighbor.h index f7b18742..f91ef3f9 100644 --- a/ospfd/ospf_neighbor.h +++ b/ospfd/ospf_neighbor.h @@ -23,6 +23,8 @@  #ifndef _ZEBRA_OSPF_NEIGHBOR_H  #define _ZEBRA_OSPF_NEIGHBOR_H +#include <ospfd/ospf_packet.h> +  /* Neighbor Data Structure */  struct ospf_neighbor  { @@ -93,10 +95,16 @@ void ospf_nbr_free (struct ospf_neighbor *);  void ospf_nbr_delete (struct ospf_neighbor *);  int ospf_nbr_bidirectional (struct in_addr *, struct in_addr *, int);  void ospf_nbr_add_self (struct ospf_interface *); -int ospf_nbr_count (struct route_table *, int); +int ospf_nbr_count (struct ospf_interface *, int);  #ifdef HAVE_OPAQUE_LSA -int ospf_opaque_capable_nbr_count (struct route_table *nbrs, int status); +int ospf_nbr_count_opaque_capable (struct ospf_interface *);  #endif /* HAVE_OPAQUE_LSA */ +struct ospf_neighbor *ospf_nbr_get (struct ospf_interface *, +                                    struct ospf_header *, +                                    struct ip *, +                                    struct prefix *); +struct ospf_neighbor *ospf_nbr_lookup (struct ospf_interface *, struct ip *, +                                       struct ospf_header *);  struct ospf_neighbor *ospf_nbr_lookup_by_addr (struct route_table *,  					       struct in_addr *);  struct ospf_neighbor *ospf_nbr_lookup_by_routerid (struct route_table *, diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 1f8ecd46..e6b2ea7c 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -607,9 +607,8 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,  {    struct ospf_hello *hello;    struct ospf_neighbor *nbr; -  struct route_node *rn; -  struct prefix p, key;    int old_state; +  struct prefix p;    /* increment statistics. */    oi->hello_in++; @@ -736,70 +735,12 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,  		   OPTIONS (oi), hello->options);  	return;        } - - -  /* Get neighbor information from table. */ -  key.family = AF_INET; -  key.prefixlen = IPV4_MAX_BITLEN; -  key.u.prefix4 = iph->ip_src; - -  rn = route_node_get (oi->nbrs, &key); -  if (rn->info) -    { -      route_unlock_node (rn); -      nbr = rn->info; - -      if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) -	{ -	  nbr->src = iph->ip_src; -	  nbr->address = p; -	} -    } -  else -    { -      /* Create new OSPF Neighbor structure. */ -      nbr = ospf_nbr_new (oi); -      nbr->state = NSM_Down; -      nbr->src = iph->ip_src; -      nbr->address = p; - -      rn->info = nbr; - -      nbr->nbr_nbma = NULL; - -      if (oi->type == OSPF_IFTYPE_NBMA) -	{ -	  struct ospf_nbr_nbma *nbr_nbma; -	  listnode node; - -	  for (node = listhead (oi->nbr_nbma); node; nextnode (node)) -	    { -	      nbr_nbma = getdata (node); -	      assert (nbr_nbma); -       -	      if (IPV4_ADDR_SAME(&nbr_nbma->addr, &iph->ip_src)) -		{ -		  nbr_nbma->nbr = nbr; -		  nbr->nbr_nbma = nbr_nbma; - -		  if (nbr_nbma->t_poll) -		    OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll); -		   -		  nbr->state_change = nbr_nbma->state_change + 1; -		} -	    } -	} -       -      /* New nbr, save the crypto sequence number if necessary */ -      if (ntohs (ospfh->auth_type) == OSPF_AUTH_CRYPTOGRAPHIC) -	nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum; - -      if (IS_DEBUG_OSPF_EVENT) -	zlog_info ("NSM[%s:%s]: start", IF_NAME (nbr->oi), -		   inet_ntoa (nbr->router_id)); -    } -  nbr->router_id = ospfh->router_id; +  /* get neighbour struct */ +  nbr = ospf_nbr_get (oi, ospfh, iph, &p); + +  /* neighbour must be valid, ospf_nbr_get creates if none existed */ +  assert (nbr);    old_state = nbr->state; @@ -1029,7 +970,7 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh,    dd = (struct ospf_db_desc *) STREAM_PNT (s); -  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src); +  nbr = ospf_nbr_lookup (oi, iph, ospfh);    if (nbr == NULL)      {        zlog_warn ("Packet[DD]: Unknown Neighbor %s", @@ -1286,7 +1227,7 @@ ospf_ls_req (struct ip *iph, struct ospf_header *ospfh,    /* Increment statistics. */    oi->ls_req_in++; -  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src); +  nbr = ospf_nbr_lookup (oi, iph, ospfh);    if (nbr == NULL)      {        zlog_warn ("Link State Request: Unknown Neighbor %s.", @@ -1520,7 +1461,7 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh,    oi->ls_upd_in++;    /* Check neighbor. */ -  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src); +  nbr = ospf_nbr_lookup (oi, iph, ospfh);    if (nbr == NULL)      {        zlog_warn ("Link State Update: Unknown Neighbor %s on int: %s", @@ -1881,7 +1822,7 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh,    /* increment statistics. */    oi->ls_ack_in++; -  nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src); +  nbr = ospf_nbr_lookup (oi, iph, ospfh);    if (nbr == NULL)      {        zlog_warn ("Link State Acknowledgment: Unknown Neighbor %s.", @@ -2043,8 +1984,7 @@ ospf_recv_packet (int fd, struct interface **ifp)  }  struct ospf_interface * -ospf_associate_packet_vl (struct ospf *ospf, -			  struct interface *ifp, struct ospf_interface *oi, +ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp,   			  struct ip *iph, struct ospf_header *ospfh)  {    struct ospf_interface *rcv_oi; @@ -2054,14 +1994,16 @@ ospf_associate_packet_vl (struct ospf *ospf,    if (IN_MULTICAST (ntohl (iph->ip_dst.s_addr)) ||        !OSPF_IS_AREA_BACKBONE (ospfh)) -    return oi; +    return NULL; -  if ((rcv_oi = oi) == NULL) -    { -     if ((rcv_oi = ospf_if_lookup_by_local_addr (ospf, NULL,  -                                                 iph->ip_dst)) == NULL) -       return NULL; -    } +  /* look for local OSPF interface matching the destination +   * to determine Area ID. We presume therefore the destination address +   * is unique, or at least (for "unnumbered" links), not used in other  +   * areas +   */ +  if ((rcv_oi = ospf_if_lookup_by_local_addr (ospf, NULL,  +                                              iph->ip_dst)) == NULL) +    return NULL;    for (node = listhead (ospf->vlinks); node; nextnode (node))      { @@ -2092,7 +2034,7 @@ ospf_associate_packet_vl (struct ospf *ospf,    if (IS_DEBUG_OSPF_EVENT)      zlog_info ("couldn't find any VL to associate the packet with"); -  return oi; +  return NULL;  }  int @@ -2287,6 +2229,12 @@ ospf_read (struct thread *thread)    if (ibuf == NULL)      return -1; +  if (ifp == NULL) +    { +      stream_free (ibuf); +      return 0; +    } +        iph = (struct ip *) STREAM_DATA (ibuf);    /* prepare for next packet. */ @@ -2316,23 +2264,33 @@ ospf_read (struct thread *thread)    /* associate packet with ospf interface */    oi = ospf_if_lookup_recv_if (ospf, iph->ip_src); -  if (ifp && oi && oi->ifp != ifp) -    { -      zlog_warn ("Packet from [%s] received on wrong link %s", -                 inet_ntoa (iph->ip_src), ifp->name);  -      stream_free (ibuf); -      return 0; -    } -   -  if ((oi = ospf_associate_packet_vl (ospf, ifp, oi, iph, ospfh)) == NULL) + +  /* if no local ospf_interface,  +   * or header area is backbone but ospf_interface is not +   * check for VLINK interface +   */ +  if ( (oi == NULL) || +      (OSPF_IS_AREA_ID_BACKBONE(ospfh->area_id) +      && !OSPF_IS_AREA_ID_BACKBONE(oi->area->area_id)) +     )      { -      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) +      if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL)          { -          zlog_info ("ospf_read[%s/%s]: Could not associate packet with VL, " -                     "dropping.", -                     ospf_packet_type_str[ospfh->type], -                     inet_ntoa (iph->ip_src)); +          zlog_warn ("Packet from [%s] received on link %s" +                     " but no ospf_interface", +                     inet_ntoa (iph->ip_src), ifp->name); +          stream_free (ibuf); +          return 0;          } +    } +     +  /* else it must be a local ospf interface, check it was received on  +   * correct link  +   */ +  else if (oi->ifp != ifp) +    { +      zlog_warn ("Packet from [%s] received on wrong link %s", +                 inet_ntoa (iph->ip_src), ifp->name);         stream_free (ibuf);        return 0;      }  | 
