Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / packet.c @ 48e5f32d

History | View | Annotate | Download (13.9 KB)

1
/*
2
 *        BIRD -- OSPF
3
 *
4
 *        (c) 1999--2005 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
#include "nest/password.h"
11
#include "lib/md5.h"
12

    
13
void
14
ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
15
{
16
  struct proto_ospf *po = ifa->oa->po;
17
  struct ospf_packet *pkt;
18

    
19
  pkt = (struct ospf_packet *) buf;
20

    
21
  pkt->version = OSPF_VERSION;
22

    
23
  pkt->type = h_type;
24

    
25
  pkt->routerid = htonl(po->router_id);
26
  pkt->areaid = htonl(ifa->oa->areaid);
27

    
28
#ifdef OSPFv3
29
  pkt->instance_id = ifa->instance_id;
30
#endif
31

    
32
#ifdef OSPFv2
33
  pkt->autype = htons(ifa->autype);
34
#endif
35

    
36
  pkt->checksum = 0;
37
}
38

    
39
unsigned
40
ospf_pkt_maxsize(struct ospf_iface *ifa)
41
{
42
  unsigned headers = SIZE_OF_IP_HEADER;
43

    
44
#ifdef OSPFv2
45
  if (ifa->autype == OSPF_AUTH_CRYPT)
46
    headers += OSPF_AUTH_CRYPT_SIZE;
47
#endif
48

    
49
  return ifa->tx_length - headers;
50
}
51

    
52
#ifdef OSPFv2
53

    
54
static void
55
ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
56
{
57
  struct password_item *passwd = NULL;
58
  void *tail;
59
  struct MD5Context ctxt;
60
  char password[OSPF_AUTH_CRYPT_SIZE];
61

    
62
  pkt->checksum = 0;
63
  pkt->autype = htons(ifa->autype);
64
  bzero(&pkt->u, sizeof(union ospf_auth));
65

    
66
  /* Compatibility note: pkt->u may contain anything if autype is
67
     none, but nonzero values do not work with Mikrotik OSPF */
68

    
69
  switch(ifa->autype)
70
  {
71
    case OSPF_AUTH_SIMPLE:
72
      passwd = password_find(ifa->passwords, 1);
73
      if (!passwd)
74
      {
75
        log( L_ERR "No suitable password found for authentication" );
76
        return;
77
      }
78
      password_cpy(pkt->u.password, passwd->password, sizeof(union ospf_auth));
79
    case OSPF_AUTH_NONE:
80
      pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet) -
81
                                  sizeof(union ospf_auth), (pkt + 1),
82
                                  ntohs(pkt->length) -
83
                                  sizeof(struct ospf_packet), NULL);
84
      break;
85
    case OSPF_AUTH_CRYPT:
86
      passwd = password_find(ifa->passwords, 0);
87
      if (!passwd)
88
      {
89
        log( L_ERR "No suitable password found for authentication" );
90
        return;
91
      }
92

    
93
      /* Perhaps use random value to prevent replay attacks after
94
         reboot when system does not have independent RTC? */
95
      if (!ifa->csn)
96
        {
97
          ifa->csn = (u32) now;
98
          ifa->csn_use = now;
99
        }
100

    
101
      /* We must have sufficient delay between sending a packet and increasing 
102
         CSN to prevent reordering of packets (in a network) with different CSNs */
103
      if ((now - ifa->csn_use) > 1)
104
        ifa->csn++;
105

    
106
      ifa->csn_use = now;
107

    
108
      pkt->u.md5.keyid = passwd->id;
109
      pkt->u.md5.len = OSPF_AUTH_CRYPT_SIZE;
110
      pkt->u.md5.zero = 0;
111
      pkt->u.md5.csn = htonl(ifa->csn);
112
      tail = ((void *)pkt) + ntohs(pkt->length);
113
      MD5Init(&ctxt);
114
      MD5Update(&ctxt, (char *) pkt, ntohs(pkt->length));
