Statistics
| Branch: | Revision:

iof-bird-daemon / proto / ospf / packet.c @ 1155c792

History | View | Annotate | Download (13.4 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 mtu = (ifa->type == OSPF_IT_VLINK) ? OSPF_VLINK_MTU : ifa->iface->mtu;
43
  unsigned headers = SIZE_OF_IP_HEADER;
44

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

    
50
  return mtu - headers;
51
}
52

    
53
#ifdef OSPFv2
54

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

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

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

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

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

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

    
107
      ifa->csn_use = now;
108

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

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

    
136

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

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

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

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

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

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

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

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

    
209
        n->csn = rcv_csn;
210
      }
211

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

    
230
#else
231

    
232
/* OSPFv3 authentication not yet supported */
233

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

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

    
244

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

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

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

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

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

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

    
290
#else /* OSPFv3 */
291

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

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

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

    
309
  if ((unsigned) size < sizeof(struct ospf_packet))
310
  {
311
    log(L_ERR "%s%I - too short (%u bytes)", mesg, sk->faddr, size);
312
    return 1;
313
  }
314

    
315
  int osize = ntohs(ps->length);
316
  if ((unsigned) osize < sizeof(struct ospf_packet))
317
  {
318
    log(L_ERR "%s%I - too low value in size field (%u bytes)", mesg, sk->faddr, osize);
319
    return 1;
320
  }
321

    
322
  if ((osize > size) || ((osize % 4) != 0))
323
  {
324
    log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, osize, size);
325
    return 1;
326
  }
327

    
328
  if ((unsigned) size > sk->rbsize)
329
  {
330
    log(L_ERR "%s%I - too large (%d vs %d)", mesg, sk->faddr, size, sk->rbsize);
331
    return 1;
332
  }
333

    
334
  if (ps->version != OSPF_VERSION)
335
  {
336
    log(L_ERR "%s%I - version %u", mesg, sk->faddr, ps->version);
337
    return 1;
338
  }
339

    
340
#ifdef OSPFv2
341
  if ((ps->autype != htons(OSPF_AUTH_CRYPT)) &&
342
      (!ipsum_verify(ps, 16, (void *) ps + sizeof(struct ospf_packet),
343
                     osize - sizeof(struct ospf_packet), NULL)))
344
  {
345
    log(L_ERR "%s%I - bad checksum", mesg, sk->faddr);
346
    return 1;
347
  }
348
#endif
349

    
350

    
351
  /* Third, we resolve associated iface and handle vlinks. */
352

    
353
  u32 areaid = ntohl(ps->areaid);
354
  u32 rid = ntohl(ps->routerid);
355

    
356
  if ((areaid == ifa->oa->areaid)
357
#ifdef OSPFv3
358
      && (ps->instance_id == ifa->instance_id)
359
#endif
360
      )
361
  {
362
    /* It is real iface, source should be local (in OSPFv2) */
363
#ifdef OSPFv2
364
    if (!src_local)
365
      return 1;
366
#endif
367
  }
368
  else if (dst_mcast || (areaid != 0))
369
  {
370
    /* Obvious mismatch */
371

    
372
#ifdef OSPFv2
373
    /* We ignore mismatch in OSPFv3, because there might be
374
       other instance with different instance ID */
375
    log(L_ERR "%s%I - area does not match (%R vs %R)",
376
        mesg, sk->faddr, areaid, ifa->oa->areaid);
377
#endif
378
    return 1;
379
  }
380
  else
381
  {
382
    /* Some vlink? */
383
    struct ospf_iface *iff = NULL;
384

    
385
    WALK_LIST(iff, po->iface_list)
386
    {
387
      if ((iff->type == OSPF_IT_VLINK) && 
388
          (iff->voa == ifa->oa) &&
389
#ifdef OSPFv3
390
          (iff->instance_id == ps->instance_id) &&
391
#endif
392
          (iff->vid == rid))
393
        {
394
          /* Vlink should be UP */
395
          if (iff->state != OSPF_IS_PTP)
396
            return 1;
397
          
398
          ifa = iff;
399
          goto found;
400
        }
401
    }
402

    
403
#ifdef OSPFv2
404
    log(L_WARN "OSPF: Received packet for unknown vlink (ID %R, IP %I)", rid, sk->faddr);
405
#endif
406
    return 1;
407
  }
408

    
409
 found:
410
  if (ifa->stub)            /* This shouldn't happen */
411
    return 1;
412

    
413
  if (ipa_equal(sk->laddr, AllDRouters) && (ifa->sk_dr == 0))
