packets.c 55.5 KB
Newer Older
1 2 3 4
/*
 *	BIRD -- BGP Packet Processing
 *
 *	(c) 2000 Martin Mares <mj@ucw.cz>
Ondřej Zajíček's avatar
Ondřej Zajíček committed
5 6
 *	(c) 2008--2016 Ondrej Zajicek <santiago@crfreenet.org>
 *	(c) 2008--2016 CZ.NIC z.s.p.o.
7 8 9 10
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

Martin Mareš's avatar
Martin Mareš committed
11
#undef LOCAL_DEBUG
12

Ondřej Zajíček's avatar
Ondřej Zajíček committed
13 14
#include <stdlib.h>

15 16 17 18
#include "nest/bird.h"
#include "nest/iface.h"
#include "nest/protocol.h"
#include "nest/route.h"
19
#include "nest/attrs.h"
20
#include "nest/mrtdump.h"
21
#include "conf/conf.h"
22
#include "lib/unaligned.h"
23
#include "lib/flowspec.h"
24
#include "lib/socket.h"
25

Ondřej Zajíček's avatar
Ondřej Zajíček committed
26 27
#include "nest/cli.h"

28
#include "bgp.h"
29

30 31 32 33 34 35

#define BGP_RR_REQUEST		0
#define BGP_RR_BEGIN		1
#define BGP_RR_END		2


36 37
static struct tbf rl_rcv_update = TBF_DEFAULT_LOG_LIMITS;
static struct tbf rl_snd_update = TBF_DEFAULT_LOG_LIMITS;
38

39 40 41 42 43 44 45
/* Table for state -> RFC 6608 FSM error subcodes */
static byte fsm_err_subcode[BS_MAX] = {
  [BS_OPENSENT] = 1,
  [BS_OPENCONFIRM] = 2,
  [BS_ESTABLISHED] = 3
};

Ondřej Zajíček's avatar
Ondřej Zajíček committed
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

static struct bgp_channel *
bgp_get_channel(struct bgp_proto *p, u32 afi)
{
  uint i;

  for (i = 0; i < p->channel_count; i++)
    if (p->afi_map[i] == afi)
      return p->channel_map[i];

  return NULL;
}

static inline void
put_af3(byte *buf, u32 id)
{
  put_u16(buf, id >> 16);
  buf[2] = id & 0xff;
}

static inline void
put_af4(byte *buf, u32 id)
{
  put_u16(buf, id >> 16);
  buf[2] = 0;
  buf[3] = id & 0xff;
}

static inline u32
get_af3(byte *buf)
{
  return (get_u16(buf) << 16) | buf[2];
}

static inline u32
get_af4(byte *buf)
{
  return (get_u16(buf) << 16) | buf[3];
}

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
/*
 * MRT Dump format is not semantically specified.
 * We will use these values in appropriate fields:
 *
 * Local AS, Remote AS - configured AS numbers for given BGP instance.
 * Local IP, Remote IP - IP addresses of the TCP connection (0 if no connection)
 *
 * We dump two kinds of MRT messages: STATE_CHANGE (for BGP state
 * changes) and MESSAGE (for received BGP messages).
 *
 * STATE_CHANGE uses always AS4 variant, but MESSAGE uses AS4 variant
 * only when AS4 session is established and even in that case MESSAGE
 * does not use AS4 variant for initial OPEN message. This strange
 * behavior is here for compatibility with Quagga and Bgpdump,
 */

static byte *
mrt_put_bgp4_hdr(byte *buf, struct bgp_conn *conn, int as4)
{
  struct bgp_proto *p = conn->bgp;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
106
  uint v4 = ipa_is_ip4(p->cf->remote_ip);
107 108

  if (as4)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
109 110 111 112 113
  {
    put_u32(buf+0, p->remote_as);
    put_u32(buf+4, p->public_as);
    buf+=8;
  }
114
  else
Ondřej Zajíček's avatar
Ondřej Zajíček committed
115 116 117 118 119
  {
    put_u16(buf+0, (p->remote_as <= 0xFFFF) ? p->remote_as : AS_TRANS);
    put_u16(buf+2, (p->public_as <= 0xFFFF) ? p->public_as : AS_TRANS);
    buf+=4;
  }
120

121
  put_u16(buf+0, (p->neigh && p->neigh->iface) ? p->neigh->iface->index : 0);
Ondřej Zajíček's avatar
Ondřej Zajíček committed
122
  put_u16(buf+2, v4 ? BGP_AFI_IPV4 : BGP_AFI_IPV6);
123
  buf+=4;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
124 125 126 127 128 129 130 131 132 133 134

  if (v4)
  {
    buf = put_ip4(buf, conn->sk ? ipa_to_ip4(conn->sk->daddr) : IP4_NONE);
    buf = put_ip4(buf, conn->sk ? ipa_to_ip4(conn->sk->saddr) : IP4_NONE);
  }
  else
  {
    buf = put_ip6(buf, conn->sk ? ipa_to_ip6(conn->sk->daddr) : IP6_NONE);
    buf = put_ip6(buf, conn->sk ? ipa_to_ip6(conn->sk->saddr) : IP6_NONE);
  }
135 136 137 138 139

  return buf;
}

static void
Ondřej Zajíček's avatar
Ondřej Zajíček committed
140
mrt_dump_bgp_packet(struct bgp_conn *conn, byte *pkt, uint len)
141
{
142
  byte *buf = alloca(128+len);	/* 128 is enough for MRT headers */
143 144 145 146 147 148 149 150 151 152 153
  byte *bp = buf + MRTDUMP_HDR_LENGTH;
  int as4 = conn->bgp->as4_session;

  bp = mrt_put_bgp4_hdr(bp, conn, as4);
  memcpy(bp, pkt, len);
  bp += len;
  mrt_dump_message(&conn->bgp->p, BGP4MP, as4 ? BGP4MP_MESSAGE_AS4 : BGP4MP_MESSAGE,
		   buf, bp-buf);
}

static inline u16
Ondřej Zajíček's avatar
Ondřej Zajíček committed
154
convert_state(uint state)
155 156 157 158 159 160
{
  /* Convert state from our BS_* values to values used in MRTDump */
  return (state == BS_CLOSE) ? 1 : state + 1;
}

void
Ondřej Zajíček's avatar
Ondřej Zajíček committed
161
mrt_dump_bgp_state_change(struct bgp_conn *conn, uint old, uint new)
162 163 164 165 166 167 168 169 170 171 172
{
  byte buf[128];
  byte *bp = buf + MRTDUMP_HDR_LENGTH;

  bp = mrt_put_bgp4_hdr(bp, conn, 1);
  put_u16(bp+0, convert_state(old));
  put_u16(bp+2, convert_state(new));
  bp += 4;
  mrt_dump_message(&conn->bgp->p, BGP4MP, BGP4MP_STATE_CHANGE_AS4, buf, bp-buf);
}

173 174 175
static byte *
bgp_create_notification(struct bgp_conn *conn, byte *buf)
{
Martin Mareš's avatar
Martin Mareš committed
176 177 178
  struct bgp_proto *p = conn->bgp;

  BGP_TRACE(D_PACKETS, "Sending NOTIFICATION(code=%d.%d)", conn->notify_code, conn->notify_subcode);
179 180
  buf[0] = conn->notify_code;
  buf[1] = conn->notify_subcode;
181 182
  memcpy(buf+2, conn->notify_data, conn->notify_size);
  return buf + 2 + conn->notify_size;
183 184
}

185

Ondřej Zajíček's avatar
Ondřej Zajíček committed
186
/* Capability negotiation as per RFC 5492 */
187

Ondřej Zajíček's avatar
Ondřej Zajíček committed
188 189
const struct bgp_af_caps *
bgp_find_af_caps(struct bgp_caps *caps, u32 afi)
190
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
191
  struct bgp_af_caps *ac;
192

Ondřej Zajíček's avatar
Ondřej Zajíček committed
193 194 195 196 197
  WALK_AF_CAPS(caps, ac)
    if (ac->afi == afi)
      return ac;

  return NULL;
198 199
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
200 201
static struct bgp_af_caps *
bgp_get_af_caps(struct bgp_caps *caps, u32 afi)
202
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
203
  struct bgp_af_caps *ac;
204

Ondřej Zajíček's avatar
Ondřej Zajíček committed
205 206 207
  WALK_AF_CAPS(caps, ac)
    if (ac->afi == afi)
      return ac;
208

