Statistics
| Branch: | Revision:

iof-bird / bird-2.0.1 / proto / ospf / dbdes.c @ 6b3f1a54

History | View | Annotate | Download (11.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)
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
  /* Update DBDES buffer */
110
  if (n->ldd_bsize != ifa->tx_length)
111
  {
112
    mb_free(n->ldd_buffer);
113
    n->ldd_buffer = mb_allocz(n->pool, ifa->tx_length);
114
    n->ldd_bsize = ifa->tx_length;
115
  }
116

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

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

    
140
  /* Prepare DBDES body */
141
  if (!(n->myimms & DBDES_I) && (n->myimms & DBDES_M))
142
  {
143
    struct ospf_lsa_header *lsas;
144
    struct top_hash_entry *en;
145
    uint i = 0, lsa_max;
146

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

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

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

    
165
      en = SNODE_NEXT(en);
166
    }
167

    
168
    s_put(&(n->dbsi), SNODE en);
169

    
170
    length += i * sizeof(struct ospf_lsa_header);
171
  }
172

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

    
178
  pkt->length = htons(length);
179
}
180

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

    
186
  OSPF_PACKET(ospf_dump_dbdes, n->ldd_buffer,
187
              "DBDES packet sent to nbr %R on %s", n->rid, ifa->ifname);
188
  sk_set_tbuf(ifa->sk, n->ldd_buffer);
189
  ospf_send_to(ifa, n->ip);
190
  sk_set_tbuf(ifa->sk, NULL);
191
}
192

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

    
209
  ASSERT((n->state == NEIGHBOR_EXSTART) || (n->state == NEIGHBOR_EXCHANGE));
210

    
211
  if (n->ifa->oa->rt == NULL)
212
    return;
213

    
214
  ospf_prepare_dbdes(p, n);
215
  ospf_do_send_dbdes(p, n);
216
}
217

    
218
void
219
ospf_rxmt_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
220
{
221
  ASSERT(n->state > NEIGHBOR_EXSTART);
222

    
223
  if (!n->ldd_buffer)
224
  {
225
    log(L_WARN "%s: No DBDES packet for retransmit", p->p.name);
226
    ospf_neigh_sm(n, INM_SEQMIS);
227
    return;
228
  }
229

    
230
  /* Send last packet */
231
  ospf_do_send_dbdes(p, n);
232
}
233

    
234
static int
235
ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_neighbor *n)
236
{
237
  struct ospf_iface *ifa = n->ifa;
238
  struct ospf_lsa_header *lsas, lsa;
239
  struct top_hash_entry *en, *req;
240
  const char *err_dsc = NULL;
241
  u32 lsa_type, lsa_domain;
242
  uint i, lsa_count;
243

    
244
  ospf_dbdes_body(p, pkt, &lsas, &lsa_count);
245

    
246
  for (i = 0; i < lsa_count; i++)
247
  {
248
    lsa_ntoh_hdr(lsas + i, &lsa);
249
    lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain);
250

    
251
    /* RFC 2328 10.6 and RFC 5340 4.2.2 */
252

    
253
    if (!lsa_type)
254
      DROP1("LSA of unknown type");
255

    
256
    if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS))
257
      DROP1("LSA with AS scope in stub area");
258

    
259
    /* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */
260
    if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT))
261
      DROP1("rt-summary-LSA in stub area");
262

    
263
    /* Not explicitly mentioned in RFC 5340 4.2.2 but makes sense */
264
    if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
265
      DROP1("LSA with invalid scope");
266

    
267
    en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
268
    if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER))
269
    {
270
      /* This should be splitted to ospf_lsa_lsrq_up() */
271
      req = ospf_hash_get(n->lsrqh, lsa_domain, lsa.id, lsa.rt, lsa_type);
272

    
273
      if (!SNODE_VALID(req))
274
        s_add_tail(&n->lsrql, SNODE req);
275

    
276
      if (!SNODE_VALID(n->lsrqi))
277
        n->lsrqi = req;
278

    
279
      req->lsa = lsa;
280
      req->lsa_body = LSA_BODY_DUMMY;
281

    
282
      if (!tm_active(n->lsrq_timer))
283
        tm_start(n->lsrq_timer, 0);
284
    }
285
  }
286

    
287
  return 0;
288

    
289
drop:
290
  LOG_LSA1("Bad LSA (Type: %04x, Id: %R, Rt: %R) in DBDES", lsa_type, lsa.id, lsa.rt);
291
  LOG_LSA2("  received from nbr %R on %s - %s", n->rid, ifa->ifname, err_dsc);
292

    
293
  ospf_neigh_sm(n, INM_SEQMIS);
294
  return -1;
295
}
296

    
297
void
298
ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
299
                   struct ospf_neighbor *n)
300
{
301
  struct ospf_proto *p = ifa->oa->po;
302
  const char *err_dsc = NULL;
303
  u32 rcv_ddseq, rcv_options;
304
  u16 rcv_iface_mtu;
305
  u8 rcv_imms;
306
  uint plen, err_val = 0;
307

    
308
  /* RFC 2328 10.6 */
309

    
310
  plen = ntohs(pkt->length);
311
  if (plen < ospf_dbdes_hdrlen(p))
312
  {
313
    LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)", n->rid, ifa->ifname, "too short", plen);
314
    return;
315
  }
316

    
317
  OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet received from nbr %R on %s", n->rid, ifa->ifname);
318

    
319
  ospf_neigh_sm(n, INM_HELLOREC);
320

    
321
  if (ospf_is_v2(p))
322
  {
323
    struct ospf_dbdes2_packet *ps = (void *) pkt;
324
    rcv_iface_mtu = ntohs(ps->iface_mtu);
325
    rcv_options = ps->options;
326
    rcv_imms = ps->imms;
327
    rcv_ddseq = ntohl(ps->ddseq);
328
  }
