Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / lsupd.c @ 061ab802

History | View | Annotate | Download (17.4 KB)

1
/*
2
 *        BIRD -- OSPF
3
 *
4
 *        (c) 2000--2004 Ondrej Filip <feela@network.cz>
5
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8

    
9
#include "ospf.h"
10

    
11

    
12
struct ospf_lsupd_packet
13
{
14
  struct ospf_packet ospf_packet;
15
  u32 lsano;                        /* Number of LSA's */
16
};
17

    
18

    
19
void ospf_dump_lsahdr(struct proto *p, struct ospf_lsa_header *lsa_n)
20
{
21
  struct ospf_lsa_header lsa;
22
  ntohlsah(lsa_n, &lsa);
23

    
24
  log(L_TRACE "%s:     LSA      Id: %R, Rt: %R, Type: %u, Age: %u, Seqno: 0x%08x, Sum: %u",
25
      p->name, lsa.id, lsa.rt, lsa.type, lsa.age, lsa.sn, lsa.checksum);
26
}
27

    
28
void ospf_dump_common(struct proto *p, struct ospf_packet *op)
29
{
30
  log(L_TRACE "%s:     length   %d", p->name, ntohs(op->length));
31
  log(L_TRACE "%s:     router   %R", p->name, ntohl(op->routerid));
32
}
33

    
34
static void ospf_dump_lsupd(struct proto *p, struct ospf_lsupd_packet *pkt)
35
{
36
  struct ospf_packet *op = &pkt->ospf_packet;
37

    
38
  ASSERT(op->type == LSUPD_P);
39
  ospf_dump_common(p, op);
40

    
41
  u8 *pbuf= (u8 *) pkt;
42
  int offset = sizeof(struct ospf_lsupd_packet);
43
  int bound = ntohs(op->length) - sizeof(struct ospf_lsa_header);
44
  int i, j;
45

    
46
  j = ntohl(pkt->lsano);
47
  for (i = 0; i < j; i++)
48
    {
49
      if (offset > bound)
50
        {
51
          log(L_TRACE "%s:     LSA      invalid", p->name);
52
          return;
53
        }
54

    
55
      struct ospf_lsa_header *lsa = (void *) (pbuf + offset);
56
      ospf_dump_lsahdr(p, lsa);
57
      offset += ntohs(lsa->length);
58
    }
59
}
60

    
61

    
62
#ifdef OSPFv2
63

    
64
int
65
ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa)
66
{
67
  if (lsa->type == LSA_T_EXT)
68
    {
69
      if (ifa->type == OSPF_IT_VLINK)
70
        return 0;
71
      if (ifa->oa->stub)
72
        return 0;
73
      return 1
74
    }
75
  else
76
    return ifa->oa->areaid == domain;
77
}
78

    
79
#else /* OSPFv3 */
80

    
81
static int
82
unknown_lsa_type(struct ospf_lsa_header *lsa)
83
{
84
  switch (lsa->type)
85
    {
86
    case LSA_T_RT:
87
    case LSA_T_NET:
88
    case LSA_T_SUM_NET:
89
    case LSA_T_SUM_RT:
90
    case LSA_T_EXT:
91
    case LSA_T_LINK:
92
    case LSA_T_PREFIX:
93
      return 0;
94

    
95
    default:
96
      return 1;
97
    }
98
}
99

    
100
int
101
ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa)
102
{    
103
  u32 scope = LSA_SCOPE(lsa);
104

    
105
  /* 4.5.2 (Case 2) */
106
  if (unknown_lsa_type(lsa) && !(lsa->type & LSA_UBIT))
107
    scope = LSA_SCOPE_LINK;
108

    
109
  switch (scope)
110
    {
111
    case LSA_SCOPE_LINK:
112
      return ifa->iface->index == domain;
113

    
114
    case LSA_SCOPE_AREA:
115
      return ifa->oa->areaid == domain;
116

    
117
    case LSA_SCOPE_AS:
118
      if (ifa->type == OSPF_IT_VLINK)
119
        return 0;
120
      if (ifa->oa->stub)
121
        return 0;
122
      return 1;
123

    
124
    default:
125
      log(L_ERR "LSA with invalid scope");
126
      return 0;
127
    }
128
}
129

    
130
#endif
131

    
132
/**
133
 * ospf_lsupd_flood - send received or generated lsa to the neighbors
134
 * @po: OSPF protocol
135
 * @n: neighbor than sent this lsa (or NULL if generated)
136
 * @hn: LSA header followed by lsa body in network endianity (may be NULL) 
137
 * @hh: LSA header in host endianity (must be filled)
138
 * @domain: domain of LSA (must be filled)
139
 * @rtl: add this LSA into retransmission list
140
 *
141
 *
142
 * return value - was the LSA flooded back?
143
 */