Ondřej Zajíček's avatar
Ondřej Zajíček committed
209 210 211
  ac = &caps->af_data[caps->af_count++];
  memset(ac, 0, sizeof(struct bgp_af_caps));
  ac->afi = afi;
212

Ondřej Zajíček's avatar
Ondřej Zajíček committed
213
  return ac;
214 215
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
216 217
static int
bgp_af_caps_cmp(const void *X, const void *Y)
218
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
219 220
  const struct bgp_af_caps *x = X, *y = Y;
  return (x->afi < y->afi) ? -1 : (x->afi > y->afi) ? 1 : 0;
221 222
}

223

224
static byte *
Ondřej Zajíček's avatar
Ondřej Zajíček committed
225
bgp_write_capabilities(struct bgp_conn *conn, byte *buf)
226
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
227 228 229 230
  struct bgp_proto *p = conn->bgp;
  struct bgp_channel *c;
  struct bgp_caps *caps;
  struct bgp_af_caps *ac;
231
  uint any_ext_next_hop = 0;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
232 233
  uint any_add_path = 0;
  byte *data;
234

Ondřej Zajíček's avatar
Ondřej Zajíček committed
235
  /* Prepare bgp_caps structure */
236

Ondřej Zajíček's avatar
Ondřej Zajíček committed
237 238 239
  int n = list_length(&p->p.channels);
  caps = mb_allocz(p->p.pool, sizeof(struct bgp_caps) + n * sizeof(struct bgp_af_caps));
  conn->local_caps = caps;
240

Ondřej Zajíček's avatar
Ondřej Zajíček committed
241 242 243 244
  caps->as4_support = p->cf->enable_as4;
  caps->ext_messages = p->cf->enable_extended_messages;
  caps->route_refresh = p->cf->enable_refresh;
  caps->enhanced_refresh = p->cf->enable_refresh;
245

Ondřej Zajíček's avatar
Ondřej Zajíček committed
246 247
  if (caps->as4_support)
    caps->as4_number = p->public_as;
248

Ondřej Zajíček's avatar
Ondřej Zajíček committed
249 250 251 252 253 254
  if (p->cf->gr_mode)
  {
    caps->gr_aware = 1;
    caps->gr_time = p->cf->gr_time;
    caps->gr_flags = p->p.gr_recovery ? BGP_GRF_RESTART : 0;
  }
255

Ondřej Zajíček's avatar
Ondřej Zajíček committed
256 257 258 259 260 261
  /* Allocate and fill per-AF fields */
  WALK_LIST(c, p->p.channels)
  {
    ac = &caps->af_data[caps->af_count++];
    ac->afi = c->afi;
    ac->ready = 1;
Martin Mareš's avatar
Martin Mareš committed
262

263 264 265
    ac->ext_next_hop = bgp_channel_is_ipv4(c) && c->cf->ext_next_hop;
    any_ext_next_hop |= ac->ext_next_hop;

Ondřej Zajíček's avatar
Ondřej Zajíček committed
266 267
    ac->add_path = c->cf->add_path;
    any_add_path |= ac->add_path;
268

Ondřej Zajíček's avatar
Ondřej Zajíček committed
269
    if (c->cf->gr_able)
270
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
271 272 273 274
      ac->gr_able = 1;

      if (p->p.gr_recovery)
	ac->gr_af_flags |= BGP_GRF_FORWARDING;
275
    }
Ondřej Zajíček's avatar
Ondřej Zajíček committed
276
  }
277

Ondřej Zajíček's avatar
Ondřej Zajíček committed
278 279
  /* Sort capability fields by AFI/SAFI */
  qsort(caps->af_data, caps->af_count, sizeof(struct bgp_af_caps), bgp_af_caps_cmp);
280

281

Ondřej Zajíček's avatar
Ondřej Zajíček committed
282
  /* Create capability list in buffer */
283

Ondřej Zajíček's avatar
Ondřej Zajíček committed
284 285 286 287 288 289
  /*
   * Note that max length is ~ 20+14*af_count. With max 6 channels that is
   * 104. Option limit is 253 and buffer size is 4096, so we cannot overflow
   * unless we add new capabilities or more AFs.
   */

Ondřej Zajíček's avatar
Ondřej Zajíček committed
290 291 292 293 294 295 296 297
  WALK_AF_CAPS(caps, ac)
    if (ac->ready)
    {
      *buf++ = 1;		/* Capability 1: Multiprotocol extensions */
      *buf++ = 4;		/* Capability data length */
      put_af4(buf, ac->afi);
      buf += 4;
    }
298

Ondřej Zajíček's avatar
Ondřej Zajíček committed
299 300 301 302 303
  if (caps->route_refresh)
  {
    *buf++ = 2;			/* Capability 2: Support for route refresh */
    *buf++ = 0;			/* Capability data length */
  }
304

305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
  if (any_ext_next_hop)
  {
    *buf++ = 5;			/* Capability 5: Support for extended next hop */
    *buf++ = 0;			/* Capability data length, will be fixed later */
    data = buf;

    WALK_AF_CAPS(caps, ac)
      if (ac->ext_next_hop)
      {
	put_af4(buf, ac->afi);
	put_u16(buf+4, BGP_AFI_IPV6);
	buf += 6;
      }

    data[-1] = buf - data;
  }

Ondřej Zajíček's avatar
Ondřej Zajíček committed
322 323 324 325 326
  if (caps->ext_messages)
  {
    *buf++ = 6;			/* Capability 6: Support for extended messages */
    *buf++ = 0;			/* Capability data length */
  }
327

Ondřej Zajíček's avatar
Ondřej Zajíček committed
328 329 330 331 332
  if (caps->gr_aware)
  {
    *buf++ = 64;		/* Capability 64: Support for graceful restart */
    *buf++ = 0;			/* Capability data length, will be fixed later */
    data = buf;
333

Ondřej Zajíček's avatar
Ondřej Zajíček committed
334 335 336
    put_u16(buf, caps->gr_time);
    buf[0] |= caps->gr_flags;
    buf += 2;
337

Ondřej Zajíček's avatar
Ondřej Zajíček committed
338 339 340 341 342 343 344
    WALK_AF_CAPS(caps, ac)
      if (ac->gr_able)
      {
	put_af3(buf, ac->afi);
	buf[3] = ac->gr_af_flags;
	buf += 4;
      }
345

Ondřej Zajíček's avatar
Ondřej Zajíček committed
346 347
    data[-1] = buf - data;
  }
348

Ondřej Zajíček's avatar
Ondřej Zajíček committed
349 350 351 352 353 354 355
  if (caps->as4_support)
  {
    *buf++ = 65;		/* Capability 65: Support for 4-octet AS number */
    *buf++ = 4;			/* Capability data length */
    put_u32(buf, p->public_as);
    buf += 4;
  }
356

Ondřej Zajíček's avatar
Ondřej Zajíček committed
357 358 359 360 361
  if (any_add_path)
  {
    *buf++ = 69;		/* Capability 69: Support for ADD-PATH */
    *buf++ = 0;			/* Capability data length, will be fixed later */
    data = buf;
362

Ondřej Zajíček's avatar
Ondřej Zajíček committed
363 364 365 366 367 368 369
    WALK_AF_CAPS(caps, ac)
      if (ac->add_path)
      {
	put_af3(buf, ac->afi);
	buf[3] = ac->add_path;
	buf += 4;
      }
370

Ondřej Zajíček's avatar
Ondřej Zajíček committed
371 372 373 374 375 376 377 378 379 380
    data[-1] = buf - data;
  }

  if (caps->enhanced_refresh)
  {
    *buf++ = 70;		/* Capability 70: Support for enhanced route refresh */
    *buf++ = 0;			/* Capability data length */
  }

  return buf;
381 382
}

383
static void
Ondřej Zajíček's avatar
Ondřej Zajíček committed
384
bgp_read_capabilities(struct bgp_conn *conn, struct bgp_caps *caps, byte *pos, int len)
385
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
386 387 388 389
  struct bgp_proto *p = conn->bgp;
  struct bgp_af_caps *ac;
  int i, cl;
  u32 af;
390