115
      password_cpy(password, passwd->password, OSPF_AUTH_CRYPT_SIZE);
116
      MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
117
      MD5Final(tail, &ctxt);
118
      break;
119
    default:
120
      bug("Unknown authentication type");
121
  }
122
}
123

    
124
static int
125
ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size)
126
{
127
  struct proto_ospf *po = ifa->oa->po;
128
  struct proto *p = &po->proto;
129
  struct password_item *pass = NULL, *ptmp;
130
  void *tail;
131
  char md5sum[OSPF_AUTH_CRYPT_SIZE];
132
  char password[OSPF_AUTH_CRYPT_SIZE];
133
  struct MD5Context ctxt;
134

    
135

    
136
  if (pkt->autype != htons(ifa->autype))
137
  {
138
    OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", ntohs(pkt->autype));
139
    return 0;
140
  }
141

    
142
  switch(ifa->autype)
143
  {
144
    case OSPF_AUTH_NONE:
145
      return 1;
146
      break;
147
    case OSPF_AUTH_SIMPLE:
148
      pass = password_find(ifa->passwords, 1);
149
      if (!pass)
150
      {
151
        OSPF_TRACE(D_PACKETS, "OSPF_auth: no password found");
152
        return 0;
153
      }
154
      password_cpy(password, pass->password, sizeof(union ospf_auth));
155

    
156
      if (memcmp(pkt->u.password, password, sizeof(union ospf_auth)))
157
      {
158
        char ppass[sizeof(union ospf_auth) + 1];
159
        bzero(ppass, (sizeof(union ospf_auth) + 1));
160
        memcpy(ppass, pkt->u.password, sizeof(union ospf_auth));
161
        OSPF_TRACE(D_PACKETS, "OSPF_auth: different passwords (%s)", ppass);
162
        return 0;
163
      }
164
      return 1;
165
      break;
166
    case OSPF_AUTH_CRYPT:
167
      if (pkt->u.md5.len != OSPF_AUTH_CRYPT_SIZE)
168
      {
169
        OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong size of md5 digest");
170
        return 0;
171
      }
172

    
173
      if (ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE > size)
174
      {
175
        OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch (%d vs %d)",
176
          ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE, size);
177
        return 0;
178
      }
179

    
180
      tail = ((void *)pkt) + ntohs(pkt->length);
181

    
182
      if (ifa->passwords)
183
      {
184
        WALK_LIST(ptmp, *(ifa->passwords))
185
        {
186
          if (pkt->u.md5.keyid != ptmp->id) continue;
187
          if ((ptmp->accfrom > now_real) || (ptmp->accto < now_real)) continue;
188
          pass = ptmp;
189
          break;
190
        }
191
      }
192

    
193
      if (!pass)
194
      {
195
        OSPF_TRACE(D_PACKETS, "OSPF_auth: no suitable md5 password found");
196
        return 0;
197
      }
198

    
199
      if (n)
200
      {
201
        u32 rcv_csn = ntohl(pkt->u.md5.csn);
202
        if(rcv_csn < n->csn)
203
        {
204
          OSPF_TRACE(D_PACKETS, "OSPF_auth: lower sequence number (rcv %d, old %d)", rcv_csn, n->csn);
205
          return 0;
206
        }
207

    
208
        n->csn = rcv_csn;
209
      }
210

    
211
      MD5Init(&ctxt);
212
      MD5Update(&ctxt, (char *) pkt, ntohs(pkt->length));
213
      password_cpy(password, pass->password, OSPF_AUTH_CRYPT_SIZE);
214
      MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
215
      MD5Final(md5sum, &ctxt);
216
      if (memcmp(md5sum, tail, OSPF_AUTH_CRYPT_SIZE))
217
      {
218
        OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong md5 digest");
219
        return 0;
220
      }
221
      return 1;
222
      break;
223
    default:
224
      OSPF_TRACE(D_PACKETS, "OSPF_auth: unknown auth type");
225
      return 0;
226
  }