329
  else /* OSPFv3 */
330
  {
331
    struct ospf_dbdes3_packet *ps = (void *) pkt;
332
    rcv_options = ntohl(ps->options);
333
    rcv_iface_mtu = ntohs(ps->iface_mtu);
334
    rcv_imms = ps->imms;
335
    rcv_ddseq = ntohl(ps->ddseq);
336
  }
337

    
338
  switch (n->state)
339
  {
340
  case NEIGHBOR_DOWN:
341
  case NEIGHBOR_ATTEMPT:
342
  case NEIGHBOR_2WAY:
343
    OSPF_TRACE(D_PACKETS, "DBDES packet ignored - lesser state than ExStart");
344
    return;
345

    
346
  case NEIGHBOR_INIT:
347
    ospf_neigh_sm(n, INM_2WAYREC);
348
    if (n->state != NEIGHBOR_EXSTART)
349
      return;
350

    
351
  case NEIGHBOR_EXSTART:
352
    if ((ifa->type != OSPF_IT_VLINK) &&
353
        (rcv_iface_mtu != ifa->iface->mtu) &&
354
        (rcv_iface_mtu != 0) &&
355
        (ifa->iface->mtu != 0))
356
      LOG_PKT_WARN("MTU mismatch with nbr %R on %s (remote %d, local %d)",
357
                   n->rid, ifa->ifname, rcv_iface_mtu, ifa->iface->mtu);
358

    
359
    if (((rcv_imms & DBDES_IMMS) == DBDES_IMMS) &&
360
        (n->rid > p->router_id) &&
361
        (plen == ospf_dbdes_hdrlen(p)))
362
    {
363
      /* I'm slave! */
364
      n->dds = rcv_ddseq;
365
      n->ddr = rcv_ddseq;
366
      n->options = rcv_options;
367
      n->myimms &= ~DBDES_MS;
368
      n->imms = rcv_imms;
369
      tm_stop(n->dbdes_timer);
370
      ospf_neigh_sm(n, INM_NEGDONE);
371
      ospf_send_dbdes(p, n);
372
      break;
373
    }
374

    
375
    if (!(rcv_imms & DBDES_I) &&
376
        !(rcv_imms & DBDES_MS) &&
377
        (n->rid < p->router_id) &&
378
        (n->dds == rcv_ddseq))
379
    {
380
      /* I'm master! */
381
      n->options = rcv_options;
382
      n->ddr = rcv_ddseq - 1;        /* It will be set corectly a few lines down */
383
      n->imms = rcv_imms;
384
      ospf_neigh_sm(n, INM_NEGDONE);
385
      /* Continue to the NEIGHBOR_EXCHANGE case */
386
    }
387
    else
388
    {
389
      DBG("%s: Nothing happend to %I (imms=%d)\n", p->name, n->ip, rcv_imms);
390
      break;
391
    }
392

    
393
  case NEIGHBOR_EXCHANGE:
394
    if ((rcv_imms == n->imms) &&
395
        (rcv_options == n->options) &&
396
        (rcv_ddseq == n->ddr))
397
      goto duplicate;
398

    
399
    if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS))
400
      DROP("MS-bit mismatch", rcv_imms);
401

    
402
    if (rcv_imms & DBDES_I)
403
      DROP("I-bit mismatch", rcv_imms);
404

    
405
    if (rcv_options != n->options)
406
      DROP("options mismatch", rcv_options);
407

    
408
    n->ddr = rcv_ddseq;
409
    n->imms = rcv_imms;
410

    
411
    if (n->myimms & DBDES_MS)
412
    {
413
      /* MASTER */
414

    
415
      if (rcv_ddseq != n->dds)
416
        DROP("DD sequence number mismatch", rcv_ddseq);
417

    
418
      n->dds++;
419

    
420
      if (ospf_process_dbdes(p, pkt, n) < 0)
421
        return;
422

    
423
      if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
424
      {
425
        tm_stop(n->dbdes_timer);
426
        ospf_neigh_sm(n, INM_EXDONE);
427
        break;
428
      }
429

    
430
      ospf_send_dbdes(p, n);
431
      tm_start(n->dbdes_timer, n->ifa->rxmtint S);
432
    }
433
    else
434
    {
435
      /* SLAVE */
436

    
437
      if (rcv_ddseq != (n->dds + 1))
438
        DROP("DD sequence number mismatch", rcv_ddseq);
439

    
440
      n->ddr = rcv_ddseq;
441
      n->dds = rcv_ddseq;
442

    
443
      if (ospf_process_dbdes(p, pkt, n) < 0)
444
        return;
445

    
446
      ospf_send_dbdes(p, n);
447

    
448
      if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
449
        ospf_neigh_sm(n, INM_EXDONE);
450
    }
451
    break;
452

    
453
  case NEIGHBOR_LOADING:
454
  case NEIGHBOR_FULL:
455
    if ((rcv_imms == n->imms) &&
456
        (rcv_options == n->options) &&
457
        (rcv_ddseq == n->ddr))
458
      goto duplicate;
459

    
460
    DROP("too late for DD exchange", n->state);
461

    
462
  default:
463
    bug("Undefined interface state");
464
  }
465
  return;
466

    
467
duplicate:
468
  OSPF_TRACE(D_PACKETS, "DBDES packet is duplicate");
469

    
470
  /* Slave should retransmit DBDES packet */
471
  if (!(n->myimms & DBDES_MS))
472
    ospf_rxmt_dbdes(p, n);
473
  return;
474

    
475
drop:
476
  LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)",
477
          n->rid, ifa->ifname, err_dsc, err_val);
478

    
479
  ospf_neigh_sm(n, INM_SEQMIS);
480
  return;
481
}