Ondřej Zajíček's avatar
Ondřej Zajíček committed
391 392 393 394
  while (len > 0)
  {
    if (len < 2 || len < (2 + pos[1]))
      goto err;
Martin Mareš's avatar
Martin Mareš committed
395

Ondřej Zajíček's avatar
Ondřej Zajíček committed
396 397
    /* Capability length */
    cl = pos[1];
398

Ondřej Zajíček's avatar
Ondřej Zajíček committed
399 400
    /* Capability type */
    switch (pos[0])
401
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417
    case  1: /* Multiprotocol capability, RFC 4760 */
      if (cl != 4)
	goto err;

      af = get_af4(pos+2);
      ac = bgp_get_af_caps(caps, af);
      ac->ready = 1;
      break;

    case  2: /* Route refresh capability, RFC 2918 */
      if (cl != 0)
	goto err;

      caps->route_refresh = 1;
      break;

418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434
    case  5: /* Extended next hop encoding capability, RFC 5549 */
      if (cl % 6)
	goto err;

      for (i = 0; i < cl; i += 6)
      {
	/* Specified only for IPv4 prefixes with IPv6 next hops */
	if ((get_u16(pos+2+i+0) != BGP_AFI_IPV4) ||
	    (get_u16(pos+2+i+4) != BGP_AFI_IPV6))
	  continue;

	af = get_af4(pos+2+i);
	ac = bgp_get_af_caps(caps, af);
	ac->ext_next_hop = 1;
      }
      break;

Ondřej Zajíček's avatar
Ondřej Zajíček committed
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
    case  6: /* Extended message length capability, RFC draft */
      if (cl != 0)
	goto err;

      caps->ext_messages = 1;
      break;

    case 64: /* Graceful restart capability, RFC 4724 */
      if (cl % 4 != 2)
	goto err;

      /* Only the last instance is valid */
      WALK_AF_CAPS(caps, ac)
      {
	ac->gr_able = 0;
	ac->gr_af_flags = 0;
      }

      caps->gr_aware = 1;
      caps->gr_flags = pos[2] & 0xf0;
      caps->gr_time = get_u16(pos + 2) & 0x0fff;

      for (i = 2; i < cl; i += 4)
      {
	af = get_af3(pos+2+i);
	ac = bgp_get_af_caps(caps, af);
	ac->gr_able = 1;
	ac->gr_af_flags = pos[2+i+3];
      }
      break;

    case 65: /* AS4 capability, RFC 4893 */
      if (cl != 4)
	goto err;

      caps->as4_support = 1;
      caps->as4_number = get_u32(pos + 2);
      break;

    case 69: /* ADD-PATH capability, RFC 7911 */
      if (cl % 4)
	goto err;

      for (i = 0; i < cl; i += 4)
      {
	byte val = pos[2+i+3];
	if (!val || (val > BGP_ADD_PATH_FULL))
482
	{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
483 484
	  log(L_WARN "%s: Got ADD-PATH capability with unknown value %u, ignoring",
	      p->p.name, val);
485 486
	  break;
	}
Ondřej Zajíček's avatar
Ondřej Zajíček committed
487
      }
488

Ondřej Zajíček's avatar
Ondřej Zajíček committed
489 490 491 492 493 494 495
      for (i = 0; i < cl; i += 4)
      {
	af = get_af3(pos+2+i);
	ac = bgp_get_af_caps(caps, af);
	ac->add_path = pos[2+i+3];
      }
      break;
496

Ondřej Zajíček's avatar
Ondřej Zajíček committed
497 498 499
    case 70: /* Enhanced route refresh capability, RFC 7313 */
      if (cl != 0)
	goto err;
500

Ondřej Zajíček's avatar
Ondřej Zajíček committed
501 502
      caps->enhanced_refresh = 1;
      break;
Martin Mareš's avatar
Martin Mareš committed
503

Ondřej Zajíček's avatar
Ondřej Zajíček committed
504 505 506 507 508 509 510 511 512 513
      /* We can safely ignore all other capabilities */
    }

    ADVANCE(pos, len, 2 + cl);
  }
  return;

err:
  bgp_error(conn, 2, 0, NULL, 0);
  return;
514 515
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
516 517
static int
bgp_read_options(struct bgp_conn *conn, byte *pos, int len)
Martin Mareš's avatar
Martin Mareš committed
518
{
519
  struct bgp_proto *p = conn->bgp;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
520 521
  struct bgp_caps *caps;
  int ol;
522

Ondřej Zajíček's avatar
Ondřej Zajíček committed
523 524 525
  /* Max number of announced AFIs is limited by max option length (255) */
  caps = alloca(sizeof(struct bgp_caps) + 64 * sizeof(struct bgp_af_caps));
  memset(caps, 0, sizeof(struct bgp_caps));
526

Ondřej Zajíček's avatar
Ondřej Zajíček committed
527 528 529 530 531 532 533
  while (len > 0)
  {
    if ((len < 2) || (len < (2 + pos[1])))
    { bgp_error(conn, 2, 0, NULL, 0); return -1; }

    ol = pos[1];
    if (pos[0] == 2)
534
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
535 536 537
      /* BGP capabilities, RFC 5492 */
      if (p->cf->capabilities)
	bgp_read_capabilities(conn, caps, pos + 2, ol);
538
    }
Ondřej Zajíček's avatar
Ondřej Zajíček committed
539
    else
540
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
541 542 543
      /* Unknown option */
      bgp_error(conn, 2, 4, pos, ol); /* FIXME: ol or ol+2 ? */
      return -1;
544 545
    }

Ondřej Zajíček's avatar
Ondřej Zajíček committed
546 547 548 549 550 551 552 553
    ADVANCE(pos, len, 2 + ol);
  }

  uint n = sizeof(struct bgp_caps) + caps->af_count * sizeof(struct bgp_af_caps);
  conn->remote_caps = mb_allocz(p->p.pool, n);
  memcpy(conn->remote_caps, caps, n);

  return 0;
Martin Mareš's avatar
Martin Mareš committed
554 555
}