144

    
145
int
146
ospf_lsupd_flood(struct proto_ospf *po,
147
                 struct ospf_neighbor *n, struct ospf_lsa_header *hn,
148
                 struct ospf_lsa_header *hh, u32 domain, int rtl)
149
{
150
  struct ospf_iface *ifa;
151
  struct ospf_neighbor *nn;
152
  struct top_hash_entry *en;
153
  struct proto *p = &po->proto;
154
  int ret, retval = 0;
155

    
156
  /* pg 148 */
157
  WALK_LIST(ifa, po->iface_list)
158
  {
159
    if (ifa->stub)
160
      continue;
161

    
162
    if (! ospf_lsa_flooding_allowed(hh, domain, ifa))
163
      continue;
164

    
165
    DBG("Wanted to flood LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
166
        hh->type, hh->id, hh->rt, hh->sn, hh->age);
167

    
168
    ret = 0;
169
    WALK_LIST(nn, ifa->neigh_list)
170
    {
171
      /* 13.3 (1a) */
172
      if (nn->state < NEIGHBOR_EXCHANGE)
173
        continue;
174

    
175
      /* 13.3 (1b) */
176
      if (nn->state < NEIGHBOR_FULL)
177
      {
178
        if ((en = ospf_hash_find_header(nn->lsrqh, domain, hh)) != NULL)
179
        {
180
          DBG("That LSA found in lsreq list for neigh %R\n", nn->rid);
181

    
182
          switch (lsa_comp(hh, &en->lsa))
183
          {
184
          case CMP_OLDER:
185
            continue;
186
            break;
187
          case CMP_SAME:
188
            s_rem_node(SNODE en);
189
            if (en->lsa_body != NULL)
190
              mb_free(en->lsa_body);
191
            en->lsa_body = NULL;
192
            DBG("Removing from lsreq list for neigh %R\n", nn->rid);
193
            ospf_hash_delete(nn->lsrqh, en);
194
            if (EMPTY_SLIST(nn->lsrql))
195
              ospf_neigh_sm(nn, INM_LOADDONE);
196
            continue;
197
            break;
198
          case CMP_NEWER:
199
            s_rem_node(SNODE en);
200
            if (en->lsa_body != NULL)
201
              mb_free(en->lsa_body);
202
            en->lsa_body = NULL;
203
            DBG("Removing from lsreq list for neigh %R\n", nn->rid);
204
            ospf_hash_delete(nn->lsrqh, en);
205
            if (EMPTY_SLIST(nn->lsrql))
206
              ospf_neigh_sm(nn, INM_LOADDONE);
207
            break;
208
          default:
209
            bug("Bug in lsa_comp?");
210
          }
211
        }
212
      }
213

    
214
      /* 13.3 (1c) */
215
      if (nn == n)
216
        continue;
217

    
218
      /* 13.3 (1d) */
219
      if (rtl)
220
      {
221
        /* In OSPFv3, there should be check whether receiving router understand
222
           that type of LSA (for LSA types with U-bit == 0). But as we does not support
223
           any optional LSA types, this is not needed yet */
224

    
225
        if ((en = ospf_hash_find_header(nn->lsrth, domain, hh)) == NULL)
226
        {
227
          en = ospf_hash_get_header(nn->lsrth, domain, hh);
228
        }
229
        else
230
        {
231
          s_rem_node(SNODE en);
232
        }
233
        s_add_tail(&nn->lsrtl, SNODE en);
234
        memcpy(&en->lsa, hh, sizeof(struct ospf_lsa_header));
235
        DBG("Adding that LSA for flood to %I\n", nn->ip);
236
      }
237
      else
238
      {
239
        if ((en = ospf_hash_find_header(nn->lsrth, domain, hh)) != NULL)
240
        {
241
          s_rem_node(SNODE en);
242
          if (en->lsa_body != NULL)
243
            mb_free(en->lsa_body);
244
          en->lsa_body = NULL;
245
          ospf_hash_delete(nn->lsrth, en);
246
        }
247
      }
248

    
249
      ret = 1;
250
    }
251

    
252
    if (ret == 0)
253
      continue;                        /* pg 150 (2) */
254

    
255
    if (n && (n->ifa == ifa))
256
    {
257
      if ((n->rid == ifa->drid) || n->rid == ifa->bdrid)
258
        continue;                /* pg 150 (3) */
259
      if (ifa->state == OSPF_IS_BACKUP)
260
        continue;                /* pg 150 (4) */
261
      retval = 1;
262
    }
263

    
264
    {
265
      sock *sk;
266
      u16 len, age;
267
      struct ospf_lsupd_packet *pk;
268
      struct ospf_packet *op;
269
      struct ospf_lsa_header *lh;
270

    
271
      if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_VLINK))
272
        sk = ifa->ip_sk;
273
      else
274
        sk = ifa->hello_sk;
275

    
276
      pk = (struct ospf_lsupd_packet *) sk->tbuf;
277
      op = (struct ospf_packet *) sk->tbuf;
278

    
279
      ospf_pkt_fill_hdr(ifa, pk, LSUPD_P);
280
      pk->lsano = htonl(1);
281

    
282
      lh = (struct ospf_lsa_header *) (pk + 1);
283

    
284
      /* Copy LSA into the packet */
285
      if (hn)
286
      {
287
        memcpy(lh, hn, ntohs(hn->length));
288
      }
289
      else
290
      {
291
        u8 *help;
292
        struct top_hash_entry *en;
293

    
294
        htonlsah(hh, lh);
295
        help = (u8 *) (lh + 1);
296
        en = ospf_hash_find_header(po->gr, domain, hh);
297
        htonlsab(en->lsa_body, help, hh->type, hh->length
298
                 - sizeof(struct ospf_lsa_header));
299
      }
300

    
301
      len = sizeof(struct ospf_lsupd_packet) + ntohs(lh->length);
302

    
303
      age = ntohs(lh->age);
304
      age += ifa->inftransdelay;
305
      if (age > LSA_MAXAGE)
306
        age = LSA_MAXAGE;
307
      lh->age = htons(age);
308

    
309
      op->length = htons(len);
310

    
311
      OSPF_PACKET(ospf_dump_lsupd,  (struct ospf_lsupd_packet *) sk->tbuf,
312
                  "LSUPD packet flooded via %s", ifa->iface->name);
313

    
314
      switch (ifa->type)
315
      {
316
      case OSPF_IT_NBMA:
317
        if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
318
          ospf_send_to_agt(sk, ifa, NEIGHBOR_EXCHANGE);
319
        else
320
          ospf_send_to_bdr(sk, ifa);
321
        break;
322

    
323
      case OSPF_IT_VLINK:
324
        ospf_send_to(sk, ifa->vip, ifa);
325
        break;
326

    
327
      default:
328
        if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR) ||
329
            (ifa->type == OSPF_IT_PTP))
