Revision 11cb6202 proto/bgp/packets.c

View differences:

proto/bgp/packets.c
12 12
#include "nest/iface.h"
13 13
#include "nest/protocol.h"
14 14
#include "nest/route.h"
15
#include "nest/attrs.h"
15 16
#include "conf/conf.h"
16 17
#include "lib/unaligned.h"
17 18
#include "lib/socket.h"
......
30 31
  return buf + 2 + conn->notify_size;
31 32
}
32 33

  
34
#ifdef IPV6
35
static byte *
36
bgp_put_cap_ipv6(struct bgp_conn *conn UNUSED, byte *buf)
37
{
38
  *buf++ = 1;		/* Capability 1: Multiprotocol extensions */
39
  *buf++ = 4;		/* Capability data length */
40
  *buf++ = 0;		/* We support AF IPv6 */
41
  *buf++ = BGP_AF_IPV6;
42
  *buf++ = 0;		/* RFU */
43
  *buf++ = 1;		/* and SAFI 1 */
44
  return buf;
45
}
46
#endif
47

  
48
static byte *
49
bgp_put_cap_as4(struct bgp_conn *conn, byte *buf)
50
{
51
  *buf++ = 65;		/* Capability 65: Support for 4-octet AS number */
52
  *buf++ = 4;		/* Capability data length */
53
  put_u32(buf, conn->bgp->local_as);
54
  return buf + 4;
55
}
56

  
33 57
static byte *
34 58
bgp_create_open(struct bgp_conn *conn, byte *buf)
35 59
{
36 60
  struct bgp_proto *p = conn->bgp;
61
  byte *cap;
62
  int cap_len;
37 63

  
38 64
  BGP_TRACE(D_PACKETS, "Sending OPEN(ver=%d,as=%d,hold=%d,id=%08x)",
39 65
	    BGP_VERSION, p->local_as, p->cf->hold_time, p->local_id);
40 66
  buf[0] = BGP_VERSION;
41
  put_u16(buf+1, p->local_as);
67
  put_u16(buf+1, (p->local_as < 0xFFFF) ? p->local_as : AS_TRANS);
42 68
  put_u16(buf+3, p->cf->hold_time);
43 69
  put_u32(buf+5, p->local_id);
44
#ifndef IPV6
45
  buf[9] = 0;				/* No optional parameters */
46
  return buf+10;
47
#else
48
  buf += 9;
49
  *buf++ = 8;		/* Optional params len */
50
  *buf++ = 2;		/* Option: Capability list */
51
  *buf++ = 6;		/* Option length */
52
  *buf++ = 1;		/* Capability 1: Multiprotocol extensions */
53
  *buf++ = 4;		/* Capability data length */
54
  *buf++ = 0;		/* We support AF IPv6 */
55
  *buf++ = BGP_AF_IPV6;
56
  *buf++ = 0;		/* RFU */
57
  *buf++ = 1;		/* and SAFI 1 */
58
  return buf;
70
  /* Skipped 3 B for length field and Capabilities parameter header */
71
  cap = buf + 12;
72

  
73
#ifdef IPV6
74
  cap = bgp_put_cap_ipv6(conn, cap);
59 75
#endif
76
  if (bgp_as4_support)
77
    cap = bgp_put_cap_as4(conn, cap);
78

  
79
  cap_len = cap - buf - 12;
80
  if (cap_len > 0)
81
    {
82
      buf[9]  = cap_len + 2;	/* Optional params len */
83
      buf[10] = 2;		/* Option: Capability list */
84
      buf[11] = cap_len;	/* Option length */
85
      return cap;
86
    }
87
  else
88
    {
89
      buf[9] = 0;		/* No optional parameters */
90
      return buf + 10;
91
    }
60 92
}
61 93

  
62 94
static unsigned int
......
118 150
	      continue;
119 151
	    }
120 152
	  DBG("Processing bucket %p\n", buck);
121
	  a_size = bgp_encode_attrs(w+2, buck->eattrs, 1024);
153
	  a_size = bgp_encode_attrs(p, w+2, buck->eattrs, 1024);
122 154
	  put_u16(w, a_size);
123 155
	  w += a_size + 2;
124 156
	  r_size = bgp_encode_prefixes(p, w, buck, remains - a_size);
......
166 198
      *tmp++ = BGP_AF_IPV6;
167 199
      *tmp++ = 1;
168 200
      ea->attrs[0].u.ptr->length = bgp_encode_prefixes(p, tmp, buck, remains-11);
169
      size = bgp_encode_attrs(w, ea, remains);
201
      size = bgp_encode_attrs(p, w, ea, remains);
170 202
      w += size;
171 203
      remains -= size;
172 204
    }
......
183 215
	      continue;
184 216
	    }
185 217
	  DBG("Processing bucket %p\n", buck);
186
	  size = bgp_encode_attrs(w, buck->eattrs, 1024);
218
	  size = bgp_encode_attrs(p, w, buck->eattrs, 1024);
187 219
	  w += size;
188 220
	  remains -= size;
189 221
	  tstart = tmp = bgp_attach_attr(&ea, bgp_linpool, BA_MP_REACH_NLRI, remains-8);
......
230 262
	  *tmp++ = 0;			/* No SNPA information */
231 263
	  tmp += bgp_encode_prefixes(p, tmp, buck, remains - (8+3+32+1));
232 264
	  ea->attrs[0].u.ptr->length = tmp - tstart;
233
	  w += bgp_encode_attrs(w, ea, remains);
265
	  w += bgp_encode_attrs(p, w, ea, remains);
234 266
	  break;
235 267
	}
236 268
    }
......
353 385
    ;