556
static byte *
Ondřej Zajíček's avatar
Ondřej Zajíček committed
557
bgp_create_open(struct bgp_conn *conn, byte *buf)
558 559 560
{
  struct bgp_proto *p = conn->bgp;

Ondřej Zajíček's avatar
Ondřej Zajíček committed
561 562
  BGP_TRACE(D_PACKETS, "Sending OPEN(ver=%d,as=%d,hold=%d,id=%08x)",
	    BGP_VERSION, p->public_as, p->cf->hold_time, p->local_id);
563

Ondřej Zajíček's avatar
Ondřej Zajíček committed
564 565 566 567
  buf[0] = BGP_VERSION;
  put_u16(buf+1, (p->public_as < 0xFFFF) ? p->public_as : AS_TRANS);
  put_u16(buf+3, p->cf->hold_time);
  put_u32(buf+5, p->local_id);
568

Ondřej Zajíček's avatar
Ondřej Zajíček committed
569 570 571 572 573
  if (p->cf->capabilities)
  {
    /* Prepare local_caps and write capabilities to buffer */
    byte *end = bgp_write_capabilities(conn, buf+12);
    uint len = end - (buf+12);
Martin Mareš's avatar
Martin Mareš committed
574

Ondřej Zajíček's avatar
Ondřej Zajíček committed
575 576 577
    buf[9] = len + 2;		/* Optional parameters length */
    buf[10] = 2;		/* Option 2: Capability list */
    buf[11] = len;		/* Option data length */
578

Ondřej Zajíček's avatar
Ondřej Zajíček committed
579 580 581 582 583 584
    return end;
  }
  else
  {
    /* Prepare empty local_caps */
    conn->local_caps = mb_allocz(p->p.pool, sizeof(struct bgp_caps));
585

Ondřej Zajíček's avatar
Ondřej Zajíček committed
586 587 588
    buf[9] = 0;			/* No optional parameters */
    return buf + 10;
  }
589 590 591 592

  return buf;
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
593 594
static void
bgp_rx_open(struct bgp_conn *conn, byte *pkt, uint len)
595 596
{
  struct bgp_proto *p = conn->bgp;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
597 598
  struct bgp_conn *other;
  u32 asn, hold, id;
599

Ondřej Zajíček's avatar
Ondřej Zajíček committed
600 601 602
  /* Check state */
  if (conn->state != BS_OPENSENT)
  { bgp_error(conn, 5, fsm_err_subcode[conn->state], NULL, 0); return; }
603

Ondřej Zajíček's avatar
Ondřej Zajíček committed
604 605 606
  /* Check message contents */
  if (len < 29 || len != 29 + (uint) pkt[28])
  { bgp_error(conn, 1, 2, pkt+16, 2); return; }
607

Ondřej Zajíček's avatar
Ondřej Zajíček committed
608 609
  if (pkt[19] != BGP_VERSION)
  { u16 val = BGP_VERSION; bgp_error(conn, 2, 1, (byte *) &val, 2); return; }
610

Ondřej Zajíček's avatar
Ondřej Zajíček committed
611 612 613 614 615 616 617 618 619 620
  asn = get_u16(pkt+20);
  hold = get_u16(pkt+22);
  id = get_u32(pkt+24);
  BGP_TRACE(D_PACKETS, "Got OPEN(as=%d,hold=%d,id=%R)", asn, hold, id);

  if (bgp_read_options(conn, pkt+29, pkt[28]) < 0)
    return;

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

Ondřej Zajíček's avatar
Ondřej Zajíček committed
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
  /* RFC 6286 2.2 - router ID is nonzero and AS-wide unique */
  if (!id || (p->is_internal && id == p->local_id))
  { bgp_error(conn, 2, 3, pkt+24, -4); return; }

  struct bgp_caps *caps = conn->remote_caps;

  if (caps->as4_support)
  {
    u32 as4 = caps->as4_number;

    if ((as4 != asn) && (asn != AS_TRANS))
      log(L_WARN "%s: Peer advertised inconsistent AS numbers", p->p.name);

    if (as4 != p->remote_as)
    { as4 = htonl(as4); bgp_error(conn, 2, 2, (byte *) &as4, 4); return; }
  }
  else
  {
    if (asn != p->remote_as)
    { bgp_error(conn, 2, 2, pkt+20, 2); return; }
  }

  /* Check the other connection */
  other = (conn == &p->outgoing_conn) ? &p->incoming_conn : &p->outgoing_conn;
  switch (other->state)
  {
  case BS_CONNECT:
  case BS_ACTIVE:
    /* Stop outgoing connection attempts */
    bgp_conn_enter_idle_state(other);
    break;

  case BS_IDLE:
  case BS_OPENSENT:
  case BS_CLOSE:
    break;

  case BS_OPENCONFIRM:
    /*
     * Description of collision detection rules in RFC 4271 is confusing and
     * contradictory, but it is essentially:
     *
     * 1. Router with higher ID is dominant
     * 2. If both have the same ID, router with higher ASN is dominant [RFC6286]
     * 3. When both connections are in OpenConfirm state, one initiated by
     *    the dominant router is kept.
     *
     * The first line in the expression below evaluates whether the neighbor
     * is dominant, the second line whether the new connection was initiated
     * by the neighbor. If both are true (or both are false), we keep the new
     * connection, otherwise we keep the old one.
     */
    if (((p->local_id < id) || ((p->local_id == id) && (p->public_as < p->remote_as)))
	== (conn == &p->incoming_conn))
676
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
677 678 679 680
      /* Should close the other connection */
      BGP_TRACE(D_EVENTS, "Connection collision, giving up the other connection");
      bgp_error(other, 6, 7, NULL, 0);
      break;
681
    }
Ondřej Zajíček's avatar
Ondřej Zajíček committed
682 683 684 685 686 687
    /* Fall thru */
  case BS_ESTABLISHED:
    /* Should close this connection */
    BGP_TRACE(D_EVENTS, "Connection collision, giving up this connection");
    bgp_error(conn, 6, 7, NULL, 0);
    return;
688

Ondřej Zajíček's avatar
Ondřej Zajíček committed
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
  default:
    bug("bgp_rx_open: Unknown state");
  }

  /* Update our local variables */
  conn->hold_time = MIN(hold, p->cf->hold_time);
  conn->keepalive_time = p->cf->keepalive_time ? : conn->hold_time / 3;
  conn->as4_session = conn->local_caps->as4_support && caps->as4_support;
  conn->ext_messages = conn->local_caps->ext_messages && caps->ext_messages;
  p->remote_id = id;

  DBG("BGP: Hold timer set to %d, keepalive to %d, AS to %d, ID to %x, AS4 session to %d\n",
      conn->hold_time, conn->keepalive_time, p->remote_as, p->remote_id, conn->as4_session);

  bgp_schedule_packet(conn, NULL, PKT_KEEPALIVE);
  bgp_start_timer(conn->hold_timer, conn->hold_time);
  bgp_conn_enter_openconfirm_state(conn);
}


/*
 *	Next hop handling
 */