227
}
228

    
229
#else
230

    
231
/* OSPFv3 authentication not yet supported */
232

    
233
static inline void
234
ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
235
{ }
236

    
237
static int
238
ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size)
239
{ return 1; }
240
 
241
#endif
242

    
243

    
244
/**
245
 * ospf_rx_hook
246
 * @sk: socket we received the packet.
247
 * @size: size of the packet
248
 *
249
 * This is the entry point for messages from neighbors. Many checks (like
250
 * authentication, checksums, size) are done before the packet is passed to
251
 * non generic functions.
252
 */
253
int
254
ospf_rx_hook(sock *sk, int size)
255
{
256
  char *mesg = "OSPF: Bad packet from ";
257

    
258
  /* We want just packets from sk->iface. Unfortunately, on BSD we
259
     cannot filter out other packets at kernel level and we receive
260
     all packets on all sockets */
261
  if (sk->lifindex != sk->iface->index)
262
    return 1;
263

    
264
  DBG("OSPF: RX hook called (iface %s, src %I, dst %I)\n",
265
      sk->ifname, sk->faddr, sk->laddr);
266

    
267
  /* Initially, the packet is associated with the 'master' iface */
268
  struct ospf_iface *ifa = sk->data;
269
  struct proto_ospf *po = ifa->oa->po;
270
  // struct proto *p = &po->proto;
271

    
272
  int src_local, dst_local UNUSED, dst_mcast; 
273
  src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
274
  dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
275
  dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, AllDRouters);
276

    
277
#ifdef OSPFv2
278
  /* First, we eliminate packets with strange address combinations.
279
   * In OSPFv2, they might be for other ospf_ifaces (with different IP
280
   * prefix) on the same real iface, so we don't log it. We enforce
281
   * that (src_local || dst_local), therefore we are eliminating all
282
   * such cases. 
283
   */
284
  if (dst_mcast && !src_local)
285
    return 1;
286
  if (!dst_mcast && !dst_local)
287
    return 1;
288

    
289
  /* Ignore my own broadcast packets */
290
  if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
291
    return 1;
292
#else /* OSPFv3 */
293

    
294
  /* In OSPFv3, src_local and dst_local mean link-local. 
295
   * RFC 5340 says that local (non-vlink) packets use
296
   * link-local src address, but does not enforce it. Strange.
297
   */
298
  if (dst_mcast && !src_local)
299
    log(L_WARN "OSPF: Received multicast packet from %I (not link-local)", sk->faddr);
300
#endif
301

    
302
  /* Second, we check packet size, checksum, and the protocol version */
303
  struct ospf_packet *ps = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size);
304

    
305
  if (ps == NULL)
306
  {
307
    log(L_ERR "%s%I - bad IP header", mesg, sk->faddr);
308
    return 1;
309
  }
310

    
311
  if (ifa->check_ttl && (sk->ttl < 255))
312
  {
313
    log(L_ERR "%s%I - TTL %d (< 255)", mesg, sk->faddr, sk->ttl);
314
    return 1;
315
  }
316

    
317
  if ((unsigned) size < sizeof(struct ospf_packet))
318
  {
319
    log(L_ERR "%s%I - too short (%u bytes)", mesg, sk->faddr, size);
320
    return 1;
321
  }
322

    
323
  uint plen = ntohs(ps->length);
324
  if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0))
325
  {
326
    log(L_ERR "%s%I - invalid length (%u)", mesg, sk->faddr, plen);
327
    return 1;
328
  }
329

    
330
  if (sk->flags & SKF_TRUNCATED)
331
  {
332
    log(L_WARN "%s%I - too large (%d/%d)", mesg, sk->faddr, plen, size);
333

    
334
    /* If we have dynamic buffers and received truncated message, we expand RX buffer */
335

    
336
    uint bs = plen + 256;
337
    bs = BIRD_ALIGN(bs, 1024);
338

    
339
    if (!ifa->cf->rx_buffer && (bs > sk->rbsize))
340
      sk_set_rbsize(sk, bs);
341

    
342
    return 1;
343
  }
