Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / dbdes.c @ a7a7372a

History | View | Annotate | Download (12.2 KB)

1
/*
2
 *        BIRD -- OSPF
3
 *
4
 *        (c) 1999--2004 Ondrej Filip <feela@network.cz>
5
 *        (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
6
 *        (c) 2009--2014 CZ.NIC z.s.p.o.
7
 *
8
 *        Can be freely distributed and used under the terms of the GNU GPL.
9
 */
10

    
11
#include "ospf.h"
12

    
13

    
14
struct ospf_dbdes2_packet
15
{
16
  struct ospf_packet hdr;
17
  union ospf_auth auth;
18

    
19
  u16 iface_mtu;
20
  u8 options;
21
  u8 imms;                        /* I, M, MS bits */
22
  u32 ddseq;
23

    
24
  struct ospf_lsa_header lsas[];
25
};
26

    
27
struct ospf_dbdes3_packet
28
{
29
  struct ospf_packet hdr;
30

    
31
  u32 options;
32
  u16 iface_mtu;
33
  u8 padding;
34
  u8 imms;                        /* I, M, MS bits */
35
  u32 ddseq;
36

    
37
  struct ospf_lsa_header lsas[];
38
};
39

    
40

    
41
static inline uint
42
ospf_dbdes_hdrlen(struct ospf_proto *p)
43
{
44
  return ospf_is_v2(p) ?
45
    sizeof(struct ospf_dbdes2_packet) : sizeof(struct ospf_dbdes3_packet);
46
}
47

    
48

    
49
static void
50
ospf_dbdes_body(struct ospf_proto *p, struct ospf_packet *pkt,
51
                struct ospf_lsa_header **body, uint *count)
52
{
53
  uint plen = ntohs(pkt->length);
54
  uint hlen = ospf_dbdes_hdrlen(p);
55

    
56
  *body = ((void *) pkt) + hlen;
57
  *count = (plen - hlen) / sizeof(struct ospf_lsa_header);
58
}
59
  