#define REPORT(msg, args...) \
  ({ log(L_REMOTE "%s: " msg, s->proto->p.name, ## args); })

Ondřej Zajíček's avatar
Ondřej Zajíček committed
716 717 718
#define DISCARD(msg, args...) \
  ({ REPORT(msg, ## args); return; })

Ondřej Zajíček's avatar
Ondřej Zajíček committed
719 720 721
#define WITHDRAW(msg, args...) \
  ({ REPORT(msg, ## args); s->err_withdraw = 1; return; })

Ondřej Zajíček's avatar
Ondřej Zajíček committed
722
#define BAD_AFI		"Unexpected AF <%u/%u> in UPDATE"
Ondřej Zajíček's avatar
Ondřej Zajíček committed
723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
#define BAD_NEXT_HOP	"Invalid NEXT_HOP attribute"
#define NO_NEXT_HOP	"Missing NEXT_HOP attribute"


static void
bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll)
{
  struct bgp_proto *p = s->proto;
  struct bgp_channel *c = s->channel;

  if (c->cf->gw_mode == GW_DIRECT)
  {
    neighbor *nbr = NULL;

    /* GW_DIRECT -> single_hop -> p->neigh != NULL */
    if (ipa_nonzero(gw))
      nbr = neigh_find2(&p->p, &gw, NULL, 0);
    else if (ipa_nonzero(ll))
      nbr = neigh_find2(&p->p, &ll, p->neigh->iface, 0);

    if (!nbr || (nbr->scope == SCOPE_HOST))
      WITHDRAW(BAD_NEXT_HOP);

    a->dest = RTD_ROUTER;
    a->gw = nbr->addr;
    a->iface = nbr->iface;
    a->hostentry = NULL;
    a->igp_metric = 0;
  }
  else /* GW_RECURSIVE */
  {
    if (ipa_zero(gw))
      WITHDRAW(BAD_NEXT_HOP);

    rta_set_recursive_next_hop(c->c.table, a, c->igp_table, gw, ll);
  }
}

static inline int
bgp_use_next_hop(struct bgp_export_state *s, eattr *a)
{
  struct bgp_proto *p = s->proto;
  ip_addr *nh = (void *) a->u.ptr->data;

  if (s->channel->cf->next_hop_self)
    return 0;

  if (s->channel->cf->next_hop_keep)
    return 1;

  /* Keep it when explicitly set in export filter */
  if (a->type & EAF_FRESH)
    return 1;

  /* Keep it when exported to internal peers */
  if (p->is_interior && ipa_nonzero(*nh))
    return 1;

  /* Keep it when forwarded between single-hop BGPs on the same iface */
  struct iface *ifa = (s->src && s->src->neigh) ? s->src->neigh->iface : NULL;
  return p->neigh && (p->neigh->iface == ifa);
}

static inline int
bgp_use_gateway(struct bgp_export_state *s)
{
  struct bgp_proto *p = s->proto;
  rta *ra = s->route->attrs;

  if (s->channel->cf->next_hop_self)
    return 0;

  /* We need valid global gateway */
  if ((ra->dest != RTD_ROUTER) || ipa_zero(ra->gw) || ipa_is_link_local(ra->gw))
    return 0;

  /* Use it when exported to internal peers */
  if (p->is_interior)
    return 1;

  /* Use it when forwarded to single-hop BGP peer on on the same iface */
  return p->neigh && (p->neigh->iface == ra->iface);
}

static void
bgp_update_next_hop_ip(struct bgp_export_state *s, eattr *a, ea_list **to)
{
  if (!a || !bgp_use_next_hop(s, a))
  {
    if (bgp_use_gateway(s))
813
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
814 815
      ip_addr nh[1] = { s->route->attrs->gw };
      bgp_set_attr_data(to, s->pool, BA_NEXT_HOP, 0, nh, 16);
816
    }
Ondřej Zajíček's avatar
Ondřej Zajíček committed
817
    else
818
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
819 820
      ip_addr nh[2] = { s->channel->next_hop_addr, s->channel->link_addr };
      bgp_set_attr_data(to, s->pool, BA_NEXT_HOP, 0, nh, ipa_nonzero(nh[1]) ? 32 : 16);
821
    }
Ondřej Zajíček's avatar
Ondřej Zajíček committed
822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839
  }

  /* Check if next hop is valid */
  a = bgp_find_attr(*to, BA_NEXT_HOP);
  if (!a)
    WITHDRAW(NO_NEXT_HOP);

  ip_addr *nh = (void *) a->u.ptr->data;
  ip_addr peer = s->proto->cf->remote_ip;
  uint len = a->u.ptr->length;

  if (ipa_zero(nh[0]) && ((len != 32) || ipa_zero(nh[1])))
    WITHDRAW(BAD_NEXT_HOP);

  if (ipa_equal(peer, nh[0]) || ((len == 32) && ipa_equal(peer, nh[1])))
    WITHDRAW(BAD_NEXT_HOP);
}

840 841 842 843 844 845 846 847 848
static uint
bgp_encode_next_hop_none(struct bgp_write_state *s UNUSED, eattr *a UNUSED, byte *buf UNUSED, uint size UNUSED)
{
  return 0;
}

static void
bgp_decode_next_hop_none(struct bgp_parse_state *s UNUSED, byte *data UNUSED, uint len UNUSED, rta *a UNUSED)
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
849 850 851 852 853 854
  /*
   * Although we expect no next hop and RFC 7606 7.11 states that attribute
   * MP_REACH_NLRI with unexpected next hop length is considered malformed,
   * FlowSpec RFC 5575 4 states that next hop shall be ignored on receipt.
   */

855 856 857 858
  return;
}

static void
Ondřej Zajíček's avatar
Ondřej Zajíček committed
859
bgp_update_next_hop_none(struct bgp_export_state *s, eattr *a, ea_list **to)
860
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
861 862 863
  /* NEXT_HOP shall not pass */
  if (a)
    bgp_unset_attr(to, s->pool, BA_NEXT_HOP);
864 865
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922

/*
 *	UPDATE
 */

static void
bgp_rte_update(struct bgp_parse_state *s, net_addr *n, u32 path_id, rta *a0)
{
  if (path_id != s->last_id)
  {
    s->last_src = rt_get_source(&s->proto->p, path_id);
    s->last_id = path_id;

    rta_free(s->cached_rta);
    s->cached_rta = NULL;
  }

  if (!a0)
  {
    /* Route withdraw */
    rte_update2(&s->channel->c, n, NULL, s->last_src);
    return;
  }

  /* Prepare cached route attributes */
  if (s->cached_rta == NULL)
  {
    a0->src = s->last_src;

    /* Workaround for rta_lookup() breaking eattrs */
    ea_list *ea = a0->eattrs;
    s->cached_rta = rta_lookup(a0);
    a0->eattrs = ea;
  }

  rta *a = rta_clone(s->cached_rta);
  rte *e = rte_get_temp(a);

  e->pflags = 0;
  e->u.bgp.suppressed = 0;
  rte_update2(&s->channel->c, n, e, s->last_src);
}



static uint
bgp_encode_nlri_ip4(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, uint size)
{
  byte *pos = buf;

  while (!EMPTY_LIST(buck->prefixes) && (size >= (5 + sizeof(ip4_addr))))
  {
    struct bgp_prefix *px = HEAD(buck->prefixes);
    struct net_addr_ip4 *net = (void *) px->net;

    /* Encode path ID */
    if (s->add_path)
923
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
924 925
      put_u32(pos, px->path_id);
      ADVANCE(pos, size, 4);
926
    }
Ondřej Zajíček's avatar
Ondřej Zajíček committed
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954

    ip4_addr a = ip4_hton(net->prefix);
    uint b = (net->pxlen + 7) / 8;

    /* Encode prefix length */
    *pos = net->pxlen;
    ADVANCE(pos, size, 1);

    /* Encode prefix body */
    memcpy(pos, &a, b);
    ADVANCE(pos, size, b);

    bgp_free_prefix(s->channel, px);
  }

  return pos - buf;
}

static void
bgp_decode_nlri_ip4(struct bgp_parse_state *s, byte *pos, uint len, rta *a)
{
  while (len)
  {
    net_addr_ip4 net;
    u32 path_id = 0;

    /* Decode path ID */
    if (s->add_path)
955
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
956 957 958 959 960
      if (len < 5)
	bgp_parse_error(s, 1);

      path_id = get_u32(pos);
      ADVANCE(pos, len, 4);
961
    }
Ondřej Zajíček's avatar
Ondřej Zajíček committed
962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026

    /* Decode prefix length */
    uint l = *pos;
    uint b = (l + 7) / 8;
    ADVANCE(pos, len, 1);

    if (l > IP4_MAX_PREFIX_LENGTH)
      bgp_parse_error(s, 10);

    if (len < b)
      bgp_parse_error(s, 1);

    /* Decode prefix body */
    ip4_addr addr = IP4_NONE;
    memcpy(&addr, pos, b);
    ADVANCE(pos, len, b);

    net = NET_ADDR_IP4(ip4_ntoh(addr), l);
    net_normalize_ip4(&net);

    // XXXX validate prefix

    bgp_rte_update(s, (net_addr *) &net, path_id, a);
  }
}

static uint
bgp_encode_next_hop_ip4(struct bgp_write_state *s UNUSED, eattr *a, byte *buf, uint size UNUSED)
{
  /* This function is used only for MP-BGP, see bgp_encode_next_hop() for IPv4 BGP */

  ASSERT(a->u.ptr->length == sizeof(ip_addr));

  put_ip4(buf, ipa_to_ip4( *(ip_addr *) a->u.ptr->data ));

  return 4;
}

static void
bgp_decode_next_hop_ip4(struct bgp_parse_state *s, byte *data, uint len, rta *a)
{
  if (len != 4)
    bgp_parse_error(s, 9);

  ip_addr nh = ipa_from_ip4(get_ip4(data));

  // XXXX validate next hop

  bgp_set_attr_data(&(a->eattrs), s->pool, BA_NEXT_HOP, 0, &nh, sizeof(nh));
  bgp_apply_next_hop(s, a, nh, IPA_NONE);
}


static uint
bgp_encode_nlri_ip6(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, uint size)
{
  byte *pos = buf;

  while (!EMPTY_LIST(buck->prefixes) && (size >= (5 + sizeof(ip6_addr))))
  {
    struct bgp_prefix *px = HEAD(buck->prefixes);
    struct net_addr_ip6 *net = (void *) px->net;

    /* Encode path ID */
    if (s->add_path)
1027
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1028 1029
      put_u32(pos, px->path_id);
      ADVANCE(pos, size, 4);
1030
    }
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058

    ip6_addr a = ip6_hton(net->prefix);
    uint b = (net->pxlen + 7) / 8;

    /* Encode prefix length */
    *pos = net->pxlen;
    ADVANCE(pos, size, 1);

    /* Encode prefix body */
    memcpy(pos, &a, b);
    ADVANCE(pos, size, b);

    bgp_free_prefix(s->channel, px);
  }

  return pos - buf;
}

static void
bgp_decode_nlri_ip6(struct bgp_parse_state *s, byte *pos, uint len, rta *a)
{
  while (len)
  {
    net_addr_ip6 net;
    u32 path_id = 0;

    /* Decode path ID */
    if (s->add_path)
1059
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1060 1061 1062 1063 1064
      if (len < 5)
	bgp_parse_error(s, 1);

      path_id = get_u32(pos);
      ADVANCE(pos, len, 4);
1065
    }
1066

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1067 1068 1069 1070
    /* Decode prefix length */
    uint l = *pos;
    uint b = (l + 7) / 8;
    ADVANCE(pos, len, 1);
1071

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1072 1073
    if (l > IP6_MAX_PREFIX_LENGTH)
      bgp_parse_error(s, 10);
1074

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1075 1076
    if (len < b)
      bgp_parse_error(s, 1);
1077

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1078 1079 1080 1081
    /* Decode prefix body */
    ip6_addr addr = IP6_NONE;
    memcpy(&addr, pos, b);
    ADVANCE(pos, len, b);
1082

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1083 1084
    net = NET_ADDR_IP6(ip6_ntoh(addr), l);
    net_normalize_ip6(&net);
1085

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1086
    // XXXX validate prefix
1087

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1088 1089
    bgp_rte_update(s, (net_addr *) &net, path_id, a);
  }
1090 1091
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1092 1093
static uint
bgp_encode_next_hop_ip6(struct bgp_write_state *s UNUSED, eattr *a, byte *buf, uint size UNUSED)
1094
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
  ip_addr *nh = (void *) a->u.ptr->data;
  uint len = a->u.ptr->length;

  ASSERT((len == 16) || (len == 32));

  put_ip6(buf, ipa_to_ip6(nh[0]));

  if (len == 32)
    put_ip6(buf+16, ipa_to_ip6(nh[1]));

  return len;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1106 1107
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1108 1109
static void
bgp_decode_next_hop_ip6(struct bgp_parse_state *s, byte *data, uint len, rta *a)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1110
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1111 1112
  struct adata *ad = lp_alloc_adata(s->pool, 32);
  ip_addr *nh = (void *) ad->data;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1113

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
  if ((len != 16) && (len != 32))
    bgp_parse_error(s, 9);

  nh[0] = ipa_from_ip6(get_ip6(data));
  nh[1] = (len == 32) ? ipa_from_ip6(get_ip6(data+16)) : IPA_NONE;

  if (ip6_is_link_local(nh[0]))
  {
    nh[1] = nh[0];
    nh[0] = IPA_NONE;
  }

  if (!ip6_is_link_local(nh[1]))
    nh[1] = IPA_NONE;

  if (ipa_zero(nh[1]))
    ad->length = 16;

  // XXXX validate next hop

  bgp_set_attr_ptr(&(a->eattrs), s->pool, BA_NEXT_HOP, 0, ad);
  bgp_apply_next_hop(s, a, nh[0], nh[1]);
1136 1137
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1138

1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322
static uint
bgp_encode_nlri_flow4(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, uint size)
{
  byte *pos = buf;

  while (!EMPTY_LIST(buck->prefixes) && (size >= 4))
  {
    struct bgp_prefix *px = HEAD(buck->prefixes);
    struct net_addr_flow4 *net = (void *) px->net;
    uint flen = net->length - sizeof(net_addr_flow4);

    /* Encode path ID */
    if (s->add_path)
    {
      put_u32(pos, px->path_id);
      ADVANCE(pos, size, 4);
    }

    if (flen > size)
      break;

    /* Copy whole flow data including length */
    memcpy(pos, net->data, flen);
    ADVANCE(pos, size, flen);

    bgp_free_prefix(s->channel, px);
  }

  return pos - buf;
}

static void
bgp_decode_nlri_flow4(struct bgp_parse_state *s, byte *pos, uint len, rta *a)
{
  while (len)
  {
    u32 path_id = 0;

    /* Decode path ID */
    if (s->add_path)
    {
      if (len < 4)
	bgp_parse_error(s, 1);

      path_id = get_u32(pos);
      ADVANCE(pos, len, 4);
    }

    if (len < 2)
      bgp_parse_error(s, 1);

    /* Decode flow length */
    uint hlen = flow_hdr_length(pos);
    uint dlen = flow_read_length(pos);
    uint flen = hlen + dlen;
    byte *data = pos + hlen;

    if (len < flen)
      bgp_parse_error(s, 1);

    /* Validate flow data */
    enum flow_validated_state r = flow4_validate(data, dlen);
    if (r != FLOW_ST_VALID)
    {
      log(L_REMOTE "%s: Invalid flow route: %s", s->proto->p.name, flow_validated_state_str(r));
      bgp_parse_error(s, 1);
    }

    if (data[0] != FLOW_TYPE_DST_PREFIX)
    {
      log(L_REMOTE "%s: No dst prefix at first pos", s->proto->p.name);
      bgp_parse_error(s, 1);
    }

    /* Decode dst prefix */
    ip4_addr px = IP4_NONE;
    uint pxlen = data[1];

    // FIXME: Use some generic function
    memcpy(&px, data, BYTES(pxlen));
    px = ip4_and(px, ip4_mkmask(pxlen));

    /* Prepare the flow */
    net_addr *n = alloca(sizeof(struct net_addr_flow4) + flen);
    net_fill_flow4(n, px, pxlen, pos, flen);
    ADVANCE(pos, len, flen);

    bgp_rte_update(s, n, path_id, a);
  }
}


static uint
bgp_encode_nlri_flow6(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, uint size)
{
  byte *pos = buf;

  while (!EMPTY_LIST(buck->prefixes) && (size >= 4))
  {
    struct bgp_prefix *px = HEAD(buck->prefixes);
    struct net_addr_flow6 *net = (void *) px->net;
    uint flen = net->length - sizeof(net_addr_flow6);

    /* Encode path ID */
    if (s->add_path)
    {
      put_u32(pos, px->path_id);
      ADVANCE(pos, size, 4);
    }

    if (flen > size)
      break;

    /* Copy whole flow data including length */
    memcpy(pos, net->data, flen);
    ADVANCE(pos, size, flen);

    bgp_free_prefix(s->channel, px);
  }

  return pos - buf;
}

static void
bgp_decode_nlri_flow6(struct bgp_parse_state *s, byte *pos, uint len, rta *a)
{
  while (len)
  {
    u32 path_id = 0;

    /* Decode path ID */
    if (s->add_path)
    {
      if (len < 4)
	bgp_parse_error(s, 1);

      path_id = get_u32(pos);
      ADVANCE(pos, len, 4);
    }

    if (len < 2)
      bgp_parse_error(s, 1);

    /* Decode flow length */
    uint hlen = flow_hdr_length(pos);
    uint dlen = flow_read_length(pos);
    uint flen = hlen + dlen;
    byte *data = pos + hlen;

    if (len < flen)
      bgp_parse_error(s, 1);

    /* Validate flow data */
    enum flow_validated_state r = flow6_validate(data, dlen);
    if (r != FLOW_ST_VALID)
    {
      log(L_REMOTE "%s: Invalid flow route: %s", s->proto->p.name, flow_validated_state_str(r));
      bgp_parse_error(s, 1);
    }

    if (data[0] != FLOW_TYPE_DST_PREFIX)
    {
      log(L_REMOTE "%s: No dst prefix at first pos", s->proto->p.name);
      bgp_parse_error(s, 1);
    }

    /* Decode dst prefix */
    ip6_addr px = IP6_NONE;
    uint pxlen = data[1];

    // FIXME: Use some generic function
    memcpy(&px, data, BYTES(pxlen));
    px = ip6_and(px, ip6_mkmask(pxlen));

    /* Prepare the flow */
    net_addr *n = alloca(sizeof(struct net_addr_flow6) + flen);
    net_fill_flow6(n, px, pxlen, pos, flen);
    ADVANCE(pos, len, flen);

    bgp_rte_update(s, n, path_id, a);
  }
}


Ondřej Zajíček's avatar
Ondřej Zajíček committed
1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
static const struct bgp_af_desc bgp_af_table[] = {
  {
    .afi = BGP_AF_IPV4,
    .net = NET_IP4,
    .name = "ipv4",
    .encode_nlri = bgp_encode_nlri_ip4,
    .decode_nlri = bgp_decode_nlri_ip4,
    .encode_next_hop = bgp_encode_next_hop_ip4,
    .decode_next_hop = bgp_decode_next_hop_ip4,
    .update_next_hop = bgp_update_next_hop_ip,
  },
  {
    .afi = BGP_AF_IPV4_MC,
    .net = NET_IP4,
    .name = "ipv4-mc",
    .encode_nlri = bgp_encode_nlri_ip4,
    .decode_nlri = bgp_decode_nlri_ip4,
    .encode_next_hop = bgp_encode_next_hop_ip4,
    .decode_next_hop = bgp_decode_next_hop_ip4,
    .update_next_hop = bgp_update_next_hop_ip,
  },
1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
  {
    .afi = BGP_AF_FLOW4,
    .net = NET_FLOW4,
    .name = "flow4",
    .encode_nlri = bgp_encode_nlri_flow4,
    .decode_nlri = bgp_decode_nlri_flow4,
    .encode_next_hop = bgp_encode_next_hop_none,
    .decode_next_hop = bgp_decode_next_hop_none,
    .update_next_hop = bgp_update_next_hop_none,
  },
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373
  {
    .afi = BGP_AF_IPV6,
    .net = NET_IP6,
    .name = "ipv6",
    .encode_nlri = bgp_encode_nlri_ip6,
    .decode_nlri = bgp_decode_nlri_ip6,
    .encode_next_hop = bgp_encode_next_hop_ip6,
    .decode_next_hop = bgp_decode_next_hop_ip6,
    .update_next_hop = bgp_update_next_hop_ip,
  },
  {
    .afi = BGP_AF_IPV6_MC,
    .net = NET_IP6,
    .name = "ipv6-mc",
    .encode_nlri = bgp_encode_nlri_ip6,
    .decode_nlri = bgp_decode_nlri_ip6,
    .encode_next_hop = bgp_encode_next_hop_ip6,
    .decode_next_hop = bgp_decode_next_hop_ip6,
    .update_next_hop = bgp_update_next_hop_ip,
  },
1374 1375 1376 1377 1378 1379 1380 1381 1382 1383
  {
    .afi = BGP_AF_FLOW6,
    .net = NET_FLOW6,
    .name = "flow6",
    .encode_nlri = bgp_encode_nlri_flow6,
    .decode_nlri = bgp_decode_nlri_flow6,
    .encode_next_hop = bgp_encode_next_hop_none,
    .decode_next_hop = bgp_decode_next_hop_none,
    .update_next_hop = bgp_update_next_hop_none,
  },
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1384 1385 1386 1387
};

const struct bgp_af_desc *
bgp_get_af_desc(u32 afi)
1388
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1389 1390 1391 1392
  uint i;
  for (i = 0; i < ARRAY_SIZE(bgp_af_table); i++)
    if (bgp_af_table[i].afi == afi)
      return &bgp_af_table[i];
1393

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1394
  return NULL;
1395 1396
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407
static inline uint
bgp_encode_nlri(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, byte *end)
{
  return s->channel->desc->encode_nlri(s, buck, buf, end - buf);
}

static inline uint
bgp_encode_next_hop(struct bgp_write_state *s, eattr *nh, byte *buf)
{
  return s->channel->desc->encode_next_hop(s, nh, buf, 255);
}
1408 1409

void
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1410
bgp_update_next_hop(struct bgp_export_state *s, eattr *a, ea_list **to)
1411
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1412 1413
  s->channel->desc->update_next_hop(s, a, to);
}
1414

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436
#define MAX_ATTRS_LENGTH (end-buf+BGP_HEADER_LENGTH - 1024)

static byte *
bgp_create_ip_reach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, byte *end)
{
  /*
   *	2 B	Withdrawn Routes Length (zero)
   *	---	IPv4 Withdrawn Routes NLRI (unused)
   *	2 B	Total Path Attribute Length
   *	var	Path Attributes
   *	var	IPv4 Network Layer Reachability Information
   */

  int lr, la;

  la = bgp_encode_attrs(s, buck->eattrs, buf+4, buf + MAX_ATTRS_LENGTH);
  if (la < 0)
  {
    /* Attribute list too long */
    bgp_withdraw_bucket(s->channel, buck);
    return NULL;
  }
1437

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1438 1439
  put_u16(buf+0, 0);
  put_u16(buf+2, la);
1440

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1441
  lr = bgp_encode_nlri(s, buck, buf+4+la, end);
1442

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1443 1444
  return buf+4+la+lr;
}
1445

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
static byte *
bgp_create_mp_reach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, byte *end)
{
  /*
   *	2 B	IPv4 Withdrawn Routes Length (zero)
   *	---	IPv4 Withdrawn Routes NLRI (unused)
   *	2 B	Total Path Attribute Length
   *	1 B	MP_REACH_NLRI hdr - Attribute Flags
   *	1 B	MP_REACH_NLRI hdr - Attribute Type Code
   *	2 B	MP_REACH_NLRI hdr - Length of Attribute Data
   *	2 B	MP_REACH_NLRI data - Address Family Identifier
   *	1 B	MP_REACH_NLRI data - Subsequent Address Family Identifier
   *	1 B	MP_REACH_NLRI data - Length of Next Hop Network Address
   *	var	MP_REACH_NLRI data - Network Address of Next Hop
   *	1 B	MP_REACH_NLRI data - Reserved (zero)
   *	var	MP_REACH_NLRI data - Network Layer Reachability Information
   *	var	Rest of Path Attributes
   *	---	IPv4 Network Layer Reachability Information (unused)
   */

  int lh, lr, la;	/* Lengths of next hop, NLRI and attributes */

  /* Begin of MP_REACH_NLRI atribute */
  buf[4] = BAF_OPTIONAL | BAF_EXT_LEN;
  buf[5] = BA_MP_REACH_NLRI;
  put_u16(buf+6, 0);		/* Will be fixed later */
  put_af3(buf+8, s->channel->afi);
  byte *pos = buf+11;

  /* Encode attributes to temporary buffer */
  byte *abuf = alloca(MAX_ATTRS_LENGTH);
  la = bgp_encode_attrs(s, buck->eattrs, abuf, abuf + MAX_ATTRS_LENGTH);
  if (la < 0)
  {
    /* Attribute list too long */
    bgp_withdraw_bucket(s->channel, buck);
    return NULL;
  }
1484

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1485 1486 1487 1488
  /* Encode the next hop */
  lh = bgp_encode_next_hop(s, s->mp_next_hop, pos+1);
  *pos = lh;
  pos += 1+lh;
1489

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1490 1491
  /* Reserved field */
  *pos++ = 0;
1492

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1493 1494 1495
  /* Encode the NLRI */
  lr = bgp_encode_nlri(s, buck, pos, end - la);
  pos += lr;
1496

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1497 1498
  /* End of MP_REACH_NLRI atribute, update data length */
  put_u16(buf+6, pos-buf-8);
1499

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1500 1501 1502 1503 1504 1505 1506 1507 1508
  /* Copy remaining attributes */
  memcpy(pos, abuf, la);
  pos += la;

  /* Initial UPDATE fields */
  put_u16(buf+0, 0);
  put_u16(buf+2, pos-buf-4);

  return pos;
1509 1510
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1511 1512 1513 1514
#undef MAX_ATTRS_LENGTH

static byte *
bgp_create_ip_unreach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, byte *end)
1515
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1516 1517 1518 1519 1520 1521 1522
  /*
   *	2 B	Withdrawn Routes Length
   *	var	IPv4 Withdrawn Routes NLRI
   *	2 B	Total Path Attribute Length (zero)
   *	---	Path Attributes (unused)
   *	---	IPv4 Network Layer Reachability Information (unused)
   */
