]> git.ipfire.org Git - thirdparty/bird.git/blame - proto/bgp/packets.c
Rate limit for most abundant log messages
[thirdparty/bird.git] / proto / bgp / packets.c
CommitLineData
c01e3741
MM
1/*
2 * BIRD -- BGP Packet Processing
3 *
4 * (c) 2000 Martin Mares <mj@ucw.cz>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
85368cd4 9#undef LOCAL_DEBUG
72a6ef11 10
c01e3741
MM
11#include "nest/bird.h"
12#include "nest/iface.h"
13#include "nest/protocol.h"
14#include "nest/route.h"
11cb6202 15#include "nest/attrs.h"
c01e3741 16#include "conf/conf.h"
72a6ef11
MM
17#include "lib/unaligned.h"
18#include "lib/socket.h"
c01e3741 19
11b32d91
OZ
20#include "nest/cli.h"
21
c01e3741 22#include "bgp.h"
72a6ef11 23
cb530392
OZ
24static struct rate_limit rl_rcv_update, rl_snd_update;
25
72a6ef11
MM
26static byte *
27bgp_create_notification(struct bgp_conn *conn, byte *buf)
28{
85368cd4
MM
29 struct bgp_proto *p = conn->bgp;
30
31 BGP_TRACE(D_PACKETS, "Sending NOTIFICATION(code=%d.%d)", conn->notify_code, conn->notify_subcode);
72a6ef11
MM
32 buf[0] = conn->notify_code;
33 buf[1] = conn->notify_subcode;
efcece2d
MM
34 memcpy(buf+2, conn->notify_data, conn->notify_size);
35 return buf + 2 + conn->notify_size;
72a6ef11
MM
36}
37
11cb6202
OZ
38#ifdef IPV6
39static byte *
40bgp_put_cap_ipv6(struct bgp_conn *conn UNUSED, byte *buf)
41{
42 *buf++ = 1; /* Capability 1: Multiprotocol extensions */
43 *buf++ = 4; /* Capability data length */
44 *buf++ = 0; /* We support AF IPv6 */
45 *buf++ = BGP_AF_IPV6;
46 *buf++ = 0; /* RFU */
47 *buf++ = 1; /* and SAFI 1 */
48 return buf;
49}
50#endif
51
52static byte *
53bgp_put_cap_as4(struct bgp_conn *conn, byte *buf)
54{
55 *buf++ = 65; /* Capability 65: Support for 4-octet AS number */
56 *buf++ = 4; /* Capability data length */
57 put_u32(buf, conn->bgp->local_as);
58 return buf + 4;
59}
60
72a6ef11
MM
61static byte *
62bgp_create_open(struct bgp_conn *conn, byte *buf)
63{
85368cd4 64 struct bgp_proto *p = conn->bgp;
11cb6202
OZ
65 byte *cap;
66 int cap_len;
85368cd4
MM
67
68 BGP_TRACE(D_PACKETS, "Sending OPEN(ver=%d,as=%d,hold=%d,id=%08x)",
69 BGP_VERSION, p->local_as, p->cf->hold_time, p->local_id);
72a6ef11 70 buf[0] = BGP_VERSION;
11cb6202 71 put_u16(buf+1, (p->local_as < 0xFFFF) ? p->local_as : AS_TRANS);
85368cd4
MM
72 put_u16(buf+3, p->cf->hold_time);
73 put_u32(buf+5, p->local_id);
165a6227
OZ
74
75 if (conn->start_state == BSS_CONNECT_NOCAP)
76 {
77 BGP_TRACE(D_PACKETS, "Skipping capabilities");
78 buf[9] = 0;
79 return buf + 10;
80 }
81
11cb6202
OZ
82 /* Skipped 3 B for length field and Capabilities parameter header */
83 cap = buf + 12;
84
85#ifdef IPV6
86 cap = bgp_put_cap_ipv6(conn, cap);
8c92bf6a 87#endif
165a6227 88 if (conn->want_as4_support)
11cb6202
OZ
89 cap = bgp_put_cap_as4(conn, cap);
90
91 cap_len = cap - buf - 12;
92 if (cap_len > 0)
93 {
94 buf[9] = cap_len + 2; /* Optional params len */
95 buf[10] = 2; /* Option: Capability list */
96 buf[11] = cap_len; /* Option length */
97 return cap;
98 }
99 else
100 {
101 buf[9] = 0; /* No optional parameters */
102 return buf + 10;
103 }
72a6ef11
MM
104}
105
f421cfdd
MM
106static unsigned int
107bgp_encode_prefixes(struct bgp_proto *p, byte *w, struct bgp_bucket *buck, unsigned int remains)
108{
109 byte *start = w;
110 ip_addr a;
111 int bytes;
112
113 while (!EMPTY_LIST(buck->prefixes) && remains >= 5)
114 {
115 struct bgp_prefix *px = SKIP_BACK(struct bgp_prefix, bucket_node, HEAD(buck->prefixes));
116 DBG("\tDequeued route %I/%d\n", px->n.prefix, px->n.pxlen);
117 *w++ = px->n.pxlen;
118 bytes = (px->n.pxlen + 7) / 8;
119 a = px->n.prefix;
120 ipa_hton(a);
121 memcpy(w, &a, bytes);
122 w += bytes;
0c3588bf 123 remains -= bytes + 1;
f421cfdd
MM
124 rem_node(&px->bucket_node);
125 fib_delete(&p->prefix_fib, px);
126 }
127 return w - start;
128}
129
1c1da87b
MM
130#ifndef IPV6 /* IPv4 version */
131
72a6ef11
MM
132static byte *
133bgp_create_update(struct bgp_conn *conn, byte *buf)
134{
85368cd4 135 struct bgp_proto *p = conn->bgp;
f421cfdd
MM
136 struct bgp_bucket *buck;
137 int remains = BGP_MAX_PACKET_LENGTH - BGP_HEADER_LENGTH - 4;
cf3d6470 138 byte *w;
f421cfdd
MM
139 int wd_size = 0;
140 int r_size = 0;
cf3d6470 141 int a_size = 0;
f421cfdd 142
f421cfdd 143 w = buf+2;
85368cd4 144 if ((buck = p->withdraw_bucket) && !EMPTY_LIST(buck->prefixes))
f421cfdd
MM
145 {
146 DBG("Withdrawn routes:\n");
85368cd4 147 wd_size = bgp_encode_prefixes(p, w, buck, remains);
f421cfdd
MM
148 w += wd_size;
149 remains -= wd_size;
150 }
151 put_u16(buf, wd_size);
3fdbafb6 152
f421cfdd
MM
153 if (remains >= 2048)
154 {
85368cd4 155 while ((buck = (struct bgp_bucket *) HEAD(p->bucket_queue))->send_node.next)
f421cfdd
MM
156 {
157 if (EMPTY_LIST(buck->prefixes))
158 {
159 DBG("Deleting empty bucket %p\n", buck);
160 rem_node(&buck->send_node);
85368cd4 161 bgp_free_bucket(p, buck);
f421cfdd
MM
162 continue;
163 }
164 DBG("Processing bucket %p\n", buck);
11cb6202 165 a_size = bgp_encode_attrs(p, w+2, buck->eattrs, 1024);
cf3d6470
MM
166 put_u16(w, a_size);
167 w += a_size + 2;
168 r_size = bgp_encode_prefixes(p, w, buck, remains - a_size);
f421cfdd
MM
169 w += r_size;
170 break;
171 }
172 }
507eea4c 173 if (!a_size) /* Attributes not already encoded */
f421cfdd
MM
174 {
175 put_u16(w, 0);
176 w += 2;
177 }
d2a7c0e9
MM
178 if (wd_size || r_size)
179 {
cb530392 180 BGP_TRACE_RL(&rl_snd_update, D_PACKETS, "Sending UPDATE");
d2a7c0e9
MM
181 return w;
182 }
183 else
184 return NULL;
72a6ef11
MM
185}
186
1c1da87b
MM
187#else /* IPv6 version */
188
189static byte *
190bgp_create_update(struct bgp_conn *conn, byte *buf)
191{
cf3d6470
MM
192 struct bgp_proto *p = conn->bgp;
193 struct bgp_bucket *buck;
194 int size, is_ll;
195 int remains = BGP_MAX_PACKET_LENGTH - BGP_HEADER_LENGTH - 4;
196 byte *w, *tmp, *tstart;
197 ip_addr ip, ip_ll;
198 ea_list *ea;
199 eattr *nh;
200 neighbor *n;
201
cf3d6470
MM
202 put_u16(buf, 0);
203 w = buf+4;
204
205 if ((buck = p->withdraw_bucket) && !EMPTY_LIST(buck->prefixes))
206 {
207 DBG("Withdrawn routes:\n");
4847a894 208 tmp = bgp_attach_attr_wa(&ea, bgp_linpool, BA_MP_UNREACH_NLRI, remains-8);
cf3d6470
MM
209 *tmp++ = 0;
210 *tmp++ = BGP_AF_IPV6;
211 *tmp++ = 1;
212 ea->attrs[0].u.ptr->length = bgp_encode_prefixes(p, tmp, buck, remains-11);
11cb6202 213 size = bgp_encode_attrs(p, w, ea, remains);
cf3d6470
MM
214 w += size;
215 remains -= size;
216 }
217
218 if (remains >= 2048)
219 {
220 while ((buck = (struct bgp_bucket *) HEAD(p->bucket_queue))->send_node.next)
221 {
222 if (EMPTY_LIST(buck->prefixes))
223 {
224 DBG("Deleting empty bucket %p\n", buck);
225 rem_node(&buck->send_node);
226 bgp_free_bucket(p, buck);
227 continue;
228 }
229 DBG("Processing bucket %p\n", buck);
11cb6202 230 size = bgp_encode_attrs(p, w, buck->eattrs, 1024);
cf3d6470
MM
231 w += size;
232 remains -= size;
4847a894 233 tstart = tmp = bgp_attach_attr_wa(&ea, bgp_linpool, BA_MP_REACH_NLRI, remains-8);
cf3d6470
MM
234 *tmp++ = 0;
235 *tmp++ = BGP_AF_IPV6;
236 *tmp++ = 1;
237 nh = ea_find(buck->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
238 ASSERT(nh);
239 ip = *(ip_addr *) nh->u.ptr->data;
11d4474c 240 is_ll = 0;
cf3d6470 241 if (ipa_equal(ip, p->local_addr))
11d4474c
MM
242 {
243 is_ll = 1;
244 ip_ll = p->local_link;
245 }
cf3d6470
MM
246 else
247 {
248 n = neigh_find(&p->p, &ip, 0);
249 if (n && n->iface == p->neigh->iface)
11d4474c
MM
250 {
251 /* FIXME: We are assuming the global scope addresses use the lower 64 bits
252 * as an interface identifier which hasn't necessarily to be true.
253 */
254 is_ll = 1;
255 ip_ll = ipa_or(ipa_build(0xfe800000,0,0,0), ipa_and(ip, ipa_build(0,0,~0,~0)));
256 }
cf3d6470
MM
257 }
258 if (is_ll)
259 {
260 *tmp++ = 32;
cf3d6470
MM
261 ipa_hton(ip);
262 memcpy(tmp, &ip, 16);
263 ipa_hton(ip_ll);
264 memcpy(tmp+16, &ip_ll, 16);
265 tmp += 32;
266 }
267 else
268 {
269 *tmp++ = 16;
270 ipa_hton(ip);
271 memcpy(tmp, &ip, 16);
272 tmp += 16;
273 }
274 *tmp++ = 0; /* No SNPA information */
275 tmp += bgp_encode_prefixes(p, tmp, buck, remains - (8+3+32+1));
276 ea->attrs[0].u.ptr->length = tmp - tstart;
11cb6202 277 w += bgp_encode_attrs(p, w, ea, remains);
cf3d6470
MM
278 break;
279 }
280 }
281
282 size = w - (buf+4);
283 put_u16(buf+2, size);
284 lp_flush(bgp_linpool);
d2a7c0e9
MM
285 if (size)
286 {
cb530392 287 BGP_TRACE_RL(&rl_snd_update, D_PACKETS, "Sending UPDATE");
d2a7c0e9
MM
288 return w;
289 }
290 else
291 return NULL;
1c1da87b
MM
292}
293
294#endif
295
72a6ef11
MM
296static void
297bgp_create_header(byte *buf, unsigned int len, unsigned int type)
298{
299 memset(buf, 0xff, 16); /* Marker */
300 put_u16(buf+16, len);
301 buf[18] = type;
302}
303
54e55169
MM
304/**
305 * bgp_fire_tx - transmit packets
306 * @conn: connection
307 *
308 * Whenever the transmit buffers of the underlying TCP connection
309 * are free and we have any packets queued for sending, the socket functions
310 * call bgp_fire_tx() which takes care of selecting the highest priority packet
311 * queued (Notification > Keepalive > Open > Update), assembling its header
312 * and body and sending it to the connection.
313 */
3fdbafb6 314static int
72a6ef11
MM
315bgp_fire_tx(struct bgp_conn *conn)
316{
85368cd4 317 struct bgp_proto *p = conn->bgp;
72a6ef11
MM
318 unsigned int s = conn->packets_to_send;
319 sock *sk = conn->sk;
0c3588bf 320 byte *buf, *pkt, *end;
72a6ef11
MM
321 int type;
322
0c3588bf
MM
323 if (!sk)
324 {
325 conn->packets_to_send = 0;
326 return 0;
327 }
328 buf = sk->tbuf;
329 pkt = buf + BGP_HEADER_LENGTH;
330
72a6ef11
MM
331 if (s & (1 << PKT_SCHEDULE_CLOSE))
332 {
11b32d91
OZ
333 /* We can finally close connection and enter idle state */
334 bgp_conn_enter_idle_state(conn);
3fdbafb6 335 return 0;
72a6ef11
MM
336 }
337 if (s & (1 << PKT_NOTIFICATION))
338 {
339 s = 1 << PKT_SCHEDULE_CLOSE;
340 type = PKT_NOTIFICATION;
341 end = bgp_create_notification(conn, pkt);
342 }
343 else if (s & (1 << PKT_KEEPALIVE))
344 {
345 s &= ~(1 << PKT_KEEPALIVE);
346 type = PKT_KEEPALIVE;
347 end = pkt; /* Keepalives carry no data */
85368cd4 348 BGP_TRACE(D_PACKETS, "Sending KEEPALIVE");
3fdbafb6 349 bgp_start_timer(conn->keepalive_timer, conn->keepalive_time);
72a6ef11
MM
350 }
351 else if (s & (1 << PKT_OPEN))
352 {
353 s &= ~(1 << PKT_OPEN);
354 type = PKT_OPEN;
355 end = bgp_create_open(conn, pkt);
356 }
357 else if (s & (1 << PKT_UPDATE))
358 {
359 end = bgp_create_update(conn, pkt);
360 type = PKT_UPDATE;
361 if (!end)
362 {
363 conn->packets_to_send = 0;
3fdbafb6 364 return 0;
72a6ef11
MM
365 }
366 }
367 else
3fdbafb6 368 return 0;
72a6ef11
MM
369 conn->packets_to_send = s;
370 bgp_create_header(buf, end - buf, type);
3fdbafb6 371 return sk_send(sk, end - buf);
72a6ef11
MM
372}
373
54e55169
MM
374/**
375 * bgp_schedule_packet - schedule a packet for transmission
376 * @conn: connection
377 * @type: packet type
378 *
379 * Schedule a packet of type @type to be sent as soon as possible.
380 */
72a6ef11
MM
381void
382bgp_schedule_packet(struct bgp_conn *conn, int type)
383{
384 DBG("BGP: Scheduling packet type %d\n", type);
385 conn->packets_to_send |= 1 << type;
0c3588bf 386 if (conn->sk && conn->sk->tpos == conn->sk->tbuf)
11b32d91
OZ
387 ev_schedule(conn->tx_ev);
388}
389
390void
391bgp_kick_tx(void *vconn)
392{
393 struct bgp_conn *conn = vconn;
394
395 DBG("BGP: kicking TX\n");
396 while (bgp_fire_tx(conn))
397 ;
72a6ef11
MM
398}
399
400void
401bgp_tx(sock *sk)
402{
403 struct bgp_conn *conn = sk->data;
404
405 DBG("BGP: TX hook\n");
3fdbafb6
MM
406 while (bgp_fire_tx(conn))
407 ;
408}
409
11cb6202
OZ
410/* Capatibility negotiation as per RFC 2842 */
411
412void
413bgp_parse_capabilities(struct bgp_conn *conn, byte *opt, int len)
414{
415 struct bgp_proto *p = conn->bgp;
416 int cl;
417 u32 as;
418
419 while (len > 0)
420 {
421 if (len < 2 || len < 2 + opt[1])
422 goto err;
423
424 cl = opt[1];
425
426 switch (opt[0])
427 {
428 case 65:
429 if (cl != 4)
430 goto err;
165a6227
OZ
431 conn->peer_as4_support = 1;
432 if (conn->want_as4_support)
11cb6202
OZ
433 conn->advertised_as = get_u32(opt + 2);
434 break;
435
436 /* We can safely ignore all other capabilities */
437 }
438 len -= 2 + cl;
439 opt += 2 + cl;
440 }
441 return;
442
443 err:
444 bgp_error(conn, 2, 0, NULL, 0);
445 return;
446}
447
a47a0108
MM
448static int
449bgp_parse_options(struct bgp_conn *conn, byte *opt, int len)
450{
11cb6202
OZ
451 int ol;
452
a47a0108
MM
453 while (len > 0)
454 {
455 if (len < 2 || len < 2 + opt[1])
efcece2d 456 { bgp_error(conn, 2, 0, NULL, 0); return 0; }
a47a0108
MM
457#ifdef LOCAL_DEBUG
458 {
459 int i;
460 DBG("\tOption %02x:", opt[0]);
461 for(i=0; i<opt[1]; i++)
462 DBG(" %02x", opt[2+i]);
463 DBG("\n");
464 }
465#endif
11cb6202
OZ
466
467 ol = opt[1];
a47a0108
MM
468 switch (opt[0])
469 {
470 case 2:
11cb6202 471 bgp_parse_capabilities(conn, opt + 2, ol);
a47a0108 472 break;
11cb6202 473
a47a0108
MM
474 default:
475 /*
476 * BGP specs don't tell us to send which option
477 * we didn't recognize, but it's common practice
478 * to do so. Also, capability negotiation with
479 * Cisco routers doesn't work without that.
480 */
11cb6202 481 bgp_error(conn, 2, 4, opt, ol);
a47a0108
MM
482 return 0;
483 }
11cb6202
OZ
484 len -= 2 + ol;
485 opt += 2 + ol;
a47a0108
MM
486 }
487 return 0;
488}
489
3fdbafb6
MM
490static void
491bgp_rx_open(struct bgp_conn *conn, byte *pkt, int len)
492{
b552ecc4 493 struct bgp_conn *other;
3fdbafb6
MM
494 struct bgp_proto *p = conn->bgp;
495 struct bgp_config *cf = p->cf;
11cb6202 496 unsigned hold;
3fdbafb6
MM
497 u32 id;
498
499 /* Check state */
500 if (conn->state != BS_OPENSENT)
11b32d91 501 { bgp_error(conn, 5, 0, NULL, 0); return; }
3fdbafb6
MM
502
503 /* Check message contents */
504 if (len < 29 || len != 29 + pkt[28])
efcece2d 505 { bgp_error(conn, 1, 2, pkt+16, 2); return; }
3fdbafb6 506 if (pkt[19] != BGP_VERSION)
efcece2d 507 { bgp_error(conn, 2, 1, pkt+19, 1); return; } /* RFC 1771 says 16 bits, draft-09 tells to use 8 */
11cb6202 508 conn->advertised_as = get_u16(pkt+20);
3fdbafb6
MM
509 hold = get_u16(pkt+22);
510 id = get_u32(pkt+24);
11cb6202
OZ
511 BGP_TRACE(D_PACKETS, "Got OPEN(as=%d,hold=%d,id=%08x)", conn->advertised_as, hold, id);
512
a47a0108
MM
513 if (bgp_parse_options(conn, pkt+29, pkt[28]))
514 return;
11cb6202
OZ
515
516 if (hold > 0 && hold < 3)
517 { bgp_error(conn, 2, 6, pkt+22, 2); return; }
518
3fdbafb6 519 if (!id || id == 0xffffffff || id == p->local_id)
efcece2d 520 { bgp_error(conn, 2, 3, pkt+24, -4); return; }
3fdbafb6 521
11cb6202
OZ
522 if (conn->advertised_as != p->remote_as)
523 {
524 bgp_error(conn, 2, 2, (byte *) &(conn->advertised_as), -4); return;
525 }
526
b552ecc4
MM
527 /* Check the other connection */
528 other = (conn == &p->outgoing_conn) ? &p->incoming_conn : &p->outgoing_conn;
529 switch (other->state)
530 {
531 case BS_IDLE:
b552ecc4
MM
532 case BS_CONNECT:
533 case BS_ACTIVE:
534 case BS_OPENSENT:
11b32d91 535 case BS_CLOSE:
b552ecc4
MM
536 break;
537 case BS_OPENCONFIRM:
538 if ((p->local_id < id) == (conn == &p->incoming_conn))
539 {
540 /* Should close the other connection */
85368cd4 541 BGP_TRACE(D_EVENTS, "Connection collision, giving up the other connection");
efcece2d 542 bgp_error(other, 6, 0, NULL, 0);
b552ecc4
MM
543 break;
544 }
545 /* Fall thru */
546 case BS_ESTABLISHED:
547 /* Should close this connection */
85368cd4 548 BGP_TRACE(D_EVENTS, "Connection collision, giving up this connection");
efcece2d 549 bgp_error(conn, 6, 0, NULL, 0);
b552ecc4
MM
550 return;
551 default:
552 bug("bgp_rx_open: Unknown state");
553 }
554
3fdbafb6 555 /* Update our local variables */
11b32d91 556 conn->hold_time = MIN(hold, p->cf->hold_time);
3fdbafb6 557 conn->keepalive_time = p->cf->keepalive_time ? : conn->hold_time / 3;
3fdbafb6 558 p->remote_id = id;
165a6227
OZ
559 p->as4_session = conn->want_as4_support && conn->peer_as4_support;
560
11b32d91 561 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, p->as4_session);
3fdbafb6
MM
562
563 bgp_schedule_packet(conn, PKT_KEEPALIVE);
564 bgp_start_timer(conn->hold_timer, conn->hold_time);
565 conn->state = BS_OPENCONFIRM;
566}
567
973399ae
MM
568#define DECODE_PREFIX(pp, ll) do { \
569 int b = *pp++; \
570 int q; \
973399ae 571 ll--; \
1c1da87b 572 if (b > BITS_PER_IP_ADDRESS) { err=10; goto bad; } \
973399ae 573 q = (b+7) / 8; \
1c1da87b 574 if (ll < q) { err=1; goto bad; } \
c00d31be 575 memcpy(&prefix, pp, q); \
973399ae
MM
576 pp += q; \
577 ll -= q; \
f421cfdd
MM
578 ipa_ntoh(prefix); \
579 prefix = ipa_and(prefix, ipa_mkmask(b)); \
c00d31be 580 pxlen = b; \
973399ae
MM
581} while (0)
582
1c1da87b
MM
583static inline int
584bgp_get_nexthop(struct bgp_proto *bgp, rta *a)
585{
586 neighbor *neigh;
587 ip_addr nexthop;
588 struct eattr *nh = ea_find(a->eattrs, EA_CODE(EAP_BGP, BA_NEXT_HOP));
589 ASSERT(nh);
590 nexthop = *(ip_addr *) nh->u.ptr->data;
bc00185e
MM
591 neigh = neigh_find(&bgp->p, &nexthop, 0);
592 if (neigh)
1c1da87b 593 {
bc00185e
MM
594 if (neigh->scope == SCOPE_HOST)
595 {
596 DBG("BGP: Loop!\n");
597 return 0;
598 }
1c1da87b 599 }
bc00185e
MM
600 else
601 neigh = bgp->neigh;
1c1da87b
MM
602 a->gw = neigh->addr;
603 a->iface = neigh->iface;
604 return 1;
605}
606
607#ifndef IPV6 /* IPv4 version */
608
3fdbafb6 609static void
1c1da87b
MM
610bgp_do_rx_update(struct bgp_conn *conn,
611 byte *withdrawn, int withdrawn_len,
612 byte *nlri, int nlri_len,
613 byte *attrs, int attr_len)
3fdbafb6 614{
85368cd4 615 struct bgp_proto *p = conn->bgp;
1c1da87b
MM
616 rta *a0;
617 rta *a = NULL;
c00d31be 618 ip_addr prefix;
c00d31be 619 net *n;
1c1da87b 620 int err = 0, pxlen;
973399ae
MM
621
622 /* Withdraw routes */
623 while (withdrawn_len)
624 {
625 DECODE_PREFIX(withdrawn, withdrawn_len);
c00d31be 626 DBG("Withdraw %I/%d\n", prefix, pxlen);
85368cd4
MM
627 if (n = net_find(p->p.table, prefix, pxlen))
628 rte_update(p->p.table, n, &p->p, NULL);
973399ae
MM
629 }
630
f94557de
MM
631 if (!attr_len && !nlri_len) /* shortcut */
632 return;
633
2a9e064d 634 a0 = bgp_decode_attrs(conn, attrs, attr_len, bgp_linpool, nlri_len);
1c1da87b 635 if (a0 && nlri_len && bgp_get_nexthop(p, a0))
973399ae 636 {
2a9e064d 637 a = rta_lookup(a0);
c00d31be 638 while (nlri_len)
973399ae 639 {
c00d31be 640 rte *e;
f8809249 641 DECODE_PREFIX(nlri, nlri_len);
c00d31be 642 DBG("Add %I/%d\n", prefix, pxlen);
f8809249 643 e = rte_get_temp(rta_clone(a));
85368cd4 644 n = net_get(p->p.table, prefix, pxlen);
c00d31be
MM
645 e->net = n;
646 e->pflags = 0;
85368cd4 647 rte_update(p->p.table, n, &p->p, e);
973399ae 648 }
973399ae 649 }
1c1da87b
MM
650bad:
651 if (a)
652 rta_free(a);
653 if (err)
654 bgp_error(conn, 3, err, NULL, 0);
f8809249 655 return;
1c1da87b 656}
f8809249 657
1c1da87b
MM
658#else /* IPv6 version */
659
660#define DO_NLRI(name) \
661 start = x = p->name##_start; \
662 len = len0 = p->name##_len; \
663 if (len) \
664 { \
665 if (len < 3) goto bad; \
666 af = get_u16(x); \
667 sub = x[2]; \
668 x += 3; \
669 len -= 3; \
670 DBG("\tNLRI AF=%d sub=%d len=%d\n", af, sub, len);\
671 } \
672 else \
673 af = 0; \
674 if (af == BGP_AF_IPV6)
675
676static void
677bgp_do_rx_update(struct bgp_conn *conn,
678 byte *withdrawn, int withdrawn_len,
679 byte *nlri, int nlri_len,
680 byte *attrs, int attr_len)
681{
682 struct bgp_proto *p = conn->bgp;
683 byte *start, *x;
684 int len, len0;
685 unsigned af, sub;
686 rta *a0;
687 rta *a = NULL;
688 ip_addr prefix;
689 net *n;
690 rte e;
691 int err = 0, pxlen;
692
693 p->mp_reach_len = 0;
694 p->mp_unreach_len = 0;
695 a0 = bgp_decode_attrs(conn, attrs, attr_len, bgp_linpool, 0);
696 if (!a0)
697 return;
698
699 DO_NLRI(mp_unreach)
700 {
701 while (len)
702 {
703 DECODE_PREFIX(x, len);
704 DBG("Withdraw %I/%d\n", prefix, pxlen);
705 if (n = net_find(p->p.table, prefix, pxlen))
706 rte_update(p->p.table, n, &p->p, NULL);
707 }
708 }
709
710 DO_NLRI(mp_reach)
711 {
1c1da87b
MM
712 int i;
713
714 /* Create fake NEXT_HOP attribute */
715 if (len < 1 || (*x != 16 && *x != 32) || len < *x + 2)
716 goto bad;
1389f369 717 memcpy(bgp_attach_attr_wa(&a0->eattrs, bgp_linpool, BA_NEXT_HOP, 16), x+1, 16);
60a72ed4 718 len -= *x + 2;
1c1da87b
MM
719 x += *x + 1;
720
721 /* Ignore SNPA info */
722 i = *x++;
723 while (i--)
724 {
725 if (len < 1 || len < 1 + *x)
726 goto bad;
727 len -= *x + 1;
728 x += *x + 1;
729 }
730
731 if (bgp_get_nexthop(p, a0))
732 {
733 a = rta_lookup(a0);
734 while (len)
735 {
736 rte *e;
737 DECODE_PREFIX(x, len);
738 DBG("Add %I/%d\n", prefix, pxlen);
739 e = rte_get_temp(rta_clone(a));
740 n = net_get(p->p.table, prefix, pxlen);
741 e->net = n;
742 e->pflags = 0;
743 rte_update(p->p.table, n, &p->p, e);
744 }
745 rta_free(a);
746 }
747 }
748
749 return;
750
751bad:
752 bgp_error(conn, 3, 9, start, len0);
f8809249
MM
753 if (a)
754 rta_free(a);
1c1da87b
MM
755 return;
756}
757
758#endif
759
760static void
761bgp_rx_update(struct bgp_conn *conn, byte *pkt, int len)
762{
763 struct bgp_proto *p = conn->bgp;
764 byte *withdrawn, *attrs, *nlri;
765 int withdrawn_len, attr_len, nlri_len;
766
cb530392
OZ
767 BGP_TRACE_RL(&rl_rcv_update, D_PACKETS, "Got UPDATE");
768
1c1da87b
MM
769 if (conn->state != BS_ESTABLISHED)
770 { bgp_error(conn, 5, 0, NULL, 0); return; }
771 bgp_start_timer(conn->hold_timer, conn->hold_time);
772
773 /* Find parts of the packet and check sizes */
774 if (len < 23)
775 {
776 bgp_error(conn, 1, 2, pkt+16, 2);
777 return;
778 }
779 withdrawn = pkt + 21;
780 withdrawn_len = get_u16(pkt + 19);
781 if (withdrawn_len + 23 > len)
782 goto malformed;
783 attrs = withdrawn + withdrawn_len + 2;
784 attr_len = get_u16(attrs - 2);
785 if (withdrawn_len + attr_len + 23 > len)
786 goto malformed;
787 nlri = attrs + attr_len;
788 nlri_len = len - withdrawn_len - attr_len - 23;
789 if (!attr_len && nlri_len)
790 goto malformed;
791 DBG("Sizes: withdrawn=%d, attrs=%d, NLRI=%d\n", withdrawn_len, attr_len, nlri_len);
792
793 lp_flush(bgp_linpool);
794
795 bgp_do_rx_update(conn, withdrawn, withdrawn_len, nlri, nlri_len, attrs, attr_len);
796 return;
797
798malformed:
efcece2d
MM
799 bgp_error(conn, 3, 1, NULL, 0);
800}
801
802static struct {
803 byte major, minor;
804 byte *msg;
805} bgp_msg_table[] = {
806 { 1, 0, "Invalid message header" },
807 { 1, 1, "Connection not synchronized" },
808 { 1, 2, "Bad message length" },
809 { 1, 3, "Bad message type" },
810 { 2, 0, "Invalid OPEN message" },
811 { 2, 1, "Unsupported version number" },
812 { 2, 2, "Bad peer AS" },
813 { 2, 3, "Bad BGP identifier" },
814 { 2, 4, "Unsupported optional parameter" },
815 { 2, 5, "Authentication failure" },
816 { 2, 6, "Unacceptable hold time" },
11cb6202 817 { 2, 7, "Required capability missing" }, /* [RFC3392] */
efcece2d
MM
818 { 3, 0, "Invalid UPDATE message" },
819 { 3, 1, "Malformed attribute list" },
820 { 3, 2, "Unrecognized well-known attribute" },
821 { 3, 3, "Missing mandatory attribute" },
822 { 3, 4, "Invalid attribute flags" },
823 { 3, 5, "Invalid attribute length" },
824 { 3, 6, "Invalid ORIGIN attribute" },
825 { 3, 7, "AS routing loop" }, /* Deprecated */
826 { 3, 8, "Invalid NEXT_HOP attribute" },
827 { 3, 9, "Optional attribute error" },
828 { 3, 10, "Invalid network field" },
829 { 3, 11, "Malformed AS_PATH" },
830 { 4, 0, "Hold timer expired" },
831 { 5, 0, "Finite state machine error" },
165a6227
OZ
832 { 6, 0, "Cease" }, /* Subcodes are according to [RFC4486] */
833 { 6, 1, "Maximum number of prefixes reached" },
834 { 6, 2, "Administrative shutdown" },
835 { 6, 3, "Peer de-configured" },
836 { 6, 4, "Administrative reset" },
837 { 6, 5, "Connection rejected" },
838 { 6, 6, "Other configuration change" },
839 { 6, 7, "Connection collision resolution" },
840 { 6, 8, "Out of Resources" }
efcece2d
MM
841};
842
11b32d91
OZ
843/**
844 * bgp_error_dsc - return BGP error description
845 * @buff: temporary buffer
846 * @code: BGP error code
847 * @subcode: BGP error subcode
848 *
849 * bgp_error_dsc() returns error description for BGP errors
850 * which might be static string or given temporary buffer.
851 */
852const byte *
853bgp_error_dsc(byte *buff, unsigned code, unsigned subcode)
854{
855 unsigned i;
856 for (i=0; i < ARRAY_SIZE(bgp_msg_table); i++)
857 if (bgp_msg_table[i].major == code && bgp_msg_table[i].minor == subcode)
858 {
859 return bgp_msg_table[i].msg;
860 }
861
862 bsprintf(buff, "Unknown error %d.%d", code, subcode);
863 return buff;
864}
865
efcece2d
MM
866void
867bgp_log_error(struct bgp_proto *p, char *msg, unsigned code, unsigned subcode, byte *data, unsigned len)
868{
11b32d91
OZ
869 const byte *name;
870 byte namebuf[32];
efcece2d
MM
871 byte *t, argbuf[36];
872 unsigned i;
873
85733143
MM
874 if (code == 6 && !subcode) /* Don't report Cease messages */
875 return;
876
11b32d91 877 name = bgp_error_dsc(namebuf, code, subcode);
efcece2d
MM
878 t = argbuf;
879 if (len)
880 {
881 *t++ = ':';
882 *t++ = ' ';
883 if (len > 16)
884 len = 16;
885 for (i=0; i<len; i++)
886 t += bsprintf(t, "%02x", data[i]);
887 }
888 *t = 0;
889 log(L_REMOTE "%s: %s: %s%s", p->p.name, msg, name, argbuf);
3fdbafb6
MM
890}
891
892static void
893bgp_rx_notification(struct bgp_conn *conn, byte *pkt, int len)
894{
165a6227 895 struct bgp_proto *p = conn->bgp;
3fdbafb6
MM
896 if (len < 21)
897 {
efcece2d 898 bgp_error(conn, 1, 2, pkt+16, 2);
3fdbafb6
MM
899 return;
900 }
11b32d91
OZ
901
902 unsigned code = pkt[19];
903 unsigned subcode = pkt[20];
165a6227
OZ
904 int delay = 1;
905
906#ifndef IPV6
907 if ((code == 2) && ((subcode == 4) || (subcode == 7)))
908 {
909 /* Error related to capability:
910 * 4 - Peer does not support capabilities at all.
911 * 7 - Peer request some capability. Strange unless it is IPv6 only peer.
912 * We try connect without capabilities
913 */
914 BGP_TRACE(D_EVENTS, "Capability related error received, capabilities disabled");
915 conn->bgp->start_state = BSS_CONNECT_NOCAP;
916 delay = 0;
917 }
918#endif
919
11b32d91
OZ
920 bgp_log_error(conn->bgp, "Received error notification", code, subcode, pkt+21, len-21);
921 bgp_store_error(conn->bgp, conn, BE_BGP_RX, (code << 16) | subcode);
165a6227 922 if (delay) bgp_update_startup_delay(conn->bgp, conn, code, subcode);
11b32d91 923 bgp_conn_enter_close_state(conn);
3fdbafb6
MM
924 bgp_schedule_packet(conn, PKT_SCHEDULE_CLOSE);
925}
926
927static void
e21423ba 928bgp_rx_keepalive(struct bgp_conn *conn)
3fdbafb6 929{
85368cd4
MM
930 struct bgp_proto *p = conn->bgp;
931
932 BGP_TRACE(D_PACKETS, "Got KEEPALIVE");
3fdbafb6
MM
933 bgp_start_timer(conn->hold_timer, conn->hold_time);
934 switch (conn->state)
935 {
936 case BS_OPENCONFIRM:
11b32d91 937 bgp_conn_enter_established_state(conn);
3fdbafb6
MM
938 break;
939 case BS_ESTABLISHED:
940 break;
941 default:
efcece2d 942 bgp_error(conn, 5, 0, NULL, 0);
3fdbafb6
MM
943 }
944}
945
54e55169
MM
946/**
947 * bgp_rx_packet - handle a received packet
948 * @conn: BGP connection
949 * @pkt: start of the packet
950 * @len: packet size
951 *
952 * bgp_rx_packet() takes a newly received packet and calls the corresponding
953 * packet handler according to the packet type.
954 */
3fdbafb6
MM
955static void
956bgp_rx_packet(struct bgp_conn *conn, byte *pkt, unsigned len)
957{
958 DBG("BGP: Got packet %02x (%d bytes)\n", pkt[18], len);
959 switch (pkt[18])
960 {
961 case PKT_OPEN: return bgp_rx_open(conn, pkt, len);
962 case PKT_UPDATE: return bgp_rx_update(conn, pkt, len);
963 case PKT_NOTIFICATION: return bgp_rx_notification(conn, pkt, len);
e21423ba 964 case PKT_KEEPALIVE: return bgp_rx_keepalive(conn);
efcece2d 965 default: bgp_error(conn, 1, 3, pkt+18, 1);
3fdbafb6 966 }
72a6ef11
MM
967}
968
54e55169
MM
969/**
970 * bgp_rx - handle received data
971 * @sk: socket
972 * @size: amount of data received
973 *
974 * bgp_rx() is called by the socket layer whenever new data arrive from
975 * the underlying TCP connection. It assembles the data fragments to packets,
976 * checks their headers and framing and passes complete packets to
977 * bgp_rx_packet().
978 */
72a6ef11
MM
979int
980bgp_rx(sock *sk, int size)
981{
982 struct bgp_conn *conn = sk->data;
983 byte *pkt_start = sk->rbuf;
984 byte *end = pkt_start + size;
3fdbafb6 985 unsigned i, len;
72a6ef11
MM
986
987 DBG("BGP: RX hook: Got %d bytes\n", size);
988 while (end >= pkt_start + BGP_HEADER_LENGTH)
989 {
11b32d91
OZ
990 if ((conn->state == BS_CLOSE) || (conn->sk != sk))
991 return 0;
3fdbafb6
MM
992 for(i=0; i<16; i++)
993 if (pkt_start[i] != 0xff)
994 {
efcece2d 995 bgp_error(conn, 1, 1, NULL, 0);
3fdbafb6
MM
996 break;
997 }
998 len = get_u16(pkt_start+16);
999 if (len < BGP_HEADER_LENGTH || len > BGP_MAX_PACKET_LENGTH)
1000 {
efcece2d 1001 bgp_error(conn, 1, 2, pkt_start+16, 2);
3fdbafb6
MM
1002 break;
1003 }
5f532add
MM
1004 if (end < pkt_start + len)
1005 break;
1006 bgp_rx_packet(conn, pkt_start, len);
1007 pkt_start += len;
72a6ef11
MM
1008 }
1009 if (pkt_start != sk->rbuf)
1010 {
1011 memmove(sk->rbuf, pkt_start, end - pkt_start);
1012 sk->rpos = sk->rbuf + (end - pkt_start);
1013 }
1014 return 0;
1015}