414
    return 1;
415

    
416
  if (rid == po->router_id)
417
  {
418
    log(L_ERR "%s%I - received my own router ID!", mesg, sk->faddr);
419
    return 1;
420
  }
421

    
422
  if (rid == 0)
423
  {
424
    log(L_ERR "%s%I - router id = 0.0.0.0", mesg, sk->faddr);
425
    return 1;
426
  }
427

    
428
#ifdef OSPFv2
429
  /* In OSPFv2, neighbors are identified by either IP or Router ID, base on network type */
430
  struct ospf_neighbor *n;
431
  if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
432
    n = find_neigh_by_ip(ifa, sk->faddr);
433
  else
434
    n = find_neigh(ifa, rid);
435
#else
436
  struct ospf_neighbor *n = find_neigh(ifa, rid);
437
#endif
438

    
439
  if(!n && (ps->type != HELLO_P))
440
  {
441
    log(L_WARN "OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)",
442
        sk->faddr, ifa->iface->name);
443
    return 1;
444
  }
445

    
446
  if (!ospf_pkt_checkauth(n, ifa, ps, size))
447
  {
448
    log(L_ERR "%s%I - authentication failed", mesg, sk->faddr);
449
    return 1;
450
  }
451

    
452
  /* Dump packet 
453
     pu8=(u8 *)(sk->rbuf+5*4);
454
     for(i=0;i<ntohs(ps->length);i+=4)
455
     DBG("%s: received %u,%u,%u,%u\n",p->name, pu8[i+0], pu8[i+1], pu8[i+2],
456
     pu8[i+3]);
457
     DBG("%s: received size: %u\n",p->name,size);
458
   */
459

    
460
  switch (ps->type)
461
  {
462
  case HELLO_P:
463
    DBG("%s: Hello received.\n", p->name);
464
    ospf_hello_receive(ps, ifa, n, sk->faddr);
465
    break;
466
  case DBDES_P:
467
    DBG("%s: Database description received.\n", p->name);
468
    ospf_dbdes_receive(ps, ifa, n);
469
    break;
470
  case LSREQ_P:
471
    DBG("%s: Link state request received.\n", p->name);
472
    ospf_lsreq_receive(ps, ifa, n);
473
    break;
474
  case LSUPD_P:
475
    DBG("%s: Link state update received.\n", p->name);
476
    ospf_lsupd_receive(ps, ifa, n);
477
    break;
478
  case LSACK_P:
479
    DBG("%s: Link state ack received.\n", p->name);
480
    ospf_lsack_receive(ps, ifa, n);
481
    break;
482
  default:
483
    log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, ps->type);
484
    return 1;
485
  };
486
  return 1;
487
}
488

    
489
void
490
ospf_tx_hook(sock * sk)
491
{
492
//  struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
493
//  struct proto *p = (struct proto *) (ifa->oa->po);
494
  log(L_ERR "OSPF: TX_Hook called");
495
}
496

    
497
void
498
ospf_err_hook(sock * sk, int err)
499
{
500
//  struct ospf_iface *ifa= (struct ospf_iface *) (sk->data);
501
//  struct proto *p = (struct proto *) (ifa->oa->po);
502
  log(L_ERR "OSPF: Socket error: %m", err);
503
}
504

    
505
void
506
ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
507
{
508
  struct ospf_neighbor *n;
509

    
510
  WALK_LIST(n, ifa->neigh_list)
511
    if (n->state >= state)
512
      ospf_send_to(ifa, n->ip);
513
}
514

    
515
void
516
ospf_send_to_bdr(struct ospf_iface *ifa)
517
{
518
  if (!ipa_equal(ifa->drip, IPA_NONE))
519
    ospf_send_to(ifa, ifa->drip);
520
  if (!ipa_equal(ifa->bdrip, IPA_NONE))
521
    ospf_send_to(ifa, ifa->bdrip);
522
}
523

    
524
void
525
ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
526
{
527
  sock *sk = ifa->sk;
528
  struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
529
  int len = ntohs(pkt->length);
530

    
531
#ifdef OSPFv2
532
  if (ifa->autype == OSPF_AUTH_CRYPT)
533
    len += OSPF_AUTH_CRYPT_SIZE;
534
#endif
535

    
536
  ospf_pkt_finalize(ifa, pkt);
537
  if (sk->tbuf != sk->tpos)
538
    log(L_ERR "Aiee, old packet was overwritten in TX buffer");
539

    
540
  sk_send_to(sk, len, dst, 0);
541
}
542