1523

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1524
  uint len = bgp_encode_nlri(s, buck, buf+2, end);
1525

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1526 1527
  put_u16(buf+0, len);
  put_u16(buf+2+len, 0);
1528

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1529
  return buf+4+len;
1530 1531
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1532 1533
static byte *
bgp_create_mp_unreach(struct bgp_write_state *s, struct bgp_bucket *buck, byte *buf, byte *end)
1534
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548
  /*
   *	2 B	Withdrawn Routes Length (zero)
   *	---	IPv4 Withdrawn Routes NLRI (unused)
   *	2 B	Total Path Attribute Length
   *	1 B	MP_UNREACH_NLRI hdr - Attribute Flags
   *	1 B	MP_UNREACH_NLRI hdr - Attribute Type Code
   *	2 B	MP_UNREACH_NLRI hdr - Length of Attribute Data
   *	2 B	MP_UNREACH_NLRI data - Address Family Identifier
   *	1 B	MP_UNREACH_NLRI data - Subsequent Address Family Identifier
   *	var	MP_UNREACH_NLRI data - Network Layer Reachability Information
   *	---	IPv4 Network Layer Reachability Information (unused)
   */

  uint len = bgp_encode_nlri(s, buck, buf+11, end);
1549

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1550 1551
  put_u16(buf+0, 0);
  put_u16(buf+2, 7+len);