354 386
}
355 387

  
388
/* Capatibility negotiation as per RFC 2842 */
389

  
390
void
391
bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
392
{
393
  struct bgp_proto *p = conn->bgp;
394
  int cl;
395
  u32 as;
396

  
397
  while (len > 0)
398
    {
399
      if (len < 2 || len < 2 + opt[1])
400
	goto err;
401
      
402
      cl = opt[1];
403

  
404
      switch (opt[0])
405
	{
406
	case 65:
407
	  if (cl != 4)
408
	    goto err;
409
	  p->as4_support = 1;
410
	  if (bgp_as4_support)
411
	    conn->advertised_as = get_u32(opt + 2);
412
	  break;
413

  
414
	  /* We can safely ignore all other capabilities */
415
	}
416
      len -= 2 + cl;
417
      opt += 2 + cl;
418
    }
419
  return;
420

  
421
    err:
422
  bgp_error(conn, 2, 0, NULL, 0);
423
  return;
424
}
425

  
356 426
static int
357 427
bgp_parse_options(struct bgp_conn *conn, byte *opt, int len)
358 428
{
429
  int ol;
430

  
359 431
  while (len > 0)
360 432
    {
361 433
      if (len < 2 || len < 2 + opt[1])
......
369 441
	DBG("\n");
370 442
      }
371 443
#endif
444

  
445
      ol = opt[1];
372 446
      switch (opt[0])
373 447
	{
374 448
	case 2:
375
	  /* Capatibility negotiation as per RFC 2842 */
376
	  /* We can safely ignore all capabilities announced */
449
	  bgp_parse_capabilities(conn, opt + 2, ol);
377 450
	  break;
451

  
378 452
	default:
379 453
	  /*
380 454
	   *  BGP specs don't tell us to send which option
......
382 456
	   *  to do so. Also, capability negotiation with
383 457
	   *  Cisco routers doesn't work without that.
384 458
	   */
385
	  bgp_error(conn, 2, 4, opt, opt[1]);
459
	  bgp_error(conn, 2, 4, opt, ol);
386 460
	  return 0;
387 461
	}
388
      len -= 2 + opt[1];
389
      opt += 2 + opt[1];
462
      len -= 2 + ol;
463
      opt += 2 + ol;
390 464
    }
391 465
  return 0;
392 466
}
......
397 471
  struct bgp_conn *other;
398 472
  struct bgp_proto *p = conn->bgp;
399 473
  struct bgp_config *cf = p->cf;
400
  unsigned as, hold;
474
  unsigned hold;
401 475
  u32 id;
402 476

  
403 477
  /* Check state */
......
409 483
    { bgp_error(conn, 1, 2, pkt+16, 2); return; }
410 484
  if (pkt[19] != BGP_VERSION)
411 485
    { bgp_error(conn, 2, 1, pkt+19, 1); return; } /* RFC 1771 says 16 bits, draft-09 tells to use 8 */
412
  as = get_u16(pkt+20);
486
  conn->advertised_as = get_u16(pkt+20);
413 487
  hold = get_u16(pkt+22);
414 488
  id = get_u32(pkt+24);
415
  BGP_TRACE(D_PACKETS, "Got OPEN(as=%d,hold=%d,id=%08x)", as, hold, id);
416
  if (cf->remote_as && as != p->remote_as)
417
    { bgp_error(conn, 2, 2, pkt+20, -2); return; }
418
  if (hold > 0 && hold < 3)
419
    { bgp_error(conn, 2, 6, pkt+22, 2); return; }
420
  p->remote_id = id;
489
  BGP_TRACE(D_PACKETS, "Got OPEN(as=%d,hold=%d,id=%08x)", conn->advertised_as, hold, id);
490

  
491
  p->remote_id = id; // ???
421 492
  if (bgp_parse_options(conn, pkt+29, pkt[28]))
422 493
    return;
494

  
495
  if (hold > 0 && hold < 3)
496
    { bgp_error(conn, 2, 6, pkt+22, 2); return; }
497

  
423 498
  if (!id || id == 0xffffffff || id == p->local_id)
424 499
    { bgp_error(conn, 2, 3, pkt+24, -4); return; }
425 500

  
501

  
502
  if (conn->advertised_as != p->remote_as)
503
    {
504
      bgp_error(conn, 2, 2, (byte *) &(conn->advertised_as), -4); return;
505
    }
506

  
426 507
  /* Check the other connection */
427 508
  other = (conn == &p->outgoing_conn) ? &p->incoming_conn : &p->outgoing_conn;
428 509
  switch (other->state)
......
463 544
  else
464 545
    conn->hold_time = p->cf->hold_time;
465 546
  conn->keepalive_time = p->cf->keepalive_time ? : conn->hold_time / 3;
466
  p->remote_as = as;
547
  // p->remote_as = conn->advertised_as;
467 548
  p->remote_id = id;
468 549
  DBG("BGP: Hold timer set to %d, keepalive to %d, AS to %d, ID to %x\n", conn->hold_time, conn->keepalive_time, p->remote_as, p->remote_id);
469 550

  
......
720 801
  { 2, 4, "Unsupported optional parameter" },
721 802
  { 2, 5, "Authentication failure" },
722 803
  { 2, 6, "Unacceptable hold time" },
723
  { 2, 7, "Required capability missing" }, /* capability negotiation draft */
804
  { 2, 7, "Required capability missing" }, /* [RFC3392] */
724 805
  { 3, 0, "Invalid UPDATE message" },
725 806
  { 3, 1, "Malformed attribute list" },
726 807
  { 3, 2, "Unrecognized well-known attribute" },

Also available in: Unified diff