60
static void
61
ospf_dump_dbdes(struct ospf_proto *p, struct ospf_packet *pkt)
62
{
63
  struct ospf_lsa_header *lsas;
64
  uint i, lsa_count;
65
  u32 pkt_ddseq;
66
  u16 pkt_iface_mtu;
67
  u8 pkt_imms;
68

    
69
  ASSERT(pkt->type == DBDES_P);
70
  ospf_dump_common(p, pkt);
71

    
72
  if (ospf_is_v2(p))
73
  {
74
    struct ospf_dbdes2_packet *ps = (void *) pkt;
75
    pkt_iface_mtu = ntohs(ps->iface_mtu);
76
    pkt_imms = ps->imms;
77
    pkt_ddseq = ntohl(ps->ddseq);
78
  }
79
  else /* OSPFv3 */
80
  {
81
    struct ospf_dbdes3_packet *ps = (void *) pkt;
82
    pkt_iface_mtu = ntohs(ps->iface_mtu);
83
    pkt_imms = ps->imms;
84
    pkt_ddseq = ntohl(ps->ddseq);
85
  }
86

    
87
  log(L_TRACE "%s:     mtu      %u", p->p.name, pkt_iface_mtu);
88
  log(L_TRACE "%s:     imms     %s%s%s", p->p.name,
89
      (pkt_imms & DBDES_I) ? "I " : "",
90
      (pkt_imms & DBDES_M) ? "M " : "",
91
      (pkt_imms & DBDES_MS) ? "MS" : "");
92
  log(L_TRACE "%s:     ddseq    %u", p->p.name, pkt_ddseq);
93

    
94
  ospf_dbdes_body(p, pkt, &lsas, &lsa_count);
95
  for (i = 0; i < lsa_count; i++)
96
    ospf_dump_lsahdr(p, lsas + i);
97
}
98

    
99

    
100
static void
101
ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int body)
102
{
103
  struct ospf_iface *ifa = n->ifa;
104
  struct ospf_packet *pkt;
105
  uint length;
106

    
107
  u16 iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : ifa->iface->mtu;
108

    
109
  if (n->ldd_bsize != ifa->tx_length)
110
  {
111
    mb_free(n->ldd_buffer);
112
    n->ldd_buffer = mb_allocz(n->pool, ifa->tx_length);
113
    n->ldd_bsize = ifa->tx_length;
114
  }
115

    
116
  pkt = n->ldd_buffer;
117
  ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
118

    
119
  if (ospf_is_v2(p))
120
  {
121
    struct ospf_dbdes2_packet *ps = (void *) pkt;
122
    ps->iface_mtu = htons(iface_mtu);
123
    ps->options = ifa->oa->options;
124
    ps->imms = 0;        /* Will be set later */
125
    ps->ddseq = htonl(n->dds);
126
    length = sizeof(struct ospf_dbdes2_packet);
127
  }
128
  else /* OSPFv3 */
129
  {
130
    struct ospf_dbdes3_packet *ps = (void *) pkt;
131
    ps->options = htonl(ifa->oa->options);
132
    ps->iface_mtu = htons(iface_mtu);
133
    ps->padding = 0;
134
    ps->imms = 0;        /* Will be set later */
135
    ps->ddseq = htonl(n->dds);
136
    length = sizeof(struct ospf_dbdes3_packet);
137
  }
138

    
139
  if (body && (n->myimms & DBDES_M))
140
  {
141
    struct ospf_lsa_header *lsas;
142
    struct top_hash_entry *en;
143
    uint i = 0, lsa_max;
144

    
145
    ospf_dbdes_body(p, pkt, &lsas, &lsa_max);
146
    en = (void *) s_get(&(n->dbsi));
147

    
148
    while (i < lsa_max)
149
    {
150
      if (!SNODE_VALID(en))
151
      {
152
        n->myimms &= ~DBDES_M;        /* Unset More bit */
153
        break;
154
      }
155

    
156
      if ((en->lsa.age < LSA_MAXAGE) &&
157
          lsa_flooding_allowed(en->lsa_type, en->domain, ifa))
158
      {
159
        lsa_hton_hdr(&(en->lsa), lsas + i);
160
        i++;
161
      }
162

    
163
      en = SNODE_NEXT(en);
164
    }
165

    
166
    s_put(&(n->dbsi), SNODE en);
167

    
168
    length += i * sizeof(struct ospf_lsa_header);
169
  }
170

    
171
  if (ospf_is_v2(p))
172
    ((struct ospf_dbdes2_packet *) pkt)->imms = n->myimms;
173
  else
174
    ((struct ospf_dbdes3_packet *) pkt)->imms = n->myimms;
175

    
176
  pkt->length = htons(length);
177
}
178

    
179
static void
180
ospf_do_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
181
{
182
  struct ospf_iface *ifa = n->ifa;
183

    
184
  OSPF_PACKET(ospf_dump_dbdes, n->ldd_buffer,
185
              "DBDES packet sent to %I via %s", n->ip, ifa->ifname);
186
  sk_set_tbuf(ifa->sk, n->ldd_buffer);
187
  ospf_send_to(ifa, n->ip);
188
  sk_set_tbuf(ifa->sk, NULL);
189
}
190

    
191
/**
192
 * ospf_send_dbdes - transmit database description packet
193
 * @n: neighbor
194
 * @next: whether to send a next packet in a sequence (1) or to retransmit the old one (0)
195
 *
196
 * Sending of a database description packet is described in 10.8 of RFC 2328.
197
 * Reception of each packet is acknowledged in the sequence number of another.
198
 * When I send a packet to a neighbor I keep a copy in a buffer. If the neighbor
199
 * does not reply, I don't create a new packet but just send the content
200
 * of the buffer.
201
 */
202
void
203
ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int next)
204
{
205
  /* RFC 2328 10.8 */
206

    
207
  if (n->ifa->oa->rt == NULL)
208
    return;
209

    
210
  switch (n->state)
211
  {
212
  case NEIGHBOR_EXSTART:
213
    n->myimms |= DBDES_I;
214

    
215
    /* Send empty packets */
216
    ospf_prepare_dbdes(p, n, 0);
217
    ospf_do_send_dbdes(p, n);
218
    break;
219

    
220
  case NEIGHBOR_EXCHANGE:
221
    n->myimms &= ~DBDES_I;
222

    
223
    if (next)
224
      ospf_prepare_dbdes(p, n, 1);
225

    
226
    /* Send prepared packet */
227
    ospf_do_send_dbdes(p, n);
228

    
229
    /* Master should restart RXMT timer for each DBDES exchange */
230
    if (n->myimms & DBDES_MS)
231
      tm_start(n->rxmt_timer, n->ifa->rxmtint);
232

    
233
    if (!(n->myimms & DBDES_MS))
234
      if (!(n->myimms & DBDES_M) && 
235
          !(n->imms & DBDES_M))
236
        ospf_neigh_sm(n, INM_EXDONE);
237
    break;
238

    
239
  case NEIGHBOR_LOADING:
240
  case NEIGHBOR_FULL:
241

    
242
    if (!n->ldd_buffer)
243
    {
244
      OSPF_TRACE(D_PACKETS, "No DBDES packet for repeating");
245
      ospf_neigh_sm(n, INM_KILLNBR);
246
      return;
247
    }
248

    
249
    /* Send last packet */
250
    ospf_do_send_dbdes(p, n);
251
    break;
252
  }
253
}
254

    
255

    
256
static int
257
ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_neighbor *n)
258
{
259
  struct ospf_iface *ifa = n->ifa;
260
  struct ospf_lsa_header *lsas;
261
  uint i, lsa_count;
262

    
263
  ospf_dbdes_body(p, pkt, &lsas, &lsa_count);
264

    
265
  for (i = 0; i < lsa_count; i++)
266
  {
267
    struct top_hash_entry *en, *req;
268
    struct ospf_lsa_header lsa;
269
    u32 lsa_type, lsa_domain;
270

    
271
    lsa_ntoh_hdr(lsas + i, &lsa);
272
    lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain);
273

    
274
    /* RFC 2328 10.6 and RFC 5340 4.2.2 */
275

    
276
    if (!lsa_type)
277
    {
278
      log(L_WARN "%s: Bad DBDES from %I - LSA of unknown type", p->p.name, n->ip);
279
      goto err;
280
    }
281

    
282
    if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS))