344

    
345
  if (plen > size)
346
  {
347
    log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, plen, size);
348
    return 1;
349
  }
350

    
351
  if (ps->version != OSPF_VERSION)
352
  {
353
    log(L_ERR "%s%I - version %u", mesg, sk->faddr, ps->version);
354
    return 1;
355
  }
356

    
357
#ifdef OSPFv2
358
  if ((ps->autype != htons(OSPF_AUTH_CRYPT)) &&
359
      (!ipsum_verify(ps, 16, (void *) ps + sizeof(struct ospf_packet),
360
                     plen - sizeof(struct ospf_packet), NULL)))
361
  {
362
    log(L_ERR "%s%I - bad checksum", mesg, sk->faddr);
363
    return 1;
364
  }
365
#endif
366

    
367

    
368
  /* Third, we resolve associated iface and handle vlinks. */
369

    
370
  u32 areaid = ntohl(ps->areaid);
371
  u32 rid = ntohl(ps->routerid);
372

    
373
  if ((areaid == ifa->oa->areaid)
374
#ifdef OSPFv3
375
      && (ps->instance_id == ifa->instance_id)
376
#endif
377
      )
378
  {
379
    /* It is real iface, source should be local (in OSPFv2) */
380
#ifdef OSPFv2
381
    if (!src_local)
382
      return 1;
383
#endif
384
  }
385
  else if (dst_mcast || (areaid != 0))
386
  {
387
    /* Obvious mismatch */
388

    
389
#ifdef OSPFv2
390
    /* We ignore mismatch in OSPFv3, because there might be
391
       other instance with different instance ID */
392
    log(L_ERR "%s%I - area does not match (%R vs %R)",
393
        mesg, sk->faddr, areaid, ifa->oa->areaid);
394
#endif
395
    return 1;
396
  }
397
  else
398
  {
399
    /* Some vlink? */
400
    struct ospf_iface *iff = NULL;
401

    
402
    WALK_LIST(iff, po->iface_list)
403
    {
404
      if ((iff->type == OSPF_IT_VLINK) && 
405
          (iff->voa == ifa->oa) &&
406
#ifdef OSPFv3
407
          (iff->instance_id == ps->instance_id) &&
408
#endif
409
          (iff->vid == rid))
410
        {
411
          /* Vlink should be UP */
412
          if (iff->state != OSPF_IS_PTP)
413
            return 1;
414
          
415
          ifa = iff;
416
          goto found;
417
        }
418
    }
419

    
420
#ifdef OSPFv2
421
    log(L_WARN "OSPF: Received packet for unknown vlink (ID %R, IP %I)", rid, sk->faddr);
422
#endif
423
    return 1;
424
  }
425

    
426
 found:
427
  if (ifa->stub)            /* This shouldn't happen */
428
    return 1;
429

    
430
  if (ipa_equal(sk->laddr, AllDRouters) && (ifa->sk_dr == 0))
431
    return 1;
432

    
433
  if (rid == po->router_id)
434
  {
435
    log(L_ERR "%s%I - received my own router ID!", mesg, sk->faddr);
436
    return 1;
437
  }
438

    
439
  if (rid == 0)
440
  {
441
    log(L_ERR "%s%I - router id = 0.0.0.0", mesg, sk->faddr);
442
    return 1;
443
  }
444

    
445
#ifdef OSPFv2
446
  /* In OSPFv2, neighbors are identified by either IP or Router ID, base on network type */
447
  struct ospf_neighbor *n;
448
  if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
449
    n = find_neigh_by_ip(ifa, sk->faddr);
450
  else
451
    n = find_neigh(ifa, rid);
452
#else
453
  struct ospf_neighbor *n = find_neigh(ifa, rid);
454
#endif
455

    
456
  if(!n && (ps->type != HELLO_P))
