3 * Used to advertise routes for upstream (l2tp port, rather than gratiutious
4 * arp) and downstream--allowing routers to load-balance both.
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).
13 char const *cvs_id_bgp
= "$Id: bgp.c,v 1.12 2005/09/02 23:39:36 bodea Exp $";
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
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);
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
,
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
);
55 static uint16_t our_as
;
56 static struct bgp_route_list
*bgp_routes
= 0;
57 static struct bgp_route6_list
*bgp_routes6
= 0;
59 int bgp_configured
= 0;
60 struct bgp_peer
*bgp_peers
= 0;
62 /* prepare peer structure, globals */
66 struct bgp_peer
*peer
;
68 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
71 memset(peer
, 0, sizeof(*peer
));
73 peer
->addr
= INADDR_NONE
;
75 peer
->state
= peer
->next_state
= Disabled
;
77 if (!((peer
->outbuf
= malloc(sizeof(*peer
->outbuf
)))
78 && (peer
->inbuf
= malloc(sizeof(*peer
->inbuf
)))))
80 LOG(0, 0, 0, "Can't allocate buffers for bgp peer (%s)\n",
86 peer
->edata
.type
= FD_TYPE_BGP
;
87 peer
->edata
.index
= i
;
99 bgp_configured
= 0; /* set by bgp_start */
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
)
111 struct bgp_path_attr a
;
113 char *p
= path_attrs
;
115 uint32_t metric
= htonl(BGP_METRIC
);
116 uint32_t no_export
= htonl(BGP_COMMUNITY_NO_EXPORT
);
121 if (peer
->state
!= Disabled
)
124 snprintf(peer
->name
, sizeof(peer
->name
), "%s", name
);
126 if (!(h
= gethostbyname(name
)) || h
->h_addrtype
!= AF_INET
)
128 LOG(0, 0, 0, "Can't get address for BGP peer %s (%s)\n",
129 name
, h
? "no address" : hstrerror(h_errno
));
134 memcpy(&peer
->addr
, h
->h_addr
, sizeof(peer
->addr
));
135 peer
->as
= as
> 0 ? as
: our_as
;
136 ibgp
= peer
->as
== our_as
;
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
;
142 if (peer
->init_hold
< 3)
145 if (peer
->init_keepalive
* 3 > peer
->init_hold
)
146 peer
->init_keepalive
= peer
->init_hold
/ 3;
148 /* clear buffers, go to Idle state */
149 peer
->next_state
= Idle
;
152 /* set initial routing state */
153 peer
->routing
= enable
;
155 /* all our routes use the same attributes, so prepare it in advance */
156 if (peer
->path_attrs
)
157 free(peer
->path_attrs
);
159 peer
->path_attr_len
= 0;
162 a
.flags
= BGP_PATH_ATTR_FLAG_TRANS
;
163 a
.code
= BGP_PATH_ATTR_CODE_ORIGIN
;
165 a
.data
.s
.value
[0] = BGP_PATH_ATTR_CODE_ORIGIN_IGP
;
167 #define ADD_ATTRIBUTE() do { \
168 i = BGP_PATH_ATTR_SIZE(a); \
171 peer->path_attr_len += i; } while (0)
176 a
.flags
= BGP_PATH_ATTR_FLAG_TRANS
;
177 a
.code
= BGP_PATH_ATTR_CODE_AS_PATH
;
191 BGP_PATH_ATTR_CODE_AS_PATH_AS_SEQUENCE
,
196 a
.data
.s
.len
= sizeof(as_path
);
197 memcpy(&a
.data
.s
.value
, &as_path
, sizeof(as_path
));
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
));
212 uint32_t local_pref
= htonl(BGP_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
));
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
));
231 /* remember the len before adding NEXT_HOP */
232 peer
->path_attr_len_without_nexthop
= peer
->path_attr_len
;
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
));
243 if (!(peer
->path_attrs
= malloc(peer
->path_attr_len
)))
245 LOG(0, 0, 0, "Can't allocate path_attrs for %s (%s)\n",
246 name
, strerror(errno
));
251 memcpy(peer
->path_attrs
, path_attrs
, peer
->path_attr_len
);
253 /* multiprotocol attributes initialization */
254 if (config
->ipv6_prefix
.s6_addr
[0])
256 struct bgp_attr_mp_reach_nlri_partial mp_reach_nlri_partial
;
257 struct bgp_attr_mp_unreach_nlri_partial mp_unreach_nlri_partial
;
259 a
.flags
= BGP_PATH_ATTR_FLAG_OPTIONAL
;
260 a
.code
= BGP_PATH_ATTR_CODE_MP_REACH_NLRI
;
261 a
.data
.s
.len
= 0; /* will be set on UPDATE */
263 mp_reach_nlri_partial
.afi
= htons(AF_INET6
);
264 mp_reach_nlri_partial
.safi
= BGP_MP_SAFI_UNICAST
;
265 mp_reach_nlri_partial
.reserved
= 0;
266 mp_reach_nlri_partial
.next_hop_len
= 16;
268 /* use the defined nexthop6, or our address in ipv6_prefix */
269 if (config
->nexthop6_address
.s6_addr
[0])
270 memcpy(&mp_reach_nlri_partial
.next_hop
,
271 &config
->nexthop6_address
.s6_addr
, 16);
274 /* our address is ipv6prefix::1 */
275 memcpy(&mp_reach_nlri_partial
.next_hop
,
276 &config
->ipv6_prefix
.s6_addr
, 16);
277 mp_reach_nlri_partial
.next_hop
[15] = 1;
280 memcpy(&a
.data
.s
.value
, &mp_reach_nlri_partial
,
281 sizeof(struct bgp_attr_mp_reach_nlri_partial
));
282 memcpy(&peer
->mp_reach_nlri_partial
, &a
,
283 BGP_PATH_ATTR_MP_REACH_NLRI_PARTIAL_SIZE
);
285 a
.flags
= BGP_PATH_ATTR_FLAG_OPTIONAL
| BGP_PATH_ATTR_FLAG_EXTLEN
;
286 a
.code
= BGP_PATH_ATTR_CODE_MP_UNREACH_NLRI
;
287 a
.data
.e
.len
= 0; /* will be set on UPDATE */
289 mp_unreach_nlri_partial
.afi
= htons(AF_INET6
);
290 mp_unreach_nlri_partial
.safi
= BGP_MP_SAFI_UNICAST
;
292 memcpy(&a
.data
.e
.value
, &mp_unreach_nlri_partial
,
293 sizeof(struct bgp_attr_mp_unreach_nlri_partial
));
294 memcpy(&peer
->mp_unreach_nlri_partial
, &a
,
295 BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE
);
298 LOG(4, 0, 0, "Initiating BGP connection to %s (routing %s)\n",
299 name
, enable
? "enabled" : "suspended");
301 /* we have at least one peer configured */
305 return bgp_connect(peer
);
308 /* clear counters, timers, routes and buffers; close socket; move to
309 next_state, which may be Disabled or Idle */
310 static void bgp_clear(struct bgp_peer
*peer
)
312 if (peer
->sock
!= -1)
318 peer
->keepalive_time
= 0;
319 peer
->expire_time
= 0;
321 peer
->keepalive
= peer
->init_keepalive
;
322 peer
->hold
= peer
->init_hold
;
324 bgp_free_routes(peer
->routes
);
326 bgp_free_routes6(peer
->routes6
);
329 peer
->outbuf
->packet
.header
.len
= 0;
330 peer
->outbuf
->done
= 0;
331 peer
->inbuf
->packet
.header
.len
= 0;
332 peer
->inbuf
->done
= 0;
337 if (peer
->state
!= peer
->next_state
)
339 peer
->state
= peer
->next_state
;
340 peer
->state_time
= time_now
;
342 LOG(4, 0, 0, "BGP peer %s: state %s\n", peer
->name
,
343 bgp_state_str(peer
->next_state
));
347 /* initiate a clean shutdown */
348 void bgp_stop(struct bgp_peer
*peer
)
350 LOG(4, 0, 0, "Terminating BGP connection to %s\n", peer
->name
);
351 bgp_send_notification(peer
, BGP_ERR_CEASE
, 0);
354 /* drop connection (if any) and set state to Disabled */
355 void bgp_halt(struct bgp_peer
*peer
)
357 LOG(4, 0, 0, "Aborting BGP connection to %s\n", peer
->name
);
358 peer
->next_state
= Disabled
;
362 /* drop connection (if any) and set to Idle for connection retry */
363 int bgp_restart(struct bgp_peer
*peer
)
365 peer
->next_state
= Idle
;
369 peer
->retry_time
= time_now
;
370 peer
->retry_count
= 0;
373 return bgp_connect(peer
);
376 static void bgp_set_retry(struct bgp_peer
*peer
)
378 if (peer
->retry_count
++ < BGP_MAX_RETRY
)
380 peer
->retry_time
= time_now
+ (BGP_RETRY_BACKOFF
* peer
->retry_count
);
381 peer
->next_state
= Idle
;
385 bgp_halt(peer
); /* give up */
388 /* convert ip/mask to CIDR notation */
389 static void bgp_cidr(in_addr_t ip
, in_addr_t mask
, struct bgp_ip_prefix
*pfx
)
394 /* convert to prefix notation */
398 if (!mask
) /* bogus */
401 for (i
= 0; i
< 32 && ((b
= ntohl(1 << i
)), !(mask
& b
)); i
++)
408 /* insert route into list; sorted */
409 static struct bgp_route_list
*bgp_insert_route(struct bgp_route_list
*head
,
410 struct bgp_route_list
*new)
412 struct bgp_route_list
*p
= head
;
413 struct bgp_route_list
*e
= 0;
415 while (p
&& memcmp(&p
->dest
, &new->dest
, sizeof(p
->dest
)) < 0)
435 /* insert route6 into list; sorted */
436 static struct bgp_route6_list
*bgp_insert_route6(struct bgp_route6_list
*head
,
437 struct bgp_route6_list
*new)
439 struct bgp_route6_list
*p
= head
;
440 struct bgp_route6_list
*e
= 0;
442 while (p
&& memcmp(&p
->dest
, &new->dest
, sizeof(p
->dest
)) < 0)
462 /* add route to list for peers */
464 * Note: this doesn't do route aggregation, nor drop routes if a less
465 * specific match already exists (partly because I'm lazy, but also so
466 * that if that route is later deleted we don't have to be concerned
467 * about adding back the more specific one).
469 int bgp_add_route(in_addr_t ip
, in_addr_t mask
)
471 struct bgp_route_list
*r
= bgp_routes
;
472 struct bgp_route_list add
;
475 bgp_cidr(ip
, mask
, &add
.dest
);
478 /* check for duplicate */
481 i
= memcmp(&r
->dest
, &add
.dest
, sizeof(r
->dest
));
483 return 1; /* already covered */
491 /* insert into route list; sorted */
492 if (!(r
= malloc(sizeof(*r
))))
494 LOG(0, 0, 0, "Can't allocate route for %s/%d (%s)\n",
495 fmtaddr(add
.dest
.prefix
, 0), add
.dest
.len
, strerror(errno
));
500 memcpy(r
, &add
, sizeof(*r
));
501 bgp_routes
= bgp_insert_route(bgp_routes
, r
);
503 /* flag established peers for update */
504 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
505 if (bgp_peers
[i
].state
== Established
)
506 bgp_peers
[i
].update_routes
= 1;
508 LOG(4, 0, 0, "Registered BGP route %s/%d\n",
509 fmtaddr(add
.dest
.prefix
, 0), add
.dest
.len
);
514 /* add route to list for peers */
516 * Note: same provisions as above
518 int bgp_add_route6(struct in6_addr ip
, int prefixlen
)
520 struct bgp_route6_list
*r
= bgp_routes6
;
521 struct bgp_route6_list add
;
523 char ipv6addr
[INET6_ADDRSTRLEN
];
525 memcpy(&add
.dest
.prefix
, &ip
.s6_addr
, 16);
526 add
.dest
.len
= prefixlen
;
529 /* check for duplicate */
532 i
= memcmp(&r
->dest
, &add
.dest
, sizeof(r
->dest
));
534 return 1; /* already covered */
542 /* insert into route list; sorted */
543 if (!(r
= malloc(sizeof(*r
))))
545 LOG(0, 0, 0, "Can't allocate route for %s/%d (%s)\n",
546 inet_ntop(AF_INET6
, &ip
, ipv6addr
, INET6_ADDRSTRLEN
), add
.dest
.len
,
552 memcpy(r
, &add
, sizeof(*r
));
553 bgp_routes6
= bgp_insert_route6(bgp_routes6
, r
);
555 /* flag established peers for update */
556 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
557 if (bgp_peers
[i
].state
== Established
)
558 bgp_peers
[i
].update_routes6
= 1;
560 LOG(4, 0, 0, "Registered BGP route %s/%d\n",
561 inet_ntop(AF_INET6
, &ip
, ipv6addr
, INET6_ADDRSTRLEN
), add
.dest
.len
);
566 /* remove route from list for peers */
567 int bgp_del_route(in_addr_t ip
, in_addr_t mask
)
569 struct bgp_route_list
*r
= bgp_routes
;
570 struct bgp_route_list
*e
= 0;
571 struct bgp_route_list del
;
574 bgp_cidr(ip
, mask
, &del
.dest
);
577 /* find entry in routes list and remove */
580 i
= memcmp(&r
->dest
, &del
.dest
, sizeof(r
->dest
));
586 bgp_routes
= r
->next
;
604 /* flag established peers for update */
605 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
606 if (bgp_peers
[i
].state
== Established
)
607 bgp_peers
[i
].update_routes
= 1;
609 LOG(4, 0, 0, "Removed BGP route %s/%d\n",
610 fmtaddr(del
.dest
.prefix
, 0), del
.dest
.len
);
615 /* remove route from list for peers */
616 int bgp_del_route6(struct in6_addr ip
, int prefixlen
)
618 struct bgp_route6_list
*r
= bgp_routes6
;
619 struct bgp_route6_list
*e
= 0;
620 struct bgp_route6_list del
;
622 char ipv6addr
[INET6_ADDRSTRLEN
];
624 memcpy(&del
.dest
.prefix
, &ip
.s6_addr
, 16);
625 del
.dest
.len
= prefixlen
;
628 /* find entry in routes list and remove */
631 i
= memcmp(&r
->dest
, &del
.dest
, sizeof(r
->dest
));
637 bgp_routes6
= r
->next
;
655 /* flag established peers for update */
656 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
657 if (bgp_peers
[i
].state
== Established
)
658 bgp_peers
[i
].update_routes6
= 1;
660 LOG(4, 0, 0, "Removed BGP route %s/%d\n",
661 inet_ntop(AF_INET6
, &ip
, ipv6addr
, INET6_ADDRSTRLEN
), del
.dest
.len
);
666 /* enable or disable routing */
667 void bgp_enable_routing(int enable
)
671 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
673 bgp_peers
[i
].routing
= enable
;
675 /* flag established peers for update */
676 if (bgp_peers
[i
].state
== Established
)
677 bgp_peers
[i
].update_routes
= 1;
680 LOG(4, 0, 0, "%s BGP routing\n", enable
? "Enabled" : "Suspended");
684 # include <sys/epoll.h>
686 # include "fake_epoll.h"
689 /* return a bitmask of the events required to poll this peer's fd */
697 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
699 struct bgp_peer
*peer
= &bgp_peers
[i
];
702 if (peer
->state
== Disabled
|| peer
->state
== Idle
)
705 if (peer
->inbuf
->done
< BGP_MAX_PACKET_SIZE
)
708 if (peer
->state
== Connect
|| /* connection in progress */
709 peer
->update_routes
|| /* routing updates */
710 peer
->outbuf
->packet
.header
.len
) /* pending output */
713 if (peer
->events
!= events
)
715 struct epoll_event ev
;
717 ev
.events
= peer
->events
= events
;
718 ev
.data
.ptr
= &peer
->edata
;
719 epoll_ctl(epollfd
, EPOLL_CTL_MOD
, peer
->sock
, &ev
);
726 /* process bgp events/timers */
727 int bgp_process(uint32_t events
[])
734 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
736 struct bgp_peer
*peer
= &bgp_peers
[i
];
738 if (*peer
->name
&& peer
->cli_flag
== BGP_CLI_RESTART
)
744 if (peer
->state
== Disabled
)
749 switch (peer
->cli_flag
)
751 case BGP_CLI_SUSPEND
:
755 if (peer
->state
== Established
)
756 peer
->update_routes
= 1;
765 if (peer
->state
== Established
)
766 peer
->update_routes
= 1;
775 /* handle empty/fill of buffers */
776 if (events
[i
] & EPOLLOUT
)
779 if (peer
->state
== Connect
)
780 r
= bgp_handle_connect(peer
);
781 else if (peer
->outbuf
->packet
.header
.len
)
788 if (events
[i
] & (EPOLLIN
|EPOLLHUP
))
794 /* process input buffer contents */
795 while (peer
->inbuf
->done
>= sizeof(peer
->inbuf
->packet
.header
)
796 && !peer
->outbuf
->packet
.header
.len
) /* may need to queue a response */
798 if (bgp_handle_input(peer
) < 0)
802 /* process pending updates */
803 if (peer
->update_routes
804 && !peer
->outbuf
->packet
.header
.len
) /* ditto */
806 if (!bgp_send_update(peer
))
810 /* process pending IPv6 updates */
811 if (peer
->update_routes6
812 && !peer
->outbuf
->packet
.header
.len
) /* ditto */
814 if (!bgp_send_update6(peer
))
819 if (peer
->state
== Established
)
821 if (time_now
> peer
->expire_time
)
823 LOG(1, 0, 0, "No message from BGP peer %s in %ds\n",
824 peer
->name
, peer
->hold
);
826 bgp_send_notification(peer
, BGP_ERR_HOLD_TIMER_EXP
, 0);
830 if (time_now
> peer
->keepalive_time
&& !peer
->outbuf
->packet
.header
.len
)
831 bgp_send_keepalive(peer
);
833 else if (peer
->state
== Idle
)
835 if (time_now
> peer
->retry_time
)
838 else if (time_now
> peer
->state_time
+ BGP_STATE_TIME
)
840 LOG(1, 0, 0, "%s timer expired for BGP peer %s\n",
841 bgp_state_str(peer
->state
), peer
->name
);
850 static void bgp_free_routes(struct bgp_route_list
*routes
)
852 struct bgp_route_list
*tmp
;
854 while ((tmp
= routes
))
861 static void bgp_free_routes6(struct bgp_route6_list
*routes
)
863 struct bgp_route6_list
*tmp
;
865 while ((tmp
= routes
))
872 char const *bgp_state_str(enum bgp_state state
)
876 case Disabled
: return "Disabled";
877 case Idle
: return "Idle";
878 case Connect
: return "Connect";
879 case Active
: return "Active";
880 case OpenSent
: return "OpenSent";
881 case OpenConfirm
: return "OpenConfirm";
882 case Established
: return "Established";
888 static char const *bgp_msg_type_str(uint8_t type
)
892 case BGP_MSG_OPEN
: return "OPEN";
893 case BGP_MSG_UPDATE
: return "UPDATE";
894 case BGP_MSG_NOTIFICATION
: return "NOTIFICATION";
895 case BGP_MSG_KEEPALIVE
: return "KEEPALIVE";
901 /* attempt to connect to peer */
902 static int bgp_connect(struct bgp_peer
*peer
)
904 static int bgp_port
= 0;
905 struct sockaddr_in addr
;
906 struct epoll_event ev
;
910 struct servent
*serv
;
911 if (!(serv
= getservbyname("bgp", "tcp")))
913 LOG(0, 0, 0, "Can't get bgp service (%s)\n", strerror(errno
));
917 bgp_port
= serv
->s_port
;
920 if ((peer
->sock
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) < 0)
922 LOG(0, 0, 0, "Can't create a socket for BGP peer %s (%s)\n",
923 peer
->name
, strerror(errno
));
925 peer
->state
= peer
->next_state
= Disabled
;
929 /* add to poll set */
930 ev
.events
= peer
->events
= EPOLLOUT
;
931 ev
.data
.ptr
= &peer
->edata
;
932 epoll_ctl(epollfd
, EPOLL_CTL_ADD
, peer
->sock
, &ev
);
934 /* set to non-blocking */
935 fcntl(peer
->sock
, F_SETFL
, fcntl(peer
->sock
, F_GETFL
, 0) | O_NONBLOCK
);
938 memset(&addr
, 0, sizeof(addr
));
939 addr
.sin_family
= AF_INET
;
940 addr
.sin_port
= bgp_port
;
941 addr
.sin_addr
.s_addr
= peer
->addr
;
943 while (connect(peer
->sock
, (struct sockaddr
*) &addr
, sizeof(addr
)) == -1)
945 if (errno
== EINTR
) /* SIGALARM handler */
948 if (errno
!= EINPROGRESS
)
950 LOG(1, 0, 0, "Can't connect to BGP peer %s (%s)\n",
951 inet_ntoa(addr
.sin_addr
), strerror(errno
));
957 peer
->state
= Connect
;
958 peer
->state_time
= time_now
;
960 LOG(4, 0, 0, "BGP peer %s: state Connect\n", peer
->name
);
964 peer
->state
= Active
;
965 peer
->state_time
= time_now
;
966 peer
->retry_time
= peer
->retry_count
= 0;
968 LOG(4, 0, 0, "BGP peer %s: state Active\n", inet_ntoa(addr
.sin_addr
));
970 peer
->handle_ipv6_routes
= 0;
972 return bgp_send_open(peer
);
975 /* complete partial connection (state = Connect) */
976 static int bgp_handle_connect(struct bgp_peer
*peer
)
979 socklen_t len
= sizeof(int);
980 getsockopt(peer
->sock
, SOL_SOCKET
, SO_ERROR
, &err
, &len
);
983 LOG(1, 0, 0, "Can't connect to BGP peer %s (%s)\n", peer
->name
,
990 peer
->state
= Active
;
991 peer
->state_time
= time_now
;
993 LOG(4, 0, 0, "BGP peer %s: state Active\n", peer
->name
);
995 peer
->handle_ipv6_routes
= 0;
997 return bgp_send_open(peer
);
1000 /* initiate a write */
1001 static int bgp_write(struct bgp_peer
*peer
)
1003 int len
= htons(peer
->outbuf
->packet
.header
.len
);
1006 while ((r
= write(peer
->sock
, &peer
->outbuf
->packet
+ peer
->outbuf
->done
,
1007 len
- peer
->outbuf
->done
)) == -1)
1012 if (errno
== EAGAIN
)
1016 LOG(1, 0, 0, "Connection to BGP peer %s closed\n", peer
->name
);
1018 LOG(1, 0, 0, "Can't write to BGP peer %s (%s)\n", peer
->name
,
1021 bgp_set_retry(peer
);
1027 peer
->outbuf
->done
+= r
;
1031 LOG(4, 0, 0, "Sent %s to BGP peer %s\n",
1032 bgp_msg_type_str(peer
->outbuf
->packet
.header
.type
), peer
->name
);
1034 peer
->outbuf
->packet
.header
.len
= 0;
1035 peer
->outbuf
->done
= 0;
1037 if (peer
->state
== Established
)
1038 peer
->keepalive_time
= time_now
+ peer
->keepalive
;
1040 if (peer
->state
!= peer
->next_state
)
1042 if (peer
->next_state
== Disabled
|| peer
->next_state
== Idle
)
1048 peer
->state
= peer
->next_state
;
1049 peer
->state_time
= time_now
;
1051 LOG(4, 0, 0, "BGP peer %s: state %s\n", peer
->name
,
1052 bgp_state_str(peer
->state
));
1058 /* initiate a read */
1059 static int bgp_read(struct bgp_peer
*peer
)
1063 while ((r
= read(peer
->sock
, &peer
->inbuf
->packet
+ peer
->inbuf
->done
,
1064 BGP_MAX_PACKET_SIZE
- peer
->inbuf
->done
)) < 1)
1068 LOG(1, 0, 0, "Connection to BGP peer %s closed\n", peer
->name
);
1075 if (errno
== EAGAIN
)
1078 LOG(1, 0, 0, "Can't read from BGP peer %s (%s)\n", peer
->name
,
1082 bgp_set_retry(peer
);
1086 peer
->inbuf
->done
+= r
;
1090 /* process buffered packets */
1091 static int bgp_handle_input(struct bgp_peer
*peer
)
1093 struct bgp_packet
*p
= &peer
->inbuf
->packet
;
1094 int len
= ntohs(p
->header
.len
);
1096 if (len
> BGP_MAX_PACKET_SIZE
)
1098 LOG(1, 0, 0, "Bad header length from BGP %s\n", peer
->name
);
1099 bgp_send_notification(peer
, BGP_ERR_HEADER
, BGP_ERR_HDR_BAD_LEN
);
1103 if (peer
->inbuf
->done
< len
)
1106 LOG(4, 0, 0, "Received %s from BGP peer %s\n",
1107 bgp_msg_type_str(p
->header
.type
), peer
->name
);
1109 switch (p
->header
.type
)
1113 struct bgp_data_open data
;
1116 off_t param_offset
, capability_offset
;
1117 struct bgp_opt_param
*param
;
1118 uint8_t capabilities_len
;
1119 char *capabilities
= NULL
;
1120 struct bgp_capability
*capability
;
1121 struct bgp_mp_cap_param
*mp_cap
;
1123 for (i
= 0; i
< sizeof(p
->header
.marker
); i
++)
1125 if ((unsigned char) p
->header
.marker
[i
] != 0xff)
1127 LOG(1, 0, 0, "Invalid marker from BGP peer %s\n",
1130 bgp_send_notification(peer
, BGP_ERR_HEADER
,
1131 BGP_ERR_HDR_NOT_SYNC
);
1137 if (peer
->state
!= OpenSent
)
1139 LOG(1, 0, 0, "OPEN from BGP peer %s in %s state\n",
1140 peer
->name
, bgp_state_str(peer
->state
));
1142 bgp_send_notification(peer
, BGP_ERR_FSM
, 0);
1146 memcpy(&data
, p
->data
, len
- sizeof(p
->header
));
1148 if (data
.version
!= BGP_VERSION
)
1150 LOG(1, 0, 0, "Bad version (%d) sent by BGP peer %s\n",
1151 (int) data
.version
, peer
->name
);
1153 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_OPN_VERSION
);
1157 if (ntohs(data
.as
) != peer
->as
)
1159 LOG(1, 0, 0, "Bad AS sent by BGP peer %s (got %d, "
1160 "expected %d)\n", peer
->name
, (int) htons(data
.as
),
1163 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_OPN_BAD_AS
);
1167 if ((hold
= ntohs(data
.hold_time
)) < 3)
1169 LOG(1, 0, 0, "Bad hold time (%d) from BGP peer %s\n",
1172 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_OPN_HOLD_TIME
);
1176 /* pick lowest hold time */
1177 if (hold
< peer
->hold
)
1180 /* adjust our keepalive based on negotiated hold value */
1181 if (peer
->keepalive
* 3 > peer
->hold
)
1182 peer
->keepalive
= peer
->hold
/ 3;
1184 /* check for optional parameters */
1185 /* 2 is for the size of type + len (both uint8_t) */
1186 for (param_offset
= 0;
1187 param_offset
< data
.opt_len
;
1188 param_offset
+= 2 + param
->len
)
1190 param
= (struct bgp_opt_param
*)(&data
.opt_params
+ param_offset
);
1192 /* sensible check */
1193 if (data
.opt_len
- param_offset
< 2
1194 || param
->len
> data
.opt_len
- param_offset
- 2)
1196 LOG(1, 0, 0, "Malformed Optional Parameter list from BGP peer %s\n",
1199 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_UNSPEC
);
1203 /* we know only one parameter type */
1204 if (param
->type
!= BGP_PARAM_TYPE_CAPABILITY
)
1206 LOG(1, 0, 0, "Unsupported Optional Parameter type %d from BGP peer %s\n",
1207 param
->type
, peer
->name
);
1209 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_OPN_UNSUP_PARAM
);
1213 capabilities_len
= param
->len
;
1214 capabilities
= (char *)¶m
->value
;
1217 /* look for BGP multiprotocol capability */
1220 for (capability_offset
= 0;
1221 capability_offset
< capabilities_len
;
1222 capability_offset
+= 2 + capability
->len
)
1224 capability
= (struct bgp_capability
*)(capabilities
+ capability_offset
);
1226 /* sensible check */
1227 if (capabilities_len
- capability_offset
< 2
1228 || capability
->len
> capabilities_len
- capability_offset
- 2)
1230 LOG(1, 0, 0, "Malformed Capabilities list from BGP peer %s\n",
1233 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_UNSPEC
);
1237 /* we only know one capability code */
1238 if (capability
->code
!= BGP_CAP_CODE_MP
1239 && capability
->len
!= sizeof(struct bgp_mp_cap_param
))
1241 LOG(4, 0, 0, "Unsupported Capability code %d from BGP peer %s\n",
1242 capability
->code
, peer
->name
);
1244 bgp_send_notification_full(peer
, BGP_ERR_OPEN
, BGP_ERR_OPN_UNSUP_CAP
,
1245 (char *)capability
, 2 + capability
->len
);
1246 /* we don't terminate, still; we just jump to the next one */
1250 mp_cap
= (struct bgp_mp_cap_param
*)&capability
->value
;
1251 /* the only <AFI, SAFI> tuple we support */
1252 if (ntohs(mp_cap
->afi
) != AF_INET6
&& mp_cap
->safi
!= BGP_MP_SAFI_UNICAST
)
1254 LOG(4, 0, 0, "Unsupported multiprotocol AFI %d and SAFI %d from BGP peer %s\n",
1255 mp_cap
->afi
, mp_cap
->safi
, peer
->name
);
1257 bgp_send_notification_full(peer
, BGP_ERR_OPEN
, BGP_ERR_OPN_UNSUP_CAP
,
1258 (char *)capability
, 2 + capability
->len
);
1259 /* we don't terminate, still; we just jump to the next one */
1263 peer
->handle_ipv6_routes
= 1;
1267 /* next transition requires an exchange of keepalives */
1268 bgp_send_keepalive(peer
);
1273 case BGP_MSG_KEEPALIVE
:
1274 if (peer
->state
== OpenConfirm
)
1276 peer
->state
= peer
->next_state
= Established
;
1277 peer
->state_time
= time_now
;
1278 peer
->keepalive_time
= time_now
+ peer
->keepalive
;
1279 peer
->update_routes
= 1;
1280 peer
->retry_count
= 0;
1281 peer
->retry_time
= 0;
1283 LOG(4, 0, 0, "BGP peer %s: state Established\n", peer
->name
);
1288 case BGP_MSG_NOTIFICATION
:
1289 if (len
> sizeof(p
->header
))
1291 struct bgp_data_notification
*notification
=
1292 (struct bgp_data_notification
*) p
->data
;
1294 if (notification
->error_code
== BGP_ERR_CEASE
)
1296 LOG(4, 0, 0, "BGP peer %s sent CEASE\n", peer
->name
);
1301 if (notification
->error_code
== BGP_ERR_OPEN
1302 && notification
->error_subcode
== BGP_ERR_OPN_UNSUP_CAP
)
1304 /* the only capability we advertise is this one, so upon receiving
1305 an "unsupported capability" message, we disable IPv6 routes for
1307 LOG(4, 0, 0, "BGP peer %s doesn't support IPv6 routes advertisement\n", peer
->name
);
1308 peer
->handle_ipv6_routes
= 0;
1312 /* FIXME: should handle more notifications */
1313 LOG(4, 0, 0, "BGP peer %s sent unhandled NOTIFICATION %d\n",
1314 peer
->name
, (int) notification
->error_code
);
1321 peer
->expire_time
= time_now
+ peer
->hold
;
1323 /* see if there's another message in the same packet/buffer */
1324 if (peer
->inbuf
->done
> len
)
1326 peer
->inbuf
->done
-= len
;
1327 memmove(p
, (char *) p
+ len
, peer
->inbuf
->done
);
1331 peer
->inbuf
->packet
.header
.len
= 0;
1332 peer
->inbuf
->done
= 0;
1335 return peer
->inbuf
->done
;
1338 /* send/buffer OPEN message */
1339 static int bgp_send_open(struct bgp_peer
*peer
)
1341 struct bgp_data_open data
;
1342 struct bgp_mp_cap_param mp_ipv6
= { htons(AF_INET6
), 0, BGP_MP_SAFI_UNICAST
};
1343 struct bgp_capability cap_mp_ipv6
;
1344 struct bgp_opt_param param_cap_mp_ipv6
;
1345 uint16_t len
= sizeof(peer
->outbuf
->packet
.header
);
1347 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1348 sizeof(peer
->outbuf
->packet
.header
.marker
));
1350 peer
->outbuf
->packet
.header
.type
= BGP_MSG_OPEN
;
1352 data
.version
= BGP_VERSION
;
1353 data
.as
= htons(our_as
);
1354 data
.hold_time
= htons(peer
->hold
);
1355 data
.identifier
= my_address
;
1357 /* construct the param and capability */
1358 cap_mp_ipv6
.code
= BGP_CAP_CODE_MP
;
1359 cap_mp_ipv6
.len
= sizeof(mp_ipv6
);
1360 memcpy(&cap_mp_ipv6
.value
, &mp_ipv6
, cap_mp_ipv6
.len
);
1362 param_cap_mp_ipv6
.type
= BGP_PARAM_TYPE_CAPABILITY
;
1363 param_cap_mp_ipv6
.len
= 2 + sizeof(mp_ipv6
);
1364 memcpy(¶m_cap_mp_ipv6
.value
, &cap_mp_ipv6
, param_cap_mp_ipv6
.len
);
1366 data
.opt_len
= 2 + param_cap_mp_ipv6
.len
;
1367 memcpy(&data
.opt_params
, ¶m_cap_mp_ipv6
, data
.opt_len
);
1369 memcpy(peer
->outbuf
->packet
.data
, &data
, BGP_DATA_OPEN_SIZE
);
1370 len
+= BGP_DATA_OPEN_SIZE
;
1372 peer
->outbuf
->packet
.header
.len
= htons(len
);
1373 peer
->outbuf
->done
= 0;
1374 peer
->next_state
= OpenSent
;
1376 return bgp_write(peer
);
1379 /* send/buffer KEEPALIVE message */
1380 static int bgp_send_keepalive(struct bgp_peer
*peer
)
1382 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1383 sizeof(peer
->outbuf
->packet
.header
.marker
));
1385 peer
->outbuf
->packet
.header
.type
= BGP_MSG_KEEPALIVE
;
1386 peer
->outbuf
->packet
.header
.len
=
1387 htons(sizeof(peer
->outbuf
->packet
.header
));
1389 peer
->outbuf
->done
= 0;
1390 peer
->next_state
= (peer
->state
== OpenSent
) ? OpenConfirm
: peer
->state
;
1392 return bgp_write(peer
);
1395 /* send/buffer UPDATE message */
1396 static int bgp_send_update(struct bgp_peer
*peer
)
1398 uint16_t unf_len
= 0;
1400 uint16_t len
= sizeof(peer
->outbuf
->packet
.header
);
1401 struct bgp_route_list
*have
= peer
->routes
;
1402 struct bgp_route_list
*want
= peer
->routing
? bgp_routes
: 0;
1403 struct bgp_route_list
*e
= 0;
1404 struct bgp_route_list
*add
= 0;
1407 char *data
= (char *) &peer
->outbuf
->packet
.data
;
1409 /* need leave room for attr_len, bgp_path_attrs and one prefix */
1410 char *max
= (char *) &peer
->outbuf
->packet
.data
1411 + sizeof(peer
->outbuf
->packet
.data
)
1412 - sizeof(attr_len
) - peer
->path_attr_len
- sizeof(struct bgp_ip_prefix
);
1414 /* skip over unf_len */
1415 data
+= sizeof(unf_len
);
1416 len
+= sizeof(unf_len
);
1418 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1419 sizeof(peer
->outbuf
->packet
.header
.marker
));
1421 peer
->outbuf
->packet
.header
.type
= BGP_MSG_UPDATE
;
1423 peer
->update_routes
= 0; /* tentatively clear */
1425 /* find differences */
1426 while ((have
|| want
) && data
< (max
- sizeof(struct bgp_ip_prefix
)))
1430 ? memcmp(&have
->dest
, &want
->dest
, sizeof(have
->dest
))
1435 if (s
< 0) /* found one to delete */
1437 struct bgp_route_list
*tmp
= have
;
1440 s
= BGP_IP_PREFIX_SIZE(tmp
->dest
);
1441 memcpy(data
, &tmp
->dest
, s
);
1446 LOG(5, 0, 0, "Withdrawing route %s/%d from BGP peer %s\n",
1447 fmtaddr(tmp
->dest
.prefix
, 0), tmp
->dest
.len
, peer
->name
);
1454 peer
->routes
= have
;
1460 e
= have
; /* stash the last found to relink above */
1464 else if (s
> 0) /* addition reqd. */
1468 peer
->update_routes
= 1; /* only one add per packet */
1482 peer
->update_routes
= 1; /* more to do */
1484 /* anything changed? */
1485 if (!(unf_len
|| add
))
1488 /* go back and insert unf_len */
1489 unf_len
= htons(unf_len
);
1490 memcpy(&peer
->outbuf
->packet
.data
, &unf_len
, sizeof(unf_len
));
1494 if (!(e
= malloc(sizeof(*e
))))
1496 LOG(0, 0, 0, "Can't allocate route for %s/%d (%s)\n",
1497 fmtaddr(add
->dest
.prefix
, 0), add
->dest
.len
, strerror(errno
));
1502 memcpy(e
, add
, sizeof(*e
));
1504 peer
->routes
= bgp_insert_route(peer
->routes
, e
);
1506 attr_len
= htons(peer
->path_attr_len
);
1507 memcpy(data
, &attr_len
, sizeof(attr_len
));
1508 data
+= sizeof(attr_len
);
1509 len
+= sizeof(attr_len
);
1511 memcpy(data
, peer
->path_attrs
, peer
->path_attr_len
);
1512 data
+= peer
->path_attr_len
;
1513 len
+= peer
->path_attr_len
;
1515 s
= BGP_IP_PREFIX_SIZE(add
->dest
);
1516 memcpy(data
, &add
->dest
, s
);
1520 LOG(5, 0, 0, "Advertising route %s/%d to BGP peer %s\n",
1521 fmtaddr(add
->dest
.prefix
, 0), add
->dest
.len
, peer
->name
);
1526 memcpy(data
, &attr_len
, sizeof(attr_len
));
1527 data
+= sizeof(attr_len
);
1528 len
+= sizeof(attr_len
);
1531 peer
->outbuf
->packet
.header
.len
= htons(len
);
1532 peer
->outbuf
->done
= 0;
1534 return bgp_write(peer
);
1537 /* send/buffer UPDATE message for IPv6 routes */
1538 static int bgp_send_update6(struct bgp_peer
*peer
)
1540 uint16_t unf_len
= 0;
1544 uint16_t len
= sizeof(peer
->outbuf
->packet
.header
);
1545 struct bgp_route6_list
*have
= peer
->routes6
;
1546 struct bgp_route6_list
*want
= peer
->routing
? bgp_routes6
: 0;
1547 struct bgp_route6_list
*e
= 0;
1548 struct bgp_route6_list
*add
= 0;
1550 char ipv6addr
[INET6_ADDRSTRLEN
];
1552 char *data
= (char *) &peer
->outbuf
->packet
.data
;
1554 /* need leave room for attr_len, bgp_path_attrs and one prefix */
1555 char *max
= (char *) &peer
->outbuf
->packet
.data
1556 + sizeof(peer
->outbuf
->packet
.data
)
1557 - sizeof(attr_len
) - peer
->path_attr_len_without_nexthop
1558 - BGP_PATH_ATTR_MP_REACH_NLRI_PARTIAL_SIZE
- sizeof(struct bgp_ip6_prefix
);
1560 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1561 sizeof(peer
->outbuf
->packet
.header
.marker
));
1563 peer
->outbuf
->packet
.header
.type
= BGP_MSG_UPDATE
;
1565 /* insert non-MP unf_len */
1566 memcpy(data
, &unf_len
, sizeof(unf_len
));
1567 /* skip over attr_len too; will be filled when known */
1568 data
+= sizeof(unf_len
) + sizeof(attr_len
);
1569 len
+= sizeof(unf_len
) + sizeof(attr_len
);
1571 /* copy usual attributes */
1572 memcpy(data
, peer
->path_attrs
, peer
->path_attr_len_without_nexthop
);
1573 data
+= peer
->path_attr_len_without_nexthop
;
1574 len
+= peer
->path_attr_len_without_nexthop
;
1576 /* copy MP unreachable NLRI heading */
1577 memcpy(data
, peer
->mp_unreach_nlri_partial
,
1578 BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE
);
1579 /* remember where to update this attr len */
1580 unreach_len
= data
+ 2;
1581 data
+= BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE
;
1582 len
+= BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE
;
1584 peer
->update_routes6
= 0; /* tentatively clear */
1586 /* find differences */
1587 while ((have
|| want
) && data
< (max
- sizeof(struct bgp_ip6_prefix
)))
1591 ? memcmp(&have
->dest
, &want
->dest
, sizeof(have
->dest
))
1596 if (s
< 0) /* found one to delete */
1598 struct bgp_route6_list
*tmp
= have
;
1601 s
= BGP_IP_PREFIX_SIZE(tmp
->dest
);
1602 memcpy(data
, &tmp
->dest
, s
);
1607 LOG(5, 0, 0, "Withdrawing route %s/%d from BGP peer %s\n",
1608 inet_ntop(AF_INET6
, &tmp
->dest
.prefix
, ipv6addr
, INET6_ADDRSTRLEN
),
1609 tmp
->dest
.len
, peer
->name
);
1616 peer
->routes6
= have
;
1622 e
= have
; /* stash the last found to relink above */
1626 else if (s
> 0) /* addition reqd. */
1630 peer
->update_routes6
= 1; /* only one add per packet */
1644 peer
->update_routes6
= 1; /* more to do */
1646 /* anything changed? */
1647 if (!(unf_len
|| add
))
1650 /* go back and insert MP unf_len */
1651 unf_len
+= sizeof(struct bgp_attr_mp_unreach_nlri_partial
);
1652 unf_len
= htons(unf_len
);
1653 memcpy(&unreach_len
, &unf_len
, sizeof(unf_len
));
1657 if (!(e
= malloc(sizeof(*e
))))
1659 LOG(0, 0, 0, "Can't allocate route for %s/%d (%s)\n",
1660 inet_ntop(AF_INET6
, &add
->dest
.prefix
, ipv6addr
, INET6_ADDRSTRLEN
),
1661 add
->dest
.len
, strerror(errno
));
1666 memcpy(e
, add
, sizeof(*e
));
1668 peer
->routes6
= bgp_insert_route6(peer
->routes6
, e
);
1670 /* copy MP reachable NLRI heading */
1671 memcpy(data
, peer
->mp_reach_nlri_partial
,
1672 BGP_PATH_ATTR_MP_REACH_NLRI_PARTIAL_SIZE
);
1673 /* with proper len */
1674 reach_len
= BGP_IP_PREFIX_SIZE(add
->dest
);
1675 data
[2] = reach_len
;
1676 data
+= BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE
;
1677 len
+= BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE
;
1679 memcpy(data
, &add
->dest
, reach_len
);
1683 LOG(5, 0, 0, "Advertising route %s/%d to BGP peer %s\n",
1684 inet_ntop(AF_INET6
, &add
->dest
.prefix
, ipv6addr
, INET6_ADDRSTRLEN
),
1685 add
->dest
.len
, peer
->name
);
1688 /* go back and insert attr_len */
1689 attr_len
= htons(len
- 4);
1690 memcpy(&peer
->outbuf
->packet
.data
+ 2, &attr_len
, sizeof(attr_len
));
1692 peer
->outbuf
->packet
.header
.len
= htons(len
);
1693 peer
->outbuf
->done
= 0;
1695 return bgp_write(peer
);
1698 /* send/buffer NOTIFICATION message */
1699 static int bgp_send_notification(struct bgp_peer
*peer
, uint8_t code
,
1702 return bgp_send_notification_full(peer
, code
, subcode
, NULL
, 0);
1705 static int bgp_send_notification_full(struct bgp_peer
*peer
, uint8_t code
,
1706 uint8_t subcode
, char *notification_data
, uint16_t data_len
)
1708 struct bgp_data_notification data
;
1711 data
.error_code
= code
;
1712 len
+= sizeof(data
.error_code
);
1714 data
.error_subcode
= subcode
;
1715 len
+= sizeof(data
.error_code
);
1717 memcpy(data
.data
, notification_data
, data_len
);
1720 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1721 sizeof(peer
->outbuf
->packet
.header
.marker
));
1723 peer
->outbuf
->packet
.header
.type
= BGP_MSG_NOTIFICATION
;
1724 peer
->outbuf
->packet
.header
.len
=
1725 htons(sizeof(peer
->outbuf
->packet
.header
) + len
);
1727 memcpy(peer
->outbuf
->packet
.data
, &data
, len
);
1729 peer
->outbuf
->done
= 0;
1730 peer
->next_state
= code
== BGP_ERR_CEASE
? Disabled
: Idle
;
1732 /* we're dying; ignore any pending input */
1733 peer
->inbuf
->packet
.header
.len
= 0;
1734 peer
->inbuf
->done
= 0;
1736 return bgp_write(peer
);