283
    {
284
      log(L_WARN "%s: Bad DBDES from %I - LSA with AS scope in stub area", p->p.name, n->ip);
285
      goto err;
286
    }
287

    
288
    /* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */
289
    if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT))
290
    {
291
      log(L_WARN "%s: Bad DBDES from %I - rt-summary-LSA in stub area", p->p.name, n->ip);
292
      goto err;
293
    }
294

    
295
    /* Not explicitly mentioned in RFC 5340 4.2.2 but makes sense */
296
    if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
297
    {
298
      log(L_WARN "%s: Bad DBDES from %I - LSA with invalid scope", p->p.name, n->ip);
299
      goto err;
300
    }
301

    
302
    en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
303
    if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER))
304
    {
305
      req = ospf_hash_get(n->lsrqh, lsa_domain, lsa.id, lsa.rt, lsa_type);
306

    
307
      if (!SNODE_VALID(req))
308
        s_add_tail(&n->lsrql, SNODE req);
309

    
310
      req->lsa = lsa;
311
      req->lsa_body = LSA_BODY_DUMMY;
312
    }
313
  }
314

    
315
  return 0;
316

    
317
 err:
318
  ospf_neigh_sm(n, INM_SEQMIS);
319
  return -1;
320
}
321

    
322
void
323
ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
324
                   struct ospf_neighbor *n)
325
{
326
  struct ospf_proto *p = ifa->oa->po;
327
  u32 rcv_ddseq, rcv_options;
328
  u16 rcv_iface_mtu;
329
  u8 rcv_imms;
330
  uint plen;
331

    
332
  /* RFC 2328 10.6 */
333

    
334
  plen = ntohs(pkt->length);
335
  if (plen < ospf_dbdes_hdrlen(p))
336
  {
337
    log(L_ERR "OSPF: Bad DBDES packet from %I - too short (%u B)", n->ip, plen);
338
    return;
339
  }
340

    
341
  OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet received from %I via %s", n->ip, ifa->ifname);
342

    
343
  ospf_neigh_sm(n, INM_HELLOREC);
344

    
345
  if (ospf_is_v2(p))
346
  {
347
    struct ospf_dbdes2_packet *ps = (void *) pkt;
348
    rcv_iface_mtu = ntohs(ps->iface_mtu);
349
    rcv_options = ps->options;
350
    rcv_imms = ps->imms;
351
    rcv_ddseq = ntohl(ps->ddseq);
352
  }
353
  else /* OSPFv3 */
354
  {
355
    struct ospf_dbdes3_packet *ps = (void *) pkt;
356
    rcv_options = ntohl(ps->options);
357
    rcv_iface_mtu = ntohs(ps->iface_mtu);
358
    rcv_imms = ps->imms;
359
    rcv_ddseq = ntohl(ps->ddseq);
360
  }
361
  
362
  switch (n->state)
363
  {
364
  case NEIGHBOR_DOWN:
365
  case NEIGHBOR_ATTEMPT:
366
  case NEIGHBOR_2WAY:
367
    return;
368

    
369
  case NEIGHBOR_INIT:
370
    ospf_neigh_sm(n, INM_2WAYREC);
371
    if (n->state != NEIGHBOR_EXSTART)
372
      return;
373

    
374
  case NEIGHBOR_EXSTART:
375
    if ((ifa->type != OSPF_IT_VLINK) &&
376
        (rcv_iface_mtu != ifa->iface->mtu) &&
377
        (rcv_iface_mtu != 0) &&
378
        (ifa->iface->mtu != 0))
379
      log(L_WARN "OSPF: MTU mismatch with neighbor %I on interface %s (remote %d, local %d)",
380
          n->ip, ifa->ifname, rcv_iface_mtu, ifa->iface->mtu);
381

    
382
    if ((rcv_imms == DBDES_IMMS) &&
383
        (n->rid > p->router_id) &&
384
        (plen == ospf_dbdes_hdrlen(p)))
385
    {
386
      /* I'm slave! */
387
      n->dds = rcv_ddseq;
388
      n->ddr = rcv_ddseq;
389
      n->options = rcv_options;
390
      n->myimms &= ~DBDES_MS;
391
      n->imms = rcv_imms;
392
      OSPF_TRACE(D_PACKETS, "I'm slave to %I", n->ip);
393
      ospf_neigh_sm(n, INM_NEGDONE);
394
      ospf_send_dbdes(p, n, 1);
395
      break;
396
    }
397

    
398
    if (!(rcv_imms & DBDES_I) &&
399
        !(rcv_imms & DBDES_MS) &&
400
        (n->rid < p->router_id) &&
401
        (n->dds == rcv_ddseq))
402
    {
403
      /* I'm master! */
404
      n->options = rcv_options;
405
      n->ddr = rcv_ddseq - 1;        /* It will be set corectly a few lines down */
406
      n->imms = rcv_imms;
407
      OSPF_TRACE(D_PACKETS, "I'm master to %I", n->ip);
408
      ospf_neigh_sm(n, INM_NEGDONE);
409
    }
410
    else
411
    {
412
      DBG("%s: Nothing happend to %I (imms=%d)\n", p->name, n->ip, rcv_imms);
413
      break;
414
    }
415

    
416
  case NEIGHBOR_EXCHANGE:
417
    if ((rcv_imms == n->imms) &&
418
        (rcv_options == n->options) &&
419
        (rcv_ddseq == n->ddr))
420
    {
421
      /* Duplicate packet */
422
      OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I", n->ip);
423
      if (!(n->myimms & DBDES_MS))
424
      {
425
        /* Slave should retransmit dbdes packet */
426
        ospf_send_dbdes(p, n, 0);
427
      }
428
      return;
429
    }
430

    
431
    if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS))        /* M/S bit differs */