457
  {
458
    log(L_WARN "OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)",
459
        sk->faddr, ifa->ifname);
460
    return 1;
461
  }
462

    
463
  if (!ospf_pkt_checkauth(n, ifa, ps, size))
464
  {
465
    log(L_ERR "%s%I - authentication failed", mesg, sk->faddr);
466
    return 1;
467
  }
468

    
469
  /* Dump packet 
470
     pu8=(u8 *)(sk->rbuf+5*4);
471
     for(i=0;i<ntohs(ps->length);i+=4)
472
     DBG("%s: received %u,%u,%u,%u\n",p->name, pu8[i+0], pu8[i+1], pu8[i+2],
473
     pu8[i+3]);
474
     DBG("%s: received size: %u\n",p->name,size);
475
   */
476

    
477
  switch (ps->type)
478
  {
479
  case HELLO_P:
480
    DBG("%s: Hello received.\n", p->name);
481
    ospf_hello_receive(ps, ifa, n, sk->faddr);
482
    break;
483
  case DBDES_P:
484
    DBG("%s: Database description received.\n", p->name);
485
    ospf_dbdes_receive(ps, ifa, n);
486
    break;
487
  case LSREQ_P:
488
    DBG("%s: Link state request received.\n", p->name);
489
    ospf_lsreq_receive(ps, ifa, n);
490
    break;
491
  case LSUPD_P:
492
    DBG("%s: Link state update received.\n", p->name);
493
    ospf_lsupd_receive(ps, ifa, n);
494
    break;
495
  case LSACK_P:
496
    DBG("%s: Link state ack received.\n", p->name);
497
    ospf_lsack_receive(ps, ifa, n);
498
    break;
499
  default:
500
    log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, ps->type);
501
    return 1;
502
  };
503
  return 1;
504
}
505

    
506
/*
507
void
508
ospf_tx_hook(sock * sk)
509
{
510
  struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
511
//  struct proto *p = (struct proto *) (ifa->oa->po);
512
  log(L_ERR "OSPF: TX hook called on %s", ifa->ifname);
513
}
514
*/
515

    
516
void
517
ospf_err_hook(sock * sk, int err)
518
{
519
  struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
520
  struct proto *p = &(ifa->oa->po->proto);
521
  log(L_ERR "%s: Socket error on %s: %M", p->name, ifa->ifname, err);
522
}
523

    
524
void
525
ospf_verr_hook(sock *sk, int err)
526
{
527
  struct proto_ospf *po = (struct proto_ospf *) (sk->data);
528
  struct proto *p =  &po->proto;
529
  log(L_ERR "%s: Vlink socket error: %M", p->name, err);
530
}
531

    
532
void
533
ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
534
{
535
  struct ospf_neighbor *n;
536

    
537
  WALK_LIST(n, ifa->neigh_list)
538
    if (n->state >= state)
539
      ospf_send_to(ifa, n->ip);
540
}
541

    
542
void
543
ospf_send_to_bdr(struct ospf_iface *ifa)
544
{
545
  if (!ipa_equal(ifa->drip, IPA_NONE))
546
    ospf_send_to(ifa, ifa->drip);
547
  if (!ipa_equal(ifa->bdrip, IPA_NONE))
548
    ospf_send_to(ifa, ifa->bdrip);
549
}
550

    
551
void
552
ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
553
{
554
  sock *sk = ifa->sk;
555
  struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
556
  int len = ntohs(pkt->length);
557

    
558
#ifdef OSPFv2
559
  if (ifa->autype == OSPF_AUTH_CRYPT)
560
    len += OSPF_AUTH_CRYPT_SIZE;
561
#endif
562

    
563
  ospf_pkt_finalize(ifa, pkt);
564

    
565
  int done = sk_send_to(sk, len, dst, 0);
566
  if (!done)
567
    log(L_WARN "OSPF: TX queue full on %s", ifa->ifname);
568
}
569