1552

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1553 1554 1555 1556 1557
  /* Begin of MP_UNREACH_NLRI atribute */
  buf[4] = BAF_OPTIONAL | BAF_EXT_LEN;
  buf[5] = BA_MP_UNREACH_NLRI;
  put_u16(buf+6, 3+len);
  put_af3(buf+8, s->channel->afi);
1558

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1559 1560
  return buf+11+len;
}
1561

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586
static byte *
bgp_create_update(struct bgp_channel *c, byte *buf)
{
  struct bgp_proto *p = (void *) c->c.proto;
  struct bgp_bucket *buck;
  byte *end = buf + (bgp_max_packet_length(p->conn) - BGP_HEADER_LENGTH);
  byte *res = NULL;

  /* Initialize write state */
  struct bgp_write_state s = {
    .proto = p,
    .channel = c,
    .pool = bgp_linpool,
    .as4_session = p->as4_session,
    .add_path = c->add_path_tx,
  };

again:

  /* Try unreachable bucket */
  if ((buck = c->withdraw_bucket) && !EMPTY_LIST(buck->prefixes))
  {
    res = (c->afi == BGP_AF_IPV4) ?
      bgp_create_ip_unreach(&s, buck, buf, end):
      bgp_create_mp_unreach(&s, buck, buf, end);
1587

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1588 1589
    goto done;
  }
1590

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1591 1592 1593 1594
  /* Try reachable buckets */
  if (!EMPTY_LIST(c->bucket_queue))
  {
    buck = HEAD(c->bucket_queue);
1595

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1596 1597
    /* Cleanup empty buckets */
    if (EMPTY_LIST(buck->prefixes))
1598
    {
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1599 1600
      bgp_free_bucket(c, buck);
      goto again;
1601
    }
1602

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1603 1604 1605
    res = (c->afi == BGP_AF_IPV4) ?
      bgp_create_ip_reach(&s, buck, buf, end):
      bgp_create_mp_reach(&s, buck, buf, end);
1606

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1607 1608 1609 1610
    if (EMPTY_LIST(buck->prefixes))
      bgp_free_bucket(c, buck);
    else
      bgp_defer_bucket(c, buck);
1611

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1612 1613
    if (!res)
      goto again;
1614

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1615 1616
    goto done;
  }
1617

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1618 1619
  /* No more prefixes to send */
  return NULL;
1620

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1621 1622 1623
done:
  BGP_TRACE_RL(&rl_snd_update, D_PACKETS, "Sending UPDATE");
  lp_flush(s.pool);
1624

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1625
  return res;
1626 1627
}

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662
static byte *
bgp_create_ip_end_mark(struct bgp_channel *c UNUSED, byte *buf)
{
  /* Empty update packet */
  put_u32(buf, 0);

  return buf+4;
}