432
    {
433
      OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit MS)", n->ip);
434
      ospf_neigh_sm(n, INM_SEQMIS);
435
      break;
436
    }
437

    
438
    if (rcv_imms & DBDES_I)                /* I bit is set */
439
    {
440
      OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit I)", n->ip);
441
      ospf_neigh_sm(n, INM_SEQMIS);
442
      break;
443
    }
444

    
445
    if (rcv_options != n->options)        /* Options differs */
446
    {
447
      OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (options)", n->ip);
448
      ospf_neigh_sm(n, INM_SEQMIS);
449
      break;
450
    }
451

    
452
    n->ddr = rcv_ddseq;
453
    n->imms = rcv_imms;
454

    
455
    if (n->myimms & DBDES_MS)
456
    {
457
      if (rcv_ddseq != n->dds)        /* MASTER */
458
      {
459
        OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (master)", n->ip);
460
        ospf_neigh_sm(n, INM_SEQMIS);
461
        break;
462
      }
463

    
464
      n->dds++;
465

    
466
      if (ospf_process_dbdes(p, pkt, n) < 0)
467
        return;
468

    
469
      if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
470
        ospf_neigh_sm(n, INM_EXDONE);
471
      else
472
        ospf_send_dbdes(p, n, 1);
473
    }
474
    else
475
    {
476
      if (rcv_ddseq != (n->dds + 1))        /* SLAVE */
477
      {
478
        OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)", n->ip);
479
        ospf_neigh_sm(n, INM_SEQMIS);
480
        break;
481
      }
482

    
483
      n->ddr = rcv_ddseq;
484
      n->dds = rcv_ddseq;
485

    
486
      if (ospf_process_dbdes(p, pkt, n) < 0)
487
        return;
488

    
489
      ospf_send_dbdes(p, n, 1);
490
    }
491
    break;
492

    
493
  case NEIGHBOR_LOADING:
494
  case NEIGHBOR_FULL:
495
    if ((rcv_imms == n->imms) &&
496
        (rcv_options == n->options) &&
497
        (rcv_ddseq == n->ddr))
498
    {
499
      /* Duplicate packet */
500
      OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I", n->ip);
501
      if (!(n->myimms & DBDES_MS))
502
      {
503
        /* Slave should retransmit dbdes packet */
504
        ospf_send_dbdes(p, n, 0);
505
      }
506
      return;
507
    }
508
    else
509
    {
510
      OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (full)", n->ip);
511
      DBG("PS=%u, DDR=%u, DDS=%u\n", rcv_ddseq, n->ddr, n->dds);
512
      ospf_neigh_sm(n, INM_SEQMIS);
513
    }
514
    break;
515

    
516
  default:
517
    bug("Received dbdes from %I in undefined state.", n->ip);
518
  }
519
}