330
          ospf_send_to(sk, AllSPFRouters, ifa);
331
        else
332
          ospf_send_to(sk, AllDRouters, ifa);
333
      }
334
    }
335
  }
336
  return retval;
337
}
338

    
339
void                                /* I send all I received in LSREQ */
340
ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
341
{
342
  struct l_lsr_head *llsh;
343
  u16 len;
344
  u32 lsano;
345
  struct top_hash_entry *en;
346
  struct ospf_lsupd_packet *pk;
347
  struct ospf_packet *op;
348
  struct ospf_area *oa = n->ifa->oa;
349
  struct proto_ospf *po = oa->po;
350
  struct proto *p = &po->proto;
351
  void *pktpos;
352

    
353
  if (EMPTY_LIST(*l))
354
    return;
355

    
356
  pk = (struct ospf_lsupd_packet *) n->ifa->ip_sk->tbuf;
357
  op = (struct ospf_packet *) n->ifa->ip_sk->tbuf;
358

    
359
  DBG("LSupd: 1st packet\n");
360

    
361
  ospf_pkt_fill_hdr(n->ifa, pk, LSUPD_P);
362
  len = sizeof(struct ospf_lsupd_packet);
363
  lsano = 0;
364
  pktpos = (pk + 1);
365

    
366
  WALK_LIST(llsh, *l)
367
  {
368
    u32 domain = ospf_lsa_domain(llsh->lsh.type, n->ifa);
369
    if ((en = ospf_hash_find(po->gr, domain, llsh->lsh.id,
370
                               llsh->lsh.rt, llsh->lsh.type)) == NULL)
371
      continue;                        /* Probably flushed LSA */
372
    /* FIXME This is a bug! I cannot flush LSA that is in lsrt */
373

    
374
    DBG("Sending LSA: Type=%u, ID=%R, RT=%R, SN: 0x%x, Age: %u\n",
375
        llsh->lsh.type, llsh->lsh.id, llsh->lsh.rt, en->lsa.sn, en->lsa.age);
376
    if (((u32) (len + en->lsa.length)) > ospf_pkt_maxsize(n->ifa))
377
    {
378
      pk->lsano = htonl(lsano);
379
      op->length = htons(len);
380

    
381
      OSPF_PACKET(ospf_dump_lsupd,  (struct ospf_lsupd_packet *) n->ifa->ip_sk->tbuf,
382
                  "LSUPD packet sent to %I via %s", n->ip, n->ifa->iface->name);
383
      ospf_send_to(n->ifa->ip_sk, n->ip, n->ifa);
384

    
385
      DBG("LSupd: next packet\n");
386
      ospf_pkt_fill_hdr(n->ifa, pk, LSUPD_P);
387
      len = sizeof(struct ospf_lsupd_packet);
388
      lsano = 0;
389
      pktpos = (pk + 1);
390
    }
391
    htonlsah(&(en->lsa), pktpos);
392
    pktpos = pktpos + sizeof(struct ospf_lsa_header);
393
    htonlsab(en->lsa_body, pktpos, en->lsa.type, en->lsa.length
394
             - sizeof(struct ospf_lsa_header));
395
    pktpos = pktpos + en->lsa.length - sizeof(struct ospf_lsa_header);
396
    len += en->lsa.length;
397
    lsano++;
398
  }
399
  if (lsano > 0)
400
  {
401
    pk->lsano = htonl(lsano);
402
    op->length = htons(len);
403

    
404
    OSPF_PACKET(ospf_dump_lsupd,  (struct ospf_lsupd_packet *) n->ifa->ip_sk->tbuf,
405
                "LSUPD packet sent to %I via %s", n->ip, n->ifa->iface->name);
406
    ospf_send_to(n->ifa->ip_sk, n->ip, n->ifa);
407
  }
408
}
409

    
410
void
411
ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
412
                   struct ospf_neighbor *n)
