Add v6 routes handling.
[l2tpns.git] / bgp.c
1 /*
2 * BGPv4
3 * Used to advertise routes for upstream (l2tp port, rather than gratiutious
4 * arp) and downstream--allowing routers to load-balance both.
5 *
6 * Implementation limitations:
7 * - We never listen for incoming connections (session always initiated by us).
8 * - Any routes advertised by the peer are accepted, but ignored.
9 * - No password support; neither RFC1771 (which no-one seems to do anyway)
10 * nor RFC2385 (which requires a kernel patch on 2.4 kernels).
11 */
12
13 char const *cvs_id_bgp = "$Id: bgp.c,v 1.12 2005/09/02 23:39:36 bodea Exp $";
14
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <string.h>
18 #include <time.h>
19 #include <errno.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
23 #include <netdb.h>
24 #include <fcntl.h>
25
26 #include "l2tpns.h"
27 #include "bgp.h"
28 #include "util.h"
29
30 static void bgp_clear(struct bgp_peer *peer);
31 static void bgp_set_retry(struct bgp_peer *peer);
32 static void bgp_cidr(in_addr_t ip, in_addr_t mask, struct bgp_ip_prefix *pfx);
33 static struct bgp_route_list *bgp_insert_route(struct bgp_route_list *head,
34 struct bgp_route_list *new);
35 static struct bgp_route6_list *bgp_insert_route6(struct bgp_route6_list *head,
36 struct bgp_route6_list *new);
37
38 static void bgp_free_routes(struct bgp_route_list *routes);
39 static void bgp_free_routes6(struct bgp_route6_list *routes);
40 static char const *bgp_msg_type_str(uint8_t type);
41 static int bgp_connect(struct bgp_peer *peer);
42 static int bgp_handle_connect(struct bgp_peer *peer);
43 static int bgp_write(struct bgp_peer *peer);
44 static int bgp_read(struct bgp_peer *peer);
45 static int bgp_handle_input(struct bgp_peer *peer);
46 static int bgp_send_open(struct bgp_peer *peer);
47 static int bgp_send_keepalive(struct bgp_peer *peer);
48 static int bgp_send_update(struct bgp_peer *peer);
49 static int bgp_send_update6(struct bgp_peer *peer);
50 static int bgp_send_notification(struct bgp_peer *peer, uint8_t code,
51 uint8_t subcode);
52 static int bgp_send_notification_full(struct bgp_peer *peer, uint8_t code,
53 uint8_t subcode, char *notification_data, uint16_t data_len);
54
55 static uint16_t our_as;
56 static struct bgp_route_list *bgp_routes = 0;
57 static struct bgp_route6_list *bgp_routes6 = 0;
58
59 int bgp_configured = 0;
60 struct bgp_peer *bgp_peers = 0;
61
62 /* prepare peer structure, globals */
63 int bgp_setup(int as)
64 {
65 int i;
66 struct bgp_peer *peer;
67
68 for (i = 0; i < BGP_NUM_PEERS; i++)
69 {
70 peer = &bgp_peers[i];
71 memset(peer, 0, sizeof(*peer));
72
73 peer->addr = INADDR_NONE;
74 peer->sock = -1;
75 peer->state = peer->next_state = Disabled;
76
77 if (!((peer->outbuf = malloc(sizeof(*peer->outbuf)))
78 && (peer->inbuf = malloc(sizeof(*peer->inbuf)))))
79 {
80 LOG(0, 0, 0, "Can't allocate buffers for bgp peer (%s)\n",
81 strerror(errno));
82
83 return 0;
84 }
85
86 peer->edata.type = FD_TYPE_BGP;
87 peer->edata.index = i;
88 peer->events = 0;
89 }
90
91 if (as < 1)
92 as = 0;
93
94 if ((our_as = as))
95 return 0;
96
97 bgp_routes = 0;
98 bgp_routes6 = 0;
99 bgp_configured = 0; /* set by bgp_start */
100
101 return 1;
102 }
103
104 /* start connection with a peer */
105 int bgp_start(struct bgp_peer *peer, char *name, int as, int keepalive,
106 int hold, int enable)
107 {
108 struct hostent *h;
109 int ibgp;
110 int i;
111 struct bgp_path_attr a;
112 char path_attrs[64];
113 char *p = path_attrs;
114 in_addr_t ip;
115 uint32_t metric = htonl(BGP_METRIC);
116 uint32_t no_export = htonl(BGP_COMMUNITY_NO_EXPORT);
117
118 if (!our_as)
119 return 0;
120
121 if (peer->state != Disabled)
122 bgp_halt(peer);
123
124 snprintf(peer->name, sizeof(peer->name), "%s", name);
125
126 if (!(h = gethostbyname(name)) || h->h_addrtype != AF_INET)
127 {
128 LOG(0, 0, 0, "Can't get address for BGP peer %s (%s)\n",
129 name, h ? "no address" : hstrerror(h_errno));
130
131 return 0;
132 }
133
134 memcpy(&peer->addr, h->h_addr, sizeof(peer->addr));
135 peer->as = as > 0 ? as : our_as;
136 ibgp = peer->as == our_as;
137
138 /* set initial timer values */
139 peer->init_keepalive = keepalive == -1 ? BGP_KEEPALIVE_TIME : keepalive;
140 peer->init_hold = hold == -1 ? BGP_HOLD_TIME : hold;
141
142 if (peer->init_hold < 3)
143 peer->init_hold = 3;
144
145 if (peer->init_keepalive * 3 > peer->init_hold)
146 peer->init_keepalive = peer->init_hold / 3;
147
148 /* clear buffers, go to Idle state */
149 peer->next_state = Idle;
150 bgp_clear(peer);
151
152 /* set initial routing state */
153 peer->routing = enable;
154
155 /* all our routes use the same attributes, so prepare it in advance */
156 if (peer->path_attrs)
157 free(peer->path_attrs);
158
159 peer->path_attr_len = 0;
160
161 /* ORIGIN */
162 a.flags = BGP_PATH_ATTR_FLAG_TRANS;
163 a.code = BGP_PATH_ATTR_CODE_ORIGIN;
164 a.data.s.len = 1;
165 a.data.s.value[0] = BGP_PATH_ATTR_CODE_ORIGIN_IGP;
166
167 #define ADD_ATTRIBUTE() do { \
168 i = BGP_PATH_ATTR_SIZE(a); \
169 memcpy(p, &a, i); \
170 p += i; \
171 peer->path_attr_len += i; } while (0)
172
173 ADD_ATTRIBUTE();
174
175 /* AS_PATH */
176 a.flags = BGP_PATH_ATTR_FLAG_TRANS;
177 a.code = BGP_PATH_ATTR_CODE_AS_PATH;
178 if (ibgp)
179 {
180 /* empty path */
181 a.data.s.len = 0;
182 }
183 else
184 {
185 /* just our AS */
186 struct {
187 uint8_t type;
188 uint8_t len;
189 uint16_t value;
190 } as_path = {
191 BGP_PATH_ATTR_CODE_AS_PATH_AS_SEQUENCE,
192 1,
193 htons(our_as),
194 };
195
196 a.data.s.len = sizeof(as_path);
197 memcpy(&a.data.s.value, &as_path, sizeof(as_path));
198 }
199
200 ADD_ATTRIBUTE();
201
202 /* MULTI_EXIT_DISC */
203 a.flags = BGP_PATH_ATTR_FLAG_OPTIONAL;
204 a.code = BGP_PATH_ATTR_CODE_MULTI_EXIT_DISC;
205 a.data.s.len = sizeof(metric);
206 memcpy(a.data.s.value, &metric, sizeof(metric));
207
208 ADD_ATTRIBUTE();
209
210 if (ibgp)
211 {
212 uint32_t local_pref = htonl(BGP_LOCAL_PREF);
213
214 /* LOCAL_PREF */
215 a.flags = BGP_PATH_ATTR_FLAG_TRANS;
216 a.code = BGP_PATH_ATTR_CODE_LOCAL_PREF;
217 a.data.s.len = sizeof(local_pref);
218 memcpy(a.data.s.value, &local_pref, sizeof(local_pref));
219
220 ADD_ATTRIBUTE();
221 }
222
223 /* COMMUNITIES */
224 a.flags = BGP_PATH_ATTR_FLAG_OPTIONAL | BGP_PATH_ATTR_FLAG_TRANS;
225 a.code = BGP_PATH_ATTR_CODE_COMMUNITIES;
226 a.data.s.len = sizeof(no_export);
227 memcpy(a.data.s.value, &no_export, sizeof(no_export));
228
229 ADD_ATTRIBUTE();
230
231 /* remember the len before adding NEXT_HOP */
232 peer->path_attr_len_without_nexthop = peer->path_attr_len;
233
234 /* NEXT_HOP */
235 a.flags = BGP_PATH_ATTR_FLAG_TRANS;
236 a.code = BGP_PATH_ATTR_CODE_NEXT_HOP;
237 ip = my_address; /* we're it */
238 a.data.s.len = sizeof(ip);
239 memcpy(a.data.s.value, &ip, sizeof(ip));
240
241 ADD_ATTRIBUTE();
242
243 if (!(peer->path_attrs = malloc(peer->path_attr_len)))
244 {
245 LOG(0, 0, 0, "Can't allocate path_attrs for %s (%s)\n",
246 name, strerror(errno));
247
248 return 0;
249 }
250
251 memcpy(peer->path_attrs, path_attrs, peer->path_attr_len);
252
253 LOG(4, 0, 0, "Initiating BGP connection to %s (routing %s)\n",
254 name, enable ? "enabled" : "suspended");
255
256 /* we have at least one peer configured */
257 bgp_configured = 1;
258
259 /* connect */
260 return bgp_connect(peer);
261 }
262
263 /* clear counters, timers, routes and buffers; close socket; move to
264 next_state, which may be Disabled or Idle */
265 static void bgp_clear(struct bgp_peer *peer)
266 {
267 if (peer->sock != -1)
268 {
269 close(peer->sock);
270 peer->sock = -1;
271 }
272
273 peer->keepalive_time = 0;
274 peer->expire_time = 0;
275
276 peer->keepalive = peer->init_keepalive;
277 peer->hold = peer->init_hold;
278
279 bgp_free_routes(peer->routes);
280 peer->routes = 0;
281 bgp_free_routes6(peer->routes6);
282 peer->routes6 = 0;
283
284 peer->outbuf->packet.header.len = 0;
285 peer->outbuf->done = 0;
286 peer->inbuf->packet.header.len = 0;
287 peer->inbuf->done = 0;
288
289 peer->cli_flag = 0;
290 peer->events = 0;
291
292 if (peer->state != peer->next_state)
293 {
294 peer->state = peer->next_state;
295 peer->state_time = time_now;
296
297 LOG(4, 0, 0, "BGP peer %s: state %s\n", peer->name,
298 bgp_state_str(peer->next_state));
299 }
300 }
301
302 /* initiate a clean shutdown */
303 void bgp_stop(struct bgp_peer *peer)
304 {
305 LOG(4, 0, 0, "Terminating BGP connection to %s\n", peer->name);
306 bgp_send_notification(peer, BGP_ERR_CEASE, 0);
307 }
308
309 /* drop connection (if any) and set state to Disabled */
310 void bgp_halt(struct bgp_peer *peer)
311 {
312 LOG(4, 0, 0, "Aborting BGP connection to %s\n", peer->name);
313 peer->next_state = Disabled;
314 bgp_clear(peer);
315 }
316
317 /* drop connection (if any) and set to Idle for connection retry */
318 int bgp_restart(struct bgp_peer *peer)
319 {
320 peer->next_state = Idle;
321 bgp_clear(peer);
322
323 /* restart now */
324 peer->retry_time = time_now;
325 peer->retry_count = 0;
326
327 /* connect */
328 return bgp_connect(peer);
329 }
330
331 static void bgp_set_retry(struct bgp_peer *peer)
332 {
333 if (peer->retry_count++ < BGP_MAX_RETRY)
334 {
335 peer->retry_time = time_now + (BGP_RETRY_BACKOFF * peer->retry_count);
336 peer->next_state = Idle;
337 bgp_clear(peer);
338 }
339 else
340 bgp_halt(peer); /* give up */
341 }
342
343 /* convert ip/mask to CIDR notation */
344 static void bgp_cidr(in_addr_t ip, in_addr_t mask, struct bgp_ip_prefix *pfx)
345 {
346 int i;
347 uint32_t b;
348
349 /* convert to prefix notation */
350 pfx->len = 32;
351 pfx->prefix = ip;
352
353 if (!mask) /* bogus */
354 mask = 0xffffffff;
355
356 for (i = 0; i < 32 && ((b = ntohl(1 << i)), !(mask & b)); i++)
357 {
358 pfx->len--;
359 pfx->prefix &= ~b;
360 }
361 }
362
363 /* insert route into list; sorted */
364 static struct bgp_route_list *bgp_insert_route(struct bgp_route_list *head,
365 struct bgp_route_list *new)
366 {
367 struct bgp_route_list *p = head;
368 struct bgp_route_list *e = 0;
369
370 while (p && memcmp(&p->dest, &new->dest, sizeof(p->dest)) < 0)
371 {
372 e = p;
373 p = p->next;
374 }
375
376 if (e)
377 {
378 new->next = e->next;
379 e->next = new;
380 }
381 else
382 {
383 new->next = head;
384 head = new;
385 }
386
387 return head;
388 }
389
390 /* insert route6 into list; sorted */
391 static struct bgp_route6_list *bgp_insert_route6(struct bgp_route6_list *head,
392 struct bgp_route6_list *new)
393 {
394 struct bgp_route6_list *p = head;
395 struct bgp_route6_list *e = 0;
396
397 while (p && memcmp(&p->dest, &new->dest, sizeof(p->dest)) < 0)
398 {
399 e = p;
400 p = p->next;
401 }
402
403 if (e)
404 {
405 new->next = e->next;
406 e->next = new;
407 }
408 else
409 {
410 new->next = head;
411 head = new;
412 }
413
414 return head;
415 }
416
417 /* add route to list for peers */
418 /*
419 * Note: this doesn't do route aggregation, nor drop routes if a less
420 * specific match already exists (partly because I'm lazy, but also so
421 * that if that route is later deleted we don't have to be concerned
422 * about adding back the more specific one).
423 */
424 int bgp_add_route(in_addr_t ip, in_addr_t mask)
425 {
426 struct bgp_route_list *r = bgp_routes;
427 struct bgp_route_list add;
428 int i;
429
430 bgp_cidr(ip, mask, &add.dest);
431 add.next = 0;
432
433 /* check for duplicate */
434 while (r)
435 {
436 i = memcmp(&r->dest, &add.dest, sizeof(r->dest));
437 if (!i)
438 return 1; /* already covered */
439
440 if (i > 0)
441 break;
442
443 r = r->next;
444 }
445
446 /* insert into route list; sorted */
447 if (!(r = malloc(sizeof(*r))))
448 {
449 LOG(0, 0, 0, "Can't allocate route for %s/%d (%s)\n",
450 fmtaddr(add.dest.prefix, 0), add.dest.len, strerror(errno));
451
452 return 0;
453 }
454
455 memcpy(r, &add, sizeof(*r));
456 bgp_routes = bgp_insert_route(bgp_routes, r);
457
458 /* flag established peers for update */
459 for (i = 0; i < BGP_NUM_PEERS; i++)
460 if (bgp_peers[i].state == Established)
461 bgp_peers[i].update_routes = 1;
462
463 LOG(4, 0, 0, "Registered BGP route %s/%d\n",
464 fmtaddr(add.dest.prefix, 0), add.dest.len);
465
466 return 1;
467 }
468
469 /* add route to list for peers */
470 /*
471 * Note: same provisions as above
472 */
473 int bgp_add_route6(struct in6_addr ip, int prefixlen)
474 {
475 struct bgp_route6_list *r = bgp_routes6;
476 struct bgp_route6_list add;
477 int i;
478 char ipv6addr[INET6_ADDRSTRLEN];
479
480 memcpy(&add.dest.prefix, &ip.s6_addr, 16);
481 add.dest.len = prefixlen;
482 add.next = 0;
483
484 /* check for duplicate */
485 while (r)
486 {
487 i = memcmp(&r->dest, &add.dest, sizeof(r->dest));
488 if (!i)
489 return 1; /* already covered */
490
491 if (i > 0)
492 break;
493
494 r = r->next;
495 }
496
497 /* insert into route list; sorted */
498 if (!(r = malloc(sizeof(*r))))
499 {
500 LOG(0, 0, 0, "Can't allocate route for %s/%d (%s)\n",
501 inet_ntop(AF_INET6, &ip, ipv6addr, INET6_ADDRSTRLEN), add.dest.len,
502 strerror(errno));
503
504 return 0;
505 }
506
507 memcpy(r, &add, sizeof(*r));
508 bgp_routes6 = bgp_insert_route6(bgp_routes6, r);
509
510 /* flag established peers for update */
511 for (i = 0; i < BGP_NUM_PEERS; i++)
512 if (bgp_peers[i].state == Established)
513 bgp_peers[i].update_routes6 = 1;
514
515 LOG(4, 0, 0, "Registered BGP route %s/%d\n",
516 inet_ntop(AF_INET6, &ip, ipv6addr, INET6_ADDRSTRLEN), add.dest.len);
517
518 return 1;
519 }
520
521 /* remove route from list for peers */
522 int bgp_del_route(in_addr_t ip, in_addr_t mask)
523 {
524 struct bgp_route_list *r = bgp_routes;
525 struct bgp_route_list *e = 0;
526 struct bgp_route_list del;
527 int i;
528
529 bgp_cidr(ip, mask, &del.dest);
530 del.next = 0;
531
532 /* find entry in routes list and remove */
533 while (r)
534 {
535 i = memcmp(&r->dest, &del.dest, sizeof(r->dest));
536 if (!i)
537 {
538 if (e)
539 e->next = r->next;
540 else
541 bgp_routes = r->next;
542
543 free(r);
544 break;
545 }
546
547 e = r;
548
549 if (i > 0)
550 r = 0; /* stop */
551 else
552 r = r->next;
553 }
554
555 /* not found */
556 if (!r)
557 return 1;
558
559 /* flag established peers for update */
560 for (i = 0; i < BGP_NUM_PEERS; i++)
561 if (bgp_peers[i].state == Established)
562 bgp_peers[i].update_routes = 1;
563
564 LOG(4, 0, 0, "Removed BGP route %s/%d\n",
565 fmtaddr(del.dest.prefix, 0), del.dest.len);
566
567 return 1;
568 }
569
570 /* remove route from list for peers */
571 int bgp_del_route6(struct in6_addr ip, int prefixlen)
572 {
573 struct bgp_route6_list *r = bgp_routes6;
574 struct bgp_route6_list *e = 0;
575 struct bgp_route6_list del;
576 int i;
577 char ipv6addr[INET6_ADDRSTRLEN];
578
579 memcpy(&del.dest.prefix, &ip.s6_addr, 16);
580 del.dest.len = prefixlen;
581 del.next = 0;
582
583 /* find entry in routes list and remove */
584 while (r)
585 {
586 i = memcmp(&r->dest, &del.dest, sizeof(r->dest));
587 if (!i)
588 {
589 if (e)
590 e->next = r->next;
591 else
592 bgp_routes6 = r->next;
593
594 free(r);
595 break;
596 }
597
598 e = r;
599
600 if (i > 0)
601 r = 0; /* stop */
602 else
603 r = r->next;
604 }
605
606 /* not found */
607 if (!r)
608 return 1;
609
610 /* flag established peers for update */
611 for (i = 0; i < BGP_NUM_PEERS; i++)
612 if (bgp_peers[i].state == Established)
613 bgp_peers[i].update_routes6 = 1;
614
615 LOG(4, 0, 0, "Removed BGP route %s/%d\n",
616 inet_ntop(AF_INET6, &ip, ipv6addr, INET6_ADDRSTRLEN), del.dest.len);
617
618 return 1;
619 }
620
621 /* enable or disable routing */
622 void bgp_enable_routing(int enable)
623 {
624 int i;
625
626 for (i = 0; i < BGP_NUM_PEERS; i++)
627 {
628 bgp_peers[i].routing = enable;
629
630 /* flag established peers for update */
631 if (bgp_peers[i].state == Established)
632 bgp_peers[i].update_routes = 1;
633 }
634
635 LOG(4, 0, 0, "%s BGP routing\n", enable ? "Enabled" : "Suspended");
636 }
637
638 #ifdef HAVE_EPOLL
639 # include <sys/epoll.h>
640 #else
641 # include "fake_epoll.h"
642 #endif
643
644 /* return a bitmask of the events required to poll this peer's fd */
645 int bgp_set_poll()
646 {
647 int i;
648
649 if (!bgp_configured)
650 return 0;
651
652 for (i = 0; i < BGP_NUM_PEERS; i++)
653 {
654 struct bgp_peer *peer = &bgp_peers[i];
655 int events = 0;
656
657 if (peer->state == Disabled || peer->state == Idle)
658 continue;
659
660 if (peer->inbuf->done < BGP_MAX_PACKET_SIZE)
661 events |= EPOLLIN;
662
663 if (peer->state == Connect || /* connection in progress */
664 peer->update_routes || /* routing updates */
665 peer->outbuf->packet.header.len) /* pending output */
666 events |= EPOLLOUT;
667
668 if (peer->events != events)
669 {
670 struct epoll_event ev;
671
672 ev.events = peer->events = events;
673 ev.data.ptr = &peer->edata;
674 epoll_ctl(epollfd, EPOLL_CTL_MOD, peer->sock, &ev);
675 }
676 }
677
678 return 1;
679 }
680
681 /* process bgp events/timers */
682 int bgp_process(uint32_t events[])
683 {
684 int i;
685
686 if (!bgp_configured)
687 return 0;
688
689 for (i = 0; i < BGP_NUM_PEERS; i++)
690 {
691 struct bgp_peer *peer = &bgp_peers[i];
692
693 if (*peer->name && peer->cli_flag == BGP_CLI_RESTART)
694 {
695 bgp_restart(peer);
696 continue;
697 }
698
699 if (peer->state == Disabled)
700 continue;
701
702 if (peer->cli_flag)
703 {
704 switch (peer->cli_flag)
705 {
706 case BGP_CLI_SUSPEND:
707 if (peer->routing)
708 {
709 peer->routing = 0;
710 if (peer->state == Established)
711 peer->update_routes = 1;
712 }
713
714 break;
715
716 case BGP_CLI_ENABLE:
717 if (!peer->routing)
718 {
719 peer->routing = 1;
720 if (peer->state == Established)
721 peer->update_routes = 1;
722 }
723
724 break;
725 }
726
727 peer->cli_flag = 0;
728 }
729
730 /* handle empty/fill of buffers */
731 if (events[i] & EPOLLOUT)
732 {
733 int r = 1;
734 if (peer->state == Connect)
735 r = bgp_handle_connect(peer);
736 else if (peer->outbuf->packet.header.len)
737 r = bgp_write(peer);
738
739 if (!r)
740 continue;
741 }
742
743 if (events[i] & (EPOLLIN|EPOLLHUP))
744 {
745 if (!bgp_read(peer))
746 continue;
747 }
748
749 /* process input buffer contents */
750 while (peer->inbuf->done >= sizeof(peer->inbuf->packet.header)
751 && !peer->outbuf->packet.header.len) /* may need to queue a response */
752 {
753 if (bgp_handle_input(peer) < 0)
754 continue;
755 }
756
757 /* process pending updates */
758 if (peer->update_routes
759 && !peer->outbuf->packet.header.len) /* ditto */
760 {
761 if (!bgp_send_update(peer))
762 continue;
763 }
764
765 /* process pending IPv6 updates */
766 if (peer->update_routes6
767 && !peer->outbuf->packet.header.len) /* ditto */
768 {
769 if (!bgp_send_update6(peer))
770 continue;
771 }
772
773 /* process timers */
774 if (peer->state == Established)
775 {
776 if (time_now > peer->expire_time)
777 {
778 LOG(1, 0, 0, "No message from BGP peer %s in %ds\n",
779 peer->name, peer->hold);
780
781 bgp_send_notification(peer, BGP_ERR_HOLD_TIMER_EXP, 0);
782 continue;
783 }
784
785 if (time_now > peer->keepalive_time && !peer->outbuf->packet.header.len)
786 bgp_send_keepalive(peer);
787 }
788 else if (peer->state == Idle)
789 {
790 if (time_now > peer->retry_time)
791 bgp_connect(peer);
792 }
793 else if (time_now > peer->state_time + BGP_STATE_TIME)
794 {
795 LOG(1, 0, 0, "%s timer expired for BGP peer %s\n",
796 bgp_state_str(peer->state), peer->name);
797
798 bgp_restart(peer);
799 }
800 }
801
802 return 1;
803 }
804
805 static void bgp_free_routes(struct bgp_route_list *routes)
806 {
807 struct bgp_route_list *tmp;
808
809 while ((tmp = routes))
810 {
811 routes = tmp->next;
812 free(tmp);
813 }
814 }
815
816 static void bgp_free_routes6(struct bgp_route6_list *routes)
817 {
818 struct bgp_route6_list *tmp;
819
820 while ((tmp = routes))
821 {
822 routes = tmp->next;
823 free(tmp);
824 }
825 }
826
827 char const *bgp_state_str(enum bgp_state state)
828 {
829 switch (state)
830 {
831 case Disabled: return "Disabled";
832 case Idle: return "Idle";
833 case Connect: return "Connect";
834 case Active: return "Active";
835 case OpenSent: return "OpenSent";
836 case OpenConfirm: return "OpenConfirm";
837 case Established: return "Established";
838 }
839
840 return "?";
841 }
842
843 static char const *bgp_msg_type_str(uint8_t type)
844 {
845 switch (type)
846 {
847 case BGP_MSG_OPEN: return "OPEN";
848 case BGP_MSG_UPDATE: return "UPDATE";
849 case BGP_MSG_NOTIFICATION: return "NOTIFICATION";
850 case BGP_MSG_KEEPALIVE: return "KEEPALIVE";
851 }
852
853 return "?";
854 }
855
856 /* attempt to connect to peer */
857 static int bgp_connect(struct bgp_peer *peer)
858 {
859 static int bgp_port = 0;
860 struct sockaddr_in addr;
861 struct epoll_event ev;
862
863 if (!bgp_port)
864 {
865 struct servent *serv;
866 if (!(serv = getservbyname("bgp", "tcp")))
867 {
868 LOG(0, 0, 0, "Can't get bgp service (%s)\n", strerror(errno));
869 return 0;
870 }
871
872 bgp_port = serv->s_port;
873 }
874
875 if ((peer->sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
876 {
877 LOG(0, 0, 0, "Can't create a socket for BGP peer %s (%s)\n",
878 peer->name, strerror(errno));
879
880 peer->state = peer->next_state = Disabled;
881 return 0;
882 }
883
884 /* add to poll set */
885 ev.events = peer->events = EPOLLOUT;
886 ev.data.ptr = &peer->edata;
887 epoll_ctl(epollfd, EPOLL_CTL_ADD, peer->sock, &ev);
888
889 /* set to non-blocking */
890 fcntl(peer->sock, F_SETFL, fcntl(peer->sock, F_GETFL, 0) | O_NONBLOCK);
891
892 /* try connect */
893 memset(&addr, 0, sizeof(addr));
894 addr.sin_family = AF_INET;
895 addr.sin_port = bgp_port;
896 addr.sin_addr.s_addr = peer->addr;
897
898 while (connect(peer->sock, (struct sockaddr *) &addr, sizeof(addr)) == -1)
899 {
900 if (errno == EINTR) /* SIGALARM handler */
901 continue;
902
903 if (errno != EINPROGRESS)
904 {
905 LOG(1, 0, 0, "Can't connect to BGP peer %s (%s)\n",
906 inet_ntoa(addr.sin_addr), strerror(errno));
907
908 bgp_set_retry(peer);
909 return 0;
910 }
911
912 peer->state = Connect;
913 peer->state_time = time_now;
914
915 LOG(4, 0, 0, "BGP peer %s: state Connect\n", peer->name);
916 return 1;
917 }
918
919 peer->state = Active;
920 peer->state_time = time_now;
921 peer->retry_time = peer->retry_count = 0;
922
923 LOG(4, 0, 0, "BGP peer %s: state Active\n", inet_ntoa(addr.sin_addr));
924
925 peer->handle_ipv6_routes = 0;
926
927 return bgp_send_open(peer);
928 }
929
930 /* complete partial connection (state = Connect) */
931 static int bgp_handle_connect(struct bgp_peer *peer)
932 {
933 int err = 0;
934 socklen_t len = sizeof(int);
935 getsockopt(peer->sock, SOL_SOCKET, SO_ERROR, &err, &len);
936 if (err)
937 {
938 LOG(1, 0, 0, "Can't connect to BGP peer %s (%s)\n", peer->name,
939 strerror(err));
940
941 bgp_set_retry(peer);
942 return 0;
943 }
944
945 peer->state = Active;
946 peer->state_time = time_now;
947
948 LOG(4, 0, 0, "BGP peer %s: state Active\n", peer->name);
949
950 peer->handle_ipv6_routes = 0;
951
952 return bgp_send_open(peer);
953 }
954
955 /* initiate a write */
956 static int bgp_write(struct bgp_peer *peer)
957 {
958 int len = htons(peer->outbuf->packet.header.len);
959 int r;
960
961 while ((r = write(peer->sock, &peer->outbuf->packet + peer->outbuf->done,
962 len - peer->outbuf->done)) == -1)
963 {
964 if (errno == EINTR)
965 continue;
966
967 if (errno == EAGAIN)
968 return 1;
969
970 if (errno == EPIPE)
971 LOG(1, 0, 0, "Connection to BGP peer %s closed\n", peer->name);
972 else
973 LOG(1, 0, 0, "Can't write to BGP peer %s (%s)\n", peer->name,
974 strerror(errno));
975
976 bgp_set_retry(peer);
977 return 0;
978 }
979
980 if (r < len)
981 {
982 peer->outbuf->done += r;
983 return 1;
984 }
985
986 LOG(4, 0, 0, "Sent %s to BGP peer %s\n",
987 bgp_msg_type_str(peer->outbuf->packet.header.type), peer->name);
988
989 peer->outbuf->packet.header.len = 0;
990 peer->outbuf->done = 0;
991
992 if (peer->state == Established)
993 peer->keepalive_time = time_now + peer->keepalive;
994
995 if (peer->state != peer->next_state)
996 {
997 if (peer->next_state == Disabled || peer->next_state == Idle)
998 {
999 bgp_clear(peer);
1000 return 0;
1001 }
1002
1003 peer->state = peer->next_state;
1004 peer->state_time = time_now;
1005
1006 LOG(4, 0, 0, "BGP peer %s: state %s\n", peer->name,
1007 bgp_state_str(peer->state));
1008 }
1009
1010 return 1;
1011 }
1012
1013 /* initiate a read */
1014 static int bgp_read(struct bgp_peer *peer)
1015 {
1016 int r;
1017
1018 while ((r = read(peer->sock, &peer->inbuf->packet + peer->inbuf->done,
1019 BGP_MAX_PACKET_SIZE - peer->inbuf->done)) < 1)
1020 {
1021 if (!r)
1022 {
1023 LOG(1, 0, 0, "Connection to BGP peer %s closed\n", peer->name);
1024 }
1025 else
1026 {
1027 if (errno == EINTR)
1028 continue;
1029
1030 if (errno == EAGAIN)
1031 return 1;
1032
1033 LOG(1, 0, 0, "Can't read from BGP peer %s (%s)\n", peer->name,
1034 strerror(errno));
1035 }
1036
1037 bgp_set_retry(peer);
1038 return 0;
1039 }
1040
1041 peer->inbuf->done += r;
1042 return 1;
1043 }
1044
1045 /* process buffered packets */
1046 static int bgp_handle_input(struct bgp_peer *peer)
1047 {
1048 struct bgp_packet *p = &peer->inbuf->packet;
1049 int len = ntohs(p->header.len);
1050
1051 if (len > BGP_MAX_PACKET_SIZE)
1052 {
1053 LOG(1, 0, 0, "Bad header length from BGP %s\n", peer->name);
1054 bgp_send_notification(peer, BGP_ERR_HEADER, BGP_ERR_HDR_BAD_LEN);
1055 return 0;
1056 }
1057
1058 if (peer->inbuf->done < len)
1059 return 0;
1060
1061 LOG(4, 0, 0, "Received %s from BGP peer %s\n",
1062 bgp_msg_type_str(p->header.type), peer->name);
1063
1064 switch (p->header.type)
1065 {
1066 case BGP_MSG_OPEN:
1067 {
1068 struct bgp_data_open data;
1069 int hold;
1070 int i;
1071 off_t param_offset, capability_offset;
1072 struct bgp_opt_param *param;
1073 uint8_t capabilities_len;
1074 char *capabilities = NULL;
1075 struct bgp_capability *capability;
1076 struct bgp_mp_cap_param *mp_cap;
1077
1078 for (i = 0; i < sizeof(p->header.marker); i++)
1079 {
1080 if ((unsigned char) p->header.marker[i] != 0xff)
1081 {
1082 LOG(1, 0, 0, "Invalid marker from BGP peer %s\n",
1083 peer->name);
1084
1085 bgp_send_notification(peer, BGP_ERR_HEADER,
1086 BGP_ERR_HDR_NOT_SYNC);
1087
1088 return 0;
1089 }
1090 }
1091
1092 if (peer->state != OpenSent)
1093 {
1094 LOG(1, 0, 0, "OPEN from BGP peer %s in %s state\n",
1095 peer->name, bgp_state_str(peer->state));
1096
1097 bgp_send_notification(peer, BGP_ERR_FSM, 0);
1098 return 0;
1099 }
1100
1101 memcpy(&data, p->data, len - sizeof(p->header));
1102
1103 if (data.version != BGP_VERSION)
1104 {
1105 LOG(1, 0, 0, "Bad version (%d) sent by BGP peer %s\n",
1106 (int) data.version, peer->name);
1107
1108 bgp_send_notification(peer, BGP_ERR_OPEN, BGP_ERR_OPN_VERSION);
1109 return 0;
1110 }
1111
1112 if (ntohs(data.as) != peer->as)
1113 {
1114 LOG(1, 0, 0, "Bad AS sent by BGP peer %s (got %d, "
1115 "expected %d)\n", peer->name, (int) htons(data.as),
1116 (int) peer->as);
1117
1118 bgp_send_notification(peer, BGP_ERR_OPEN, BGP_ERR_OPN_BAD_AS);
1119 return 0;
1120 }
1121
1122 if ((hold = ntohs(data.hold_time)) < 3)
1123 {
1124 LOG(1, 0, 0, "Bad hold time (%d) from BGP peer %s\n",
1125 hold, peer->name);
1126
1127 bgp_send_notification(peer, BGP_ERR_OPEN, BGP_ERR_OPN_HOLD_TIME);
1128 return 0;
1129 }
1130
1131 /* pick lowest hold time */
1132 if (hold < peer->hold)
1133 peer->hold = hold;
1134
1135 /* adjust our keepalive based on negotiated hold value */
1136 if (peer->keepalive * 3 > peer->hold)
1137 peer->keepalive = peer->hold / 3;
1138
1139 /* check for optional parameters */
1140 /* 2 is for the size of type + len (both uint8_t) */
1141 for (param_offset = 0;
1142 param_offset < data.opt_len;
1143 param_offset += 2 + param->len)
1144 {
1145 param = (struct bgp_opt_param *)(&data.opt_params + param_offset);
1146
1147 /* sensible check */
1148 if (data.opt_len - param_offset < 2
1149 || param->len > data.opt_len - param_offset - 2)
1150 {
1151 LOG(1, 0, 0, "Malformed Optional Parameter list from BGP peer %s\n",
1152 peer->name);
1153
1154 bgp_send_notification(peer, BGP_ERR_OPEN, BGP_ERR_UNSPEC);
1155 return 0;
1156 }
1157
1158 /* we know only one parameter type */
1159 if (param->type != BGP_PARAM_TYPE_CAPABILITY)
1160 {
1161 LOG(1, 0, 0, "Unsupported Optional Parameter type %d from BGP peer %s\n",
1162 param->type, peer->name);
1163
1164 bgp_send_notification(peer, BGP_ERR_OPEN, BGP_ERR_OPN_UNSUP_PARAM);
1165 return 0;
1166 }
1167
1168 capabilities_len = param->len;
1169 capabilities = (char *)&param->value;
1170 }
1171
1172 /* look for BGP multiprotocol capability */
1173 if (capabilities)
1174 {
1175 for (capability_offset = 0;
1176 capability_offset < capabilities_len;
1177 capability_offset += 2 + capability->len)
1178 {
1179 capability = (struct bgp_capability *)(capabilities + capability_offset);
1180
1181 /* sensible check */
1182 if (capabilities_len - capability_offset < 2
1183 || capability->len > capabilities_len - capability_offset - 2)
1184 {
1185 LOG(1, 0, 0, "Malformed Capabilities list from BGP peer %s\n",
1186 peer->name);
1187
1188 bgp_send_notification(peer, BGP_ERR_OPEN, BGP_ERR_UNSPEC);
1189 return 0;
1190 }
1191
1192 /* we only know one capability code */
1193 if (capability->code != BGP_CAP_CODE_MP
1194 && capability->len != sizeof(struct bgp_mp_cap_param))
1195 {
1196 LOG(4, 0, 0, "Unsupported Capability code %d from BGP peer %s\n",
1197 capability->code, peer->name);
1198
1199 bgp_send_notification_full(peer, BGP_ERR_OPEN, BGP_ERR_OPN_UNSUP_CAP,
1200 (char *)capability, 2 + capability->len);
1201 /* we don't terminate, still; we just jump to the next one */
1202 continue;
1203 }
1204
1205 mp_cap = (struct bgp_mp_cap_param *)&capability->value;
1206 /* the only <AFI, SAFI> tuple we support */
1207 if (ntohs(mp_cap->afi) != AF_INET6 && mp_cap->safi != BGP_MP_SAFI_UNICAST)
1208 {
1209 LOG(4, 0, 0, "Unsupported multiprotocol AFI %d and SAFI %d from BGP peer %s\n",
1210 mp_cap->afi, mp_cap->safi, peer->name);
1211
1212 bgp_send_notification_full(peer, BGP_ERR_OPEN, BGP_ERR_OPN_UNSUP_CAP,
1213 (char *)capability, 2 + capability->len);
1214 /* we don't terminate, still; we just jump to the next one */
1215 continue;
1216 }
1217
1218 peer->handle_ipv6_routes = 1;
1219 }
1220 }
1221
1222 /* next transition requires an exchange of keepalives */
1223 bgp_send_keepalive(peer);
1224 }
1225
1226 break;
1227
1228 case BGP_MSG_KEEPALIVE:
1229 if (peer->state == OpenConfirm)
1230 {
1231 peer->state = peer->next_state = Established;
1232 peer->state_time = time_now;
1233 peer->keepalive_time = time_now + peer->keepalive;
1234 peer->update_routes = 1;
1235 peer->retry_count = 0;
1236 peer->retry_time = 0;
1237
1238 LOG(4, 0, 0, "BGP peer %s: state Established\n", peer->name);
1239 }
1240
1241 break;
1242
1243 case BGP_MSG_NOTIFICATION:
1244 if (len > sizeof(p->header))
1245 {
1246 struct bgp_data_notification *notification =
1247 (struct bgp_data_notification *) p->data;
1248
1249 if (notification->error_code == BGP_ERR_CEASE)
1250 {
1251 LOG(4, 0, 0, "BGP peer %s sent CEASE\n", peer->name);
1252 bgp_restart(peer);
1253 return 0;
1254 }
1255
1256 if (notification->error_code == BGP_ERR_OPEN
1257 && notification->error_subcode == BGP_ERR_OPN_UNSUP_CAP)
1258 {
1259 /* the only capability we advertise is this one, so upon receiving
1260 an "unsupported capability" message, we disable IPv6 routes for
1261 this peer */
1262 LOG(4, 0, 0, "BGP peer %s doesn't support IPv6 routes advertisement\n", peer->name);
1263 peer->handle_ipv6_routes = 0;
1264 break;
1265 }
1266
1267 /* FIXME: should handle more notifications */
1268 LOG(4, 0, 0, "BGP peer %s sent unhandled NOTIFICATION %d\n",
1269 peer->name, (int) notification->error_code);
1270 }
1271
1272 break;
1273 }
1274
1275 /* reset timer */
1276 peer->expire_time = time_now + peer->hold;
1277
1278 /* see if there's another message in the same packet/buffer */
1279 if (peer->inbuf->done > len)
1280 {
1281 peer->inbuf->done -= len;
1282 memmove(p, (char *) p + len, peer->inbuf->done);
1283 }
1284 else
1285 {
1286 peer->inbuf->packet.header.len = 0;
1287 peer->inbuf->done = 0;
1288 }
1289
1290 return peer->inbuf->done;
1291 }
1292
1293 /* send/buffer OPEN message */
1294 static int bgp_send_open(struct bgp_peer *peer)
1295 {
1296 struct bgp_data_open data;
1297 struct bgp_mp_cap_param mp_ipv6 = { htons(AF_INET6), 0, BGP_MP_SAFI_UNICAST };
1298 struct bgp_capability cap_mp_ipv6;
1299 struct bgp_opt_param param_cap_mp_ipv6;
1300 uint16_t len = sizeof(peer->outbuf->packet.header);
1301
1302 memset(peer->outbuf->packet.header.marker, 0xff,
1303 sizeof(peer->outbuf->packet.header.marker));
1304
1305 peer->outbuf->packet.header.type = BGP_MSG_OPEN;
1306
1307 data.version = BGP_VERSION;
1308 data.as = htons(our_as);
1309 data.hold_time = htons(peer->hold);
1310 data.identifier = my_address;
1311
1312 /* construct the param and capability */
1313 cap_mp_ipv6.code = BGP_CAP_CODE_MP;
1314 cap_mp_ipv6.len = sizeof(mp_ipv6);
1315 memcpy(&cap_mp_ipv6.value, &mp_ipv6, cap_mp_ipv6.len);
1316
1317 param_cap_mp_ipv6.type = BGP_PARAM_TYPE_CAPABILITY;
1318 param_cap_mp_ipv6.len = 2 + sizeof(mp_ipv6);
1319 memcpy(&param_cap_mp_ipv6.value, &cap_mp_ipv6, param_cap_mp_ipv6.len);
1320
1321 data.opt_len = 2 + param_cap_mp_ipv6.len;
1322 memcpy(&data.opt_params, &param_cap_mp_ipv6, data.opt_len);
1323
1324 memcpy(peer->outbuf->packet.data, &data, BGP_DATA_OPEN_SIZE);
1325 len += BGP_DATA_OPEN_SIZE;
1326
1327 peer->outbuf->packet.header.len = htons(len);
1328 peer->outbuf->done = 0;
1329 peer->next_state = OpenSent;
1330
1331 return bgp_write(peer);
1332 }
1333
1334 /* send/buffer KEEPALIVE message */
1335 static int bgp_send_keepalive(struct bgp_peer *peer)
1336 {
1337 memset(peer->outbuf->packet.header.marker, 0xff,
1338 sizeof(peer->outbuf->packet.header.marker));
1339
1340 peer->outbuf->packet.header.type = BGP_MSG_KEEPALIVE;
1341 peer->outbuf->packet.header.len =
1342 htons(sizeof(peer->outbuf->packet.header));
1343
1344 peer->outbuf->done = 0;
1345 peer->next_state = (peer->state == OpenSent) ? OpenConfirm : peer->state;
1346
1347 return bgp_write(peer);
1348 }
1349
1350 /* send/buffer UPDATE message */
1351 static int bgp_send_update(struct bgp_peer *peer)
1352 {
1353 uint16_t unf_len = 0;
1354 uint16_t attr_len;
1355 uint16_t len = sizeof(peer->outbuf->packet.header);
1356 struct bgp_route_list *have = peer->routes;
1357 struct bgp_route_list *want = peer->routing ? bgp_routes : 0;
1358 struct bgp_route_list *e = 0;
1359 struct bgp_route_list *add = 0;
1360 int s;
1361
1362 char *data = (char *) &peer->outbuf->packet.data;
1363
1364 /* need leave room for attr_len, bgp_path_attrs and one prefix */
1365 char *max = (char *) &peer->outbuf->packet.data
1366 + sizeof(peer->outbuf->packet.data)
1367 - sizeof(attr_len) - peer->path_attr_len - sizeof(struct bgp_ip_prefix);
1368
1369 /* skip over unf_len */
1370 data += sizeof(unf_len);
1371 len += sizeof(unf_len);
1372
1373 memset(peer->outbuf->packet.header.marker, 0xff,
1374 sizeof(peer->outbuf->packet.header.marker));
1375
1376 peer->outbuf->packet.header.type = BGP_MSG_UPDATE;
1377
1378 peer->update_routes = 0; /* tentatively clear */
1379
1380 /* find differences */
1381 while ((have || want) && data < (max - sizeof(struct bgp_ip_prefix)))
1382 {
1383 if (have)
1384 s = want
1385 ? memcmp(&have->dest, &want->dest, sizeof(have->dest))
1386 : -1;
1387 else
1388 s = 1;
1389
1390 if (s < 0) /* found one to delete */
1391 {
1392 struct bgp_route_list *tmp = have;
1393 have = have->next;
1394
1395 s = BGP_IP_PREFIX_SIZE(tmp->dest);
1396 memcpy(data, &tmp->dest, s);
1397 data += s;
1398 unf_len += s;
1399 len += s;
1400
1401 LOG(5, 0, 0, "Withdrawing route %s/%d from BGP peer %s\n",
1402 fmtaddr(tmp->dest.prefix, 0), tmp->dest.len, peer->name);
1403
1404 free(tmp);
1405
1406 if (e)
1407 e->next = have;
1408 else
1409 peer->routes = have;
1410 }
1411 else
1412 {
1413 if (!s) /* same */
1414 {
1415 e = have; /* stash the last found to relink above */
1416 have = have->next;
1417 want = want->next;
1418 }
1419 else if (s > 0) /* addition reqd. */
1420 {
1421 if (add)
1422 {
1423 peer->update_routes = 1; /* only one add per packet */
1424 if (!have)
1425 break;
1426 }
1427 else
1428 add = want;
1429
1430 if (want)
1431 want = want->next;
1432 }
1433 }
1434 }
1435
1436 if (have || want)
1437 peer->update_routes = 1; /* more to do */
1438
1439 /* anything changed? */
1440 if (!(unf_len || add))
1441 return 1;
1442
1443 /* go back and insert unf_len */
1444 unf_len = htons(unf_len);
1445 memcpy(&peer->outbuf->packet.data, &unf_len, sizeof(unf_len));
1446
1447 if (add)
1448 {
1449 if (!(e = malloc(sizeof(*e))))
1450 {
1451 LOG(0, 0, 0, "Can't allocate route for %s/%d (%s)\n",
1452 fmtaddr(add->dest.prefix, 0), add->dest.len, strerror(errno));
1453
1454 return 0;
1455 }
1456
1457 memcpy(e, add, sizeof(*e));
1458 e->next = 0;
1459 peer->routes = bgp_insert_route(peer->routes, e);
1460
1461 attr_len = htons(peer->path_attr_len);
1462 memcpy(data, &attr_len, sizeof(attr_len));
1463 data += sizeof(attr_len);
1464 len += sizeof(attr_len);
1465
1466 memcpy(data, peer->path_attrs, peer->path_attr_len);
1467 data += peer->path_attr_len;
1468 len += peer->path_attr_len;
1469
1470 s = BGP_IP_PREFIX_SIZE(add->dest);
1471 memcpy(data, &add->dest, s);
1472 data += s;
1473 len += s;
1474
1475 LOG(5, 0, 0, "Advertising route %s/%d to BGP peer %s\n",
1476 fmtaddr(add->dest.prefix, 0), add->dest.len, peer->name);
1477 }
1478 else
1479 {
1480 attr_len = 0;
1481 memcpy(data, &attr_len, sizeof(attr_len));
1482 data += sizeof(attr_len);
1483 len += sizeof(attr_len);
1484 }
1485
1486 peer->outbuf->packet.header.len = htons(len);
1487 peer->outbuf->done = 0;
1488
1489 return bgp_write(peer);
1490 }
1491
1492 /* send/buffer UPDATE message for IPv6 routes */
1493 static int bgp_send_update6(struct bgp_peer *peer)
1494 {
1495 }
1496
1497 /* send/buffer NOTIFICATION message */
1498 static int bgp_send_notification(struct bgp_peer *peer, uint8_t code,
1499 uint8_t subcode)
1500 {
1501 return bgp_send_notification_full(peer, code, subcode, NULL, 0);
1502 }
1503
1504 static int bgp_send_notification_full(struct bgp_peer *peer, uint8_t code,
1505 uint8_t subcode, char *notification_data, uint16_t data_len)
1506 {
1507 struct bgp_data_notification data;
1508 uint16_t len = 0;
1509
1510 data.error_code = code;
1511 len += sizeof(data.error_code);
1512
1513 data.error_subcode = subcode;
1514 len += sizeof(data.error_code);
1515
1516 memcpy(data.data, notification_data, data_len);
1517 len += data_len;
1518
1519 memset(peer->outbuf->packet.header.marker, 0xff,
1520 sizeof(peer->outbuf->packet.header.marker));
1521
1522 peer->outbuf->packet.header.type = BGP_MSG_NOTIFICATION;
1523 peer->outbuf->packet.header.len =
1524 htons(sizeof(peer->outbuf->packet.header) + len);
1525
1526 memcpy(peer->outbuf->packet.data, &data, len);
1527
1528 peer->outbuf->done = 0;
1529 peer->next_state = code == BGP_ERR_CEASE ? Disabled : Idle;
1530
1531 /* we're dying; ignore any pending input */
1532 peer->inbuf->packet.header.len = 0;
1533 peer->inbuf->done = 0;
1534
1535 return bgp_write(peer);
1536 }