static byte *
bgp_create_mp_end_mark(struct bgp_channel *c, byte *buf)
{
  put_u16(buf+0, 0);
  put_u16(buf+2, 6);		/* length 4--9 */

  /* Empty MP_UNREACH_NLRI atribute */
  buf[4] = BAF_OPTIONAL;
  buf[5] = BA_MP_UNREACH_NLRI;
  buf[6] = 3;			/* Length 7--9 */
  put_af3(buf+7, c->afi);

  return buf+10;
}

static byte *
bgp_create_end_mark(struct bgp_channel *c, byte *buf)
{
  struct bgp_proto *p = (void *) c->c.proto;

  BGP_TRACE(D_PACKETS, "Sending END-OF-RIB");

  return (c->afi == BGP_AF_IPV4) ?
    bgp_create_ip_end_mark(c, buf):
    bgp_create_mp_end_mark(c, buf);
}
1663 1664

static inline void
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1665
bgp_rx_end_mark(struct bgp_parse_state *s, u32 afi)
1666
{
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1667
  struct bgp_proto *p = s->proto;
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1668 1669
  struct bgp_channel *c = bgp_get_channel(p, afi);

1670 1671
  BGP_TRACE(D_PACKETS, "Got END-OF-RIB");

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1672
  if (!c)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1673
    DISCARD(BAD_AFI, BGP_AFI(afi), BGP_SAFI(afi));
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1674 1675 1676

  if (c->load_state == BFS_LOADING)
    c->load_state = BFS_NONE;
1677 1678

  if (p->p.gr_recovery)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691
    channel_graceful_restart_unlock(&c->c);

  if (c->gr_active)
    bgp_graceful_restart_done(c);
}

static inline void
bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_list *ea, byte *nh, uint nh_len)
{
  struct bgp_channel *c = bgp_get_channel(s->proto, afi);
  rta *a = NULL;

  if (!c)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1692
    DISCARD(BAD_AFI, BGP_AFI(afi), BGP_SAFI(afi));
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795

  s->channel = c;
  s->add_path = c->add_path_rx;

  s->last_id = 0;
  s->last_src = s->proto->p.main_source;

  /*
   * IPv4 BGP and MP-BGP may be used together in one update, therefore we do not
   * add BA_NEXT_HOP in bgp_decode_attrs(), but we add it here independently for
   * IPv4 BGP and MP-BGP. We undo the attribute (and possibly others attached by
   * decode_next_hop hooks) by restoring a->eattrs afterwards.
   */

  if (ea)
  {
    a = alloca(sizeof(struct rta));
    memset(a, 0, sizeof(struct rta));

    a->source = RTS_BGP;
    a->scope = SCOPE_UNIVERSE;
    a->cast = RTC_UNICAST;
    a->dest = RTD_UNREACHABLE;
    a->from = s->proto->cf->remote_ip;
    a->eattrs = ea;

    c->desc->decode_next_hop(s, nh, nh_len, a);

    /* Handle withdraw during next hop decoding */
    if (s->err_withdraw)
      a = NULL;
  }

  c->desc->decode_nlri(s, nlri, len, a);

  rta_free(s->cached_rta);
  s->cached_rta = NULL;
}

static void
bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len)
{
  struct bgp_proto *p = conn->bgp;
  ea_list *ea = NULL;

  BGP_TRACE_RL(&rl_rcv_update, D_PACKETS, "Got UPDATE");

  /* Workaround for some BGP implementations that skip initial KEEPALIVE */
  if (conn->state == BS_OPENCONFIRM)
    bgp_conn_enter_established_state(conn);

  if (conn->state != BS_ESTABLISHED)
  { bgp_error(conn, 5, fsm_err_subcode[conn->state], NULL, 0); return; }

  bgp_start_timer(conn->hold_timer, conn->hold_time);

  /* Initialize parse state */
  struct bgp_parse_state s = {
    .proto = p,
    .pool = bgp_linpool,
    .as4_session = p->as4_session,
  };

  /* Parse error handler */
  if (setjmp(s.err_jmpbuf))
  {
    bgp_error(conn, 3, s.err_subcode, NULL, 0);
    goto done;
  }

  /* Check minimal length */
  if (len < 23)
  { bgp_error(conn, 1, 2, pkt+16, 2); return; }

  /* Skip fixed header */
  uint pos = 19;

  /*
   *	UPDATE message format
   *
   *	2 B	IPv4 Withdrawn Routes Length
   *	var	IPv4 Withdrawn Routes NLRI
   *	2 B	Total Path Attribute Length
   *	var	Path Attributes
   *	var	IPv4 Reachable Routes NLRI
   */

  s.ip_unreach_len = get_u16(pkt + pos);
  s.ip_unreach_nlri = pkt + pos + 2;
  pos += 2 + s.ip_unreach_len;

  if (pos + 2 > len)
    bgp_parse_error(&s, 1);

  s.attr_len = get_u16(pkt + pos);
  s.attrs = pkt + pos + 2;
  pos += 2 + s.attr_len;

  if (pos > len)
    bgp_parse_error(&s, 1);

  s.ip_reach_len = len - pos;
  s.ip_reach_nlri = pkt + pos;
1796 1797


Ondřej Zajíček's avatar
Ondřej Zajíček committed
1798 1799
  if (s.attr_len)
    ea = bgp_decode_attrs(&s, s.attrs, s.attr_len);
1800

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1801 1802
  /* Check for End-of-RIB marker */
  if (!s.attr_len && !s.ip_unreach_len && !s.ip_reach_len)
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1803
  { bgp_rx_end_mark(&s, BGP_AF_IPV4); goto done; }
1804

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1805 1806
  /* Check for MP End-of-RIB marker */
  if ((s.attr_len < 8) && !s.ip_unreach_len && !s.ip_reach_len &&
Ondřej Zajíček's avatar
Ondřej Zajíček committed
1807 1808
      !s.mp_reach_len && !s.mp_unreach_len && s.mp_unreach_af)
  { bgp_rx_end_mark(&s, s.mp_unreach_af); goto done; }
1809

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1810 1811
  if (s.ip_unreach_len)
    bgp_decode_nlri(&s, BGP_AF_IPV4, s.ip_unreach_nlri, s.ip_unreach_len, NULL, NULL, 0);
1812

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1813 1814
  if (s.mp_unreach_len)
    bgp_decode_nlri(&s, s.mp_unreach_af, s.mp_unreach_nlri, s.mp_unreach_len, NULL, NULL, 0);
1815

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1816 1817 1818
  if (s.ip_reach_len)
    bgp_decode_nlri(&s, BGP_AF_IPV4, s.ip_reach_nlri, s.ip_reach_len,
		    ea, s.ip_next_hop_data, s.ip_next_hop_len);
1819

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1820 1821 1822
  if (s.mp_reach_len)
    bgp_decode_nlri(&s, s.mp_reach_af, s.mp_reach_nlri, s.mp_reach_len,
		    ea, s.mp_next_hop_data, s.mp_next_hop_len);
1823

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1824 1825 1826 1827
done:
  rta_free(s.cached_rta);
  lp_flush(s.pool);
  return;
1828 1829 1830
}


Ondřej Zajíček's avatar
Ondřej Zajíček committed
1831 1832 1833
/*
 *	ROUTE-REFRESH
 */
1834

Ondřej Zajíček's avatar
Ondřej Zajíček committed
1835 1836
static inlin