413
{
414
  struct ospf_lsupd_packet *ps = (void *) ps_i;
415
  struct ospf_neighbor *ntmp;
416
  struct ospf_lsa_header *lsa;
417
  struct proto_ospf *po = ifa->oa->po;
418
  struct proto *p = &po->proto;
419
  unsigned int i, sendreq = 1, size = ntohs(ps->ospf_packet.length);
420

    
421
  OSPF_PACKET(ospf_dump_lsupd, ps, "LSUPD packet received from %I via %s", n->ip, ifa->iface->name);
422

    
423
  if (n->state < NEIGHBOR_EXCHANGE)
424
  {
425
    OSPF_TRACE(D_PACKETS, "Received lsupd in lesser state than EXCHANGE from (%I)", n->ip);
426
    return;
427
  }
428

    
429
  if (size <=
430
      (sizeof(struct ospf_lsupd_packet) + sizeof(struct ospf_lsa_header)))
431
  {
432
    log(L_WARN "Received lsupd from %I is too short!", n->ip);
433
    return;
434
  }
435

    
436
  ospf_neigh_sm(n, INM_HELLOREC);        /* Questionable */
437

    
438
  lsa = (struct ospf_lsa_header *) (ps + 1);
439

    
440
  for (i = 0; i < ntohl(ps->lsano); i++,
441
       lsa = (struct ospf_lsa_header *) (((u8 *) lsa) + ntohs(lsa->length)))
442
  {
443
    struct ospf_lsa_header lsatmp;
444
    struct top_hash_entry *lsadb;
445
    unsigned diff = ((u8 *) lsa) - ((u8 *) ps), lenn = ntohs(lsa->length);
446
    u16 chsum;
447

    
448
    if (((diff + sizeof(struct ospf_lsa_header)) >= size)
449
        || ((lenn + diff) > size))
450
    {
451
      log(L_WARN "Received lsupd from %I is too short!", n->ip);
452
      ospf_neigh_sm(n, INM_BADLSREQ);
453
      break;
454
    }
455

    
456
    if ((lenn <= sizeof(struct ospf_lsa_header))
457
        || (lenn != (4 * (lenn / 4))))
458
    {
459
      log(L_WARN "Received LSA from %I with bad length", n->ip);
460
      ospf_neigh_sm(n, INM_BADLSREQ);
461
      break;
462
    }
463

    
464
    /* pg 143 (1) */
465
    chsum = lsa->checksum;
466
    log(L_WARN "Checking rcv %R %R %d (len %d)", ntohl(lsa->id), ntohl(lsa->rt), ntoht(lsa->type), ntohs(lsa->length));
467
    buf_dump("RCV", lsa, ntohs(lsa->length));
468
    if (chsum != lsasum_check(lsa, NULL))
469
    {
470
      log(L_WARN "Received bad lsa checksum from %I: %x %x", n->ip, chsum, lsa->checksum);
471
      continue;
472
    }
473

    
474

    
475
#ifdef OSPFv2
476
    /* pg 143 (2) */
477
    if ((lsa->type < LSA_T_RT) || (lsa->type > LSA_T_EXT))
478
    {
479
      log(L_WARN "Unknown LSA type from %I", n->ip);
480
      continue;
481
    }
482

    
483
    /* pg 143 (3) */
484
    if ((lsa->type == LSA_T_EXT) && ifa->oa->stub)
485
    {
486
      log(L_WARN "Received External LSA in stub area from %I", n->ip);
487
      continue;
488
    }
489
#else /* OSPFv3 */
490
    /* 4.5.1 (2) */
491
    if ((LSA_SCOPE(lsa) == LSA_SCOPE_AS) && ifa->oa->stub)
492
    {
493
      log(L_WARN "Received LSA with AS scope in stub area from %I", n->ip);
494
      continue;
495
    }
496

    
497
    /* 4.5.1 (3) */
498
    if ((LSA_SCOPE(lsa) == LSA_SCOPE_RES))
499
    {
500
      log(L_WARN "Received LSA with invalid scope from %I", n->ip);
501
      continue;
502
    }
503
#endif
504

    
505
    ntohlsah(lsa, &lsatmp);
506

    
507
    DBG("Update Type: %u ID: %R RT: %R, Sn: 0x%08x Age: %u, Sum: %u\n",
508
        lsatmp.type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, lsatmp.checksum);
509

    
510
    u32 domain = ospf_lsa_domain(lsatmp.type, ifa);
511
    lsadb = ospf_hash_find_header(po->gr, domain, &lsatmp);
512

    
513
#ifdef LOCAL_DEBUG
514
    if (lsadb)
515
      DBG("I have Type: %u ID: %R RT: %R, Sn: 0x%08x Age: %u, Sum: %u\n",
516
          lsadb->lsa.type, lsadb->lsa.id, lsadb->lsa.rt,
517
          lsadb->lsa.sn, lsadb->lsa.age, lsadb->lsa.checksum);
518
#endif
519

    
520
    /* pg 143 (4) */
521
    if ((lsatmp.age == LSA_MAXAGE) && (lsadb == NULL) && can_flush_lsa(po))
522
    {
523
      ospf_lsack_enqueue(n, lsa, ACKL_DIRECT);
524
      continue;
525
    }
526

    
527
    /* pg 144 (5) */
528
    if ((lsadb == NULL) || (lsa_comp(&lsatmp, &lsadb->lsa) == CMP_NEWER))
529
    {
530
      struct ospf_iface *ift = NULL;
531
      void *body;
532
      int self = (lsatmp.rt == p->cf->global->router_id);
533

    
534
      DBG("PG143(5): Received LSA is newer\n");
535

    
536
#ifdef OSPFv2
537
      /* 13.4 - check self-originated LSAs of NET type */
538
      if ((!self) && (lsatmp.type == LSA_T_NET))
539
      {
540
        struct ospf_iface *nifa;
541
        WALK_LIST(nifa, po->iface_list)
542
        {
543
          if (!nifa->iface)
544
            continue;
545
          if (ipa_equal(nifa->iface->addr->ip, ipa_from_u32(lsatmp.id)))
546
          {
547
            self = 1;
548
            break;
549
          }
550
        }
551
      }
552
#endif
553

    
554
      /* pg 145 (5f) - premature aging of self originated lsa */
555
      if (self)
556
      {
557
        struct top_hash_entry *en;
558

    
559
        if ((lsatmp.age == LSA_MAXAGE) && (lsatmp.sn == LSA_MAXSEQNO))
560
        {
561
          ospf_lsack_enqueue(n, lsa, ACKL_DIRECT);
562
          continue;
563
        }
564

    
565
        lsatmp.age = LSA_MAXAGE;
566
        lsatmp.sn = LSA_MAXSEQNO;
567
        lsa->age = htons(LSA_MAXAGE);
568
        lsa->sn = htonl(LSA_MAXSEQNO);
569
        OSPF_TRACE(D_EVENTS, "Premature aging self originated lsa.");
570
        OSPF_TRACE(D_EVENTS, "Type: %d, Id: %R, Rt: %R",
571
                   lsatmp.type, lsatmp.id, lsatmp.rt);
572
        lsasum_check(lsa, (lsa + 1));        /* It also calculates chsum! */
573
        lsatmp.checksum = ntohs(lsa->checksum);
574
        ospf_lsupd_flood(po, NULL, lsa, &lsatmp, domain, 0);
575
        if (en = ospf_hash_find_header(po->gr, domain, &lsatmp))
576
        { /* FIXME verify hacks */
577
          ospf_lsupd_flood(po, NULL, NULL, &en->lsa, domain, 1);
578
        }
579
        continue;
580
      }
581

    
582
      /* pg 144 (5a) */
583
      if (lsadb && ((now - lsadb->inst_t) <= MINLSARRIVAL))        /* FIXME: test for flooding? */
584
      {
585
        DBG("I got it in less that MINLSARRIVAL\n");
586
        sendreq = 0;
587
        continue;
588
      }
589

    
590
      if (ospf_lsupd_flood(po, n, lsa, &lsatmp, domain, 1) == 0)
591
      {
592
        DBG("Wasn't flooded back\n");        /* ps 144(5e), pg 153 */
593
        if (ifa->state == OSPF_IS_BACKUP)
594
        {
595
          if (ifa->drid == n->rid)
596
            ospf_lsack_enqueue(n, lsa, ACKL_DELAY);
597
        }
598
        else
599
          ospf_lsack_enqueue(n, lsa, ACKL_DELAY);
600
      }
601

    
602
      /* Remove old from all ret lists */
603
      /* pg 144 (5c) */
604
      if (lsadb)
605
        WALK_LIST(ift, po->iface_list)
606
          WALK_LIST(ntmp, ift->neigh_list)
607
      {
608
        struct top_hash_entry *en;
609
        if (ntmp->state > NEIGHBOR_EXSTART)
610
          if ((en = ospf_hash_find_header(ntmp->lsrth, domain, &lsadb->lsa)) != NULL)
611
          {
612
            s_rem_node(SNODE en);
613
            if (en->lsa_body != NULL)
614
              mb_free(en->lsa_body);
615
            en->lsa_body = NULL;
616
            ospf_hash_delete(ntmp->lsrth, en);
617
          }
618
      }
619

    
620
      if ((lsatmp.age == LSA_MAXAGE) && (lsatmp.sn == LSA_MAXSEQNO)
621
          && lsadb && can_flush_lsa(po))
622
      {
623
        flush_lsa(lsadb, po);
624
        schedule_rtcalc(po);
625
        continue;
626
      }                                /* FIXME lsack? */
627

    
628
      /* pg 144 (5d) */
629
      body =
630
        mb_alloc(p->pool, lsatmp.length - sizeof(struct ospf_lsa_header));
631
      ntohlsab(lsa + 1, body, lsatmp.type,
632
               lsatmp.length - sizeof(struct ospf_lsa_header));
633
      lsadb = lsa_install_new(po, &lsatmp, domain, body);
634
      DBG("New LSA installed in DB\n");
635

    
636
      continue;
637
    }
638

    
639
    /* FIXME pg145 (6) */
640

    
641
    /* pg145 (7) */
642
    if (lsa_comp(&lsatmp, &lsadb->lsa) == CMP_SAME)
643
    {
644
      struct top_hash_entry *en;
645
      DBG("PG145(7) Got the same LSA\n");
646
      if ((en = ospf_hash_find_header(n->lsrth, lsadb->domain, &lsadb->lsa)) != NULL)
647
      {
648
        /* pg145 (7a) */
649
        s_rem_node(SNODE en);
650
        if (en->lsa_body != NULL)
651
          mb_free(en->lsa_body);
652
        en->lsa_body = NULL;
653
        ospf_hash_delete(n->lsrth, en);
654
        if (ifa->state == OSPF_IS_BACKUP)
655
        {
656
          if (n->rid == ifa->drid)
657
            ospf_lsack_enqueue(n, lsa, ACKL_DELAY);
658
        }
659
      }
660
      else
661
      {
662
        /* pg145 (7b) */
663
        ospf_lsack_enqueue(n, lsa, ACKL_DIRECT);
664
      }
665
      sendreq = 0;
666
      continue;
667
    }
668

    
669
    /* pg145 (8) */
670
    if ((lsadb->lsa.age == LSA_MAXAGE) && (lsadb->lsa.sn == LSA_MAXSEQNO))
671
    {
672
      continue;
673
    }
674

    
675
    {
676
      list l;
677
      struct l_lsr_head ll;
678
      init_list(&l);
679
      ll.lsh.id = lsadb->lsa.id;
680
      ll.lsh.rt = lsadb->lsa.rt;
681
      ll.lsh.type = lsadb->lsa.type;
682
      add_tail(&l, NODE & ll);
683
      ospf_lsupd_send_list(n, &l);
684
    }
685
  }
686

    
687
  /* Send direct LSAs */
688
  ospf_lsack_send(n, ACKL_DIRECT);
689

    
690
  if (sendreq && (n->state == NEIGHBOR_LOADING))
691
  {
692
    ospf_lsreq_send(n);                /* Ask for another part of neighbor's database */
693
  }
694
}
695

    
696
void
697
ospf_lsupd_flush_nlsa(struct proto_ospf *po, struct top_hash_entry *en)
698
{
699
  struct ospf_lsa_header *lsa = &en->lsa;
700
  struct proto *p = &po->proto;
701

    
702
  lsa->age = LSA_MAXAGE;
703
  lsa->sn = LSA_MAXSEQNO;
704
  lsasum_calculate(lsa, en->lsa_body);
705
  OSPF_TRACE(D_EVENTS, "Premature aging self originated lsa!");
706
  OSPF_TRACE(D_EVENTS, "Type: %d, Id: %R, Rt: %R", lsa->type, lsa->id, lsa->rt);
707
  ospf_lsupd_flood(po, NULL, NULL, lsa, en->domain, 0);
708
}