1/*
2 * OSPF Neighbor functions.
3 * Copyright (C) 1999, 2000 Toshiaki Takada
4 *
5 * This file is part of GNU Zebra.
6 *
7 * GNU Zebra is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation; either version 2, or (at your
10 * option) any later version.
11 *
12 * GNU Zebra is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Zebra; see the file COPYING.  If not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22
23#include <zebra.h>
24
25#include "linklist.h"
26#include "prefix.h"
27#include "memory.h"
28#include "command.h"
29#include "thread.h"
30#include "stream.h"
31#include "table.h"
32#include "log.h"
33
34#include "ospfd/ospfd.h"
35#include "ospfd/ospf_interface.h"
36#include "ospfd/ospf_asbr.h"
37#include "ospfd/ospf_lsa.h"
38#include "ospfd/ospf_lsdb.h"
39#include "ospfd/ospf_neighbor.h"
40#include "ospfd/ospf_nsm.h"
41#include "ospfd/ospf_packet.h"
42#include "ospfd/ospf_network.h"
43#include "ospfd/ospf_flood.h"
44#include "ospfd/ospf_dump.h"
45
46struct ospf_neighbor *
47ospf_nbr_new (struct ospf_interface *oi)
48{
49  struct ospf_neighbor *nbr;
50
51  /* Allcate new neighbor. */
52  nbr = XMALLOC (MTYPE_OSPF_NEIGHBOR, sizeof (struct ospf_neighbor));
53  memset (nbr, 0, sizeof (struct ospf_neighbor));
54
55  /* Relate neighbor to the interface. */
56  nbr->oi = oi;
57
58  /* Set default values. */
59  nbr->state = NSM_Down;
60
61  /* Set inheritance values. */
62  nbr->v_inactivity = OSPF_IF_PARAM (oi, v_wait);
63  nbr->v_db_desc = OSPF_IF_PARAM (oi, retransmit_interval);
64  nbr->v_ls_req = OSPF_IF_PARAM (oi, retransmit_interval);
65  nbr->v_ls_upd = OSPF_IF_PARAM (oi, retransmit_interval);
66  nbr->priority = -1;
67
68  /* DD flags. */
69  nbr->dd_flags = OSPF_DD_FLAG_MS|OSPF_DD_FLAG_M|OSPF_DD_FLAG_I;
70
71  /* Last received and sent DD. */
72  nbr->last_send = NULL;
73
74  nbr->nbr_nbma = NULL;
75
76  ospf_lsdb_init (&nbr->db_sum);
77  ospf_lsdb_init (&nbr->ls_rxmt);
78  ospf_lsdb_init (&nbr->ls_req);
79
80  nbr->crypt_seqnum = 0;
81
82  return nbr;
83}
84
85void
86ospf_nbr_free (struct ospf_neighbor *nbr)
87{
88  /* Free DB summary list. */
89  if (ospf_db_summary_count (nbr))
90    ospf_db_summary_clear (nbr);
91    /* ospf_db_summary_delete_all (nbr); */
92
93  /* Free ls request list. */
94  if (ospf_ls_request_count (nbr))
95    ospf_ls_request_delete_all (nbr);
96
97  /* Free retransmit list. */
98  if (ospf_ls_retransmit_count (nbr))
99    ospf_ls_retransmit_clear (nbr);
100
101  /* Cleanup LSDBs. */
102  ospf_lsdb_cleanup (&nbr->db_sum);
103  ospf_lsdb_cleanup (&nbr->ls_req);
104  ospf_lsdb_cleanup (&nbr->ls_rxmt);
105
106  /* Clear last send packet. */
107  if (nbr->last_send)
108    ospf_packet_free (nbr->last_send);
109
110  if (nbr->nbr_nbma)
111    {
112      nbr->nbr_nbma->nbr = NULL;
113      nbr->nbr_nbma = NULL;
114    }
115
116  /* Cancel all timers. */
117  OSPF_NSM_TIMER_OFF (nbr->t_inactivity);
118  OSPF_NSM_TIMER_OFF (nbr->t_db_desc);
119  OSPF_NSM_TIMER_OFF (nbr->t_ls_req);
120  OSPF_NSM_TIMER_OFF (nbr->t_ls_upd);
121
122  XFREE (MTYPE_OSPF_NEIGHBOR, nbr);
123}
124
125/* Delete specified OSPF neighbor from interface. */
126void
127ospf_nbr_delete (struct ospf_neighbor *nbr)
128{
129  struct ospf_interface *oi;
130  struct route_node *rn;
131  struct prefix p;
132
133  oi = nbr->oi;
134
135  /* Unlink ospf neighbor from the interface. */
136  p.family = AF_INET;
137  p.prefixlen = IPV4_MAX_BITLEN;
138  p.u.prefix4 = nbr->src;
139
140  rn = route_node_lookup (oi->nbrs, &p);
141  if (rn)
142    {
143      if (rn->info)
144	{
145	  rn->info = NULL;
146	  route_unlock_node (rn);
147	}
148      else
149	zlog_info ("Can't find neighbor %s in the interface %s",
150		   inet_ntoa (nbr->src), IF_NAME (oi));
151
152      route_unlock_node (rn);
153    }
154
155  /* Free ospf_neighbor structure. */
156  ospf_nbr_free (nbr);
157}
158
159/* Check myself is in the neighbor list. */
160int
161ospf_nbr_bidirectional (struct in_addr *router_id,
162			struct in_addr *neighbors, int size)
163{
164  int i;
165  int max;
166
167  max = size / sizeof (struct in_addr);
168
169  for (i = 0; i < max; i ++)
170    if (IPV4_ADDR_SAME (router_id, &neighbors[i]))
171      return 1;
172
173  return 0;
174}
175
176/* Add self to nbr list. */
177void
178ospf_nbr_add_self (struct ospf_interface *oi)
179{
180  struct ospf_neighbor *nbr;
181  struct prefix p;
182  struct route_node *rn;
183
184  p.family = AF_INET;
185  p.prefixlen = 32;
186  p.u.prefix4 = oi->address->u.prefix4;
187
188  rn = route_node_get (oi->nbrs, &p);
189  if (rn->info)
190    {
191      /* There is already pseudo neighbor. */
192      nbr = rn->info;
193      route_unlock_node (rn);
194    }
195  else
196    rn->info = oi->nbr_self;
197}
198
199/* Get neighbor count by status.
200   Specify status = 0, get all neighbor other than myself. */
201int
202ospf_nbr_count (struct route_table *nbrs, int state)
203{
204  struct route_node *rn;
205  struct ospf_neighbor *nbr;
206  int count = 0;
207
208  /* Sanity check. */
209  if (nbrs == NULL)
210    return 0;
211
212  for (rn = route_top (nbrs); rn; rn = route_next (rn))
213    if ((nbr = rn->info) != NULL)
214      /* Ignore myself. */
215      if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf_top->router_id))
216	if (state == 0 || nbr->state == state)
217	  count++;
218
219  return count;
220}
221
222#ifdef HAVE_OPAQUE_LSA
223int
224ospf_opaque_capable_nbr_count (struct route_table *nbrs, int state)
225{
226  struct route_node *rn;
227  struct ospf_neighbor *nbr;
228  int count = 0;
229
230  /* Sanity check. */
231  if (nbrs == NULL)
232    return 0;
233
234  for (rn = route_top (nbrs); rn; rn = route_next (rn))
235    if ((nbr = rn->info) != NULL)
236      /* Ignore myself. */
237      if (!IPV4_ADDR_SAME (&nbr->router_id, &ospf_top->router_id))
238	if ((state == 0 || nbr->state == state)
239	&&  CHECK_FLAG (nbr->options, OSPF_OPTION_O))
240	  count++;
241
242  return count;
243}
244#endif /* HAVE_OPAQUE_LSA */
245
246struct ospf_neighbor *
247ospf_nbr_lookup_by_addr (struct route_table *nbrs,
248			 struct in_addr *addr)
249{
250  struct prefix p;
251  struct route_node *rn;
252  struct ospf_neighbor *nbr;
253
254  p.family = AF_INET;
255  p.prefixlen = IPV4_MAX_BITLEN;
256  p.u.prefix4 = *addr;
257
258  rn = route_node_lookup (nbrs, &p);
259  if (! rn)
260    return NULL;
261
262  if (rn->info == NULL)
263    {
264      route_unlock_node (rn);
265      return NULL;
266    }
267
268  nbr = (struct ospf_neighbor *) rn->info;
269  route_unlock_node (rn);
270
271  return nbr;
272}
273
274struct ospf_neighbor *
275ospf_nbr_lookup_by_routerid (struct route_table *nbrs,
276			     struct in_addr *id)
277{
278  struct route_node *rn;
279  struct ospf_neighbor *nbr;
280
281  for (rn = route_top (nbrs); rn; rn = route_next (rn))
282    if ((nbr = rn->info) != NULL)
283      if (IPV4_ADDR_SAME (&nbr->router_id, id))
284	{
285	  route_unlock_node(rn);
286	  return nbr;
287	}
288
289  return NULL;
290}
291
292void
293ospf_renegotiate_optional_capabilities (struct ospf *top)
294{
295  listnode node;
296  struct ospf_interface *oi;
297  struct route_table *nbrs;
298  struct route_node *rn;
299  struct ospf_neighbor *nbr;
300
301  /* At first, flush self-originated LSAs from routing domain. */
302  ospf_flush_self_originated_lsas_now (top);
303
304  /* Revert all neighbor status to ExStart. */
305  for (node = listhead (top->oiflist); node; nextnode (node))
306    {
307      if ((oi = getdata (node)) == NULL || (nbrs = oi->nbrs) == NULL)
308        continue;
309
310      for (rn = route_top (nbrs); rn; rn = route_next (rn))
311        {
312          if ((nbr = rn->info) == NULL || nbr == oi->nbr_self)
313            continue;
314
315          if (nbr->state < NSM_ExStart)
316            continue;
317
318          if (IS_DEBUG_OSPF_EVENT)
319            zlog_info ("Renegotiate optional capabilities with neighbor(%s)", inet_ntoa (nbr->router_id));
320
321          OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_SeqNumberMismatch);
322        }
323    }
324
325  return;
326}
327