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).
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <arpa/inet.h>
28 static void bgp_clear(struct bgp_peer
*peer
);
29 static void bgp_set_retry(struct bgp_peer
*peer
);
30 static struct bgp_route_list
*bgp_insert_route(struct bgp_route_list
*head
,
31 struct bgp_route_list
*new);
32 static struct bgp_route6_list
*bgp_insert_route6(struct bgp_route6_list
*head
,
33 struct bgp_route6_list
*new);
35 static void bgp_process_timers(struct bgp_peer
*peer
);
36 static void bgp_free_routes(struct bgp_route_list
*routes
);
37 static void bgp_free_routes6(struct bgp_route6_list
*routes
);
38 static char const *bgp_msg_type_str(uint8_t type
);
39 static int bgp_connect(struct bgp_peer
*peer
);
40 static int bgp_handle_connect(struct bgp_peer
*peer
);
41 static int bgp_write(struct bgp_peer
*peer
);
42 static int bgp_read(struct bgp_peer
*peer
);
43 static int bgp_handle_input(struct bgp_peer
*peer
);
44 static int bgp_send_open(struct bgp_peer
*peer
);
45 static int bgp_send_keepalive(struct bgp_peer
*peer
);
46 static int bgp_send_update(struct bgp_peer
*peer
);
47 static int bgp_send_update6(struct bgp_peer
*peer
);
48 static int bgp_send_notification(struct bgp_peer
*peer
, uint8_t code
,
51 static uint16_t our_as
;
52 static struct bgp_route_list
*bgp_routes
= 0;
53 static struct bgp_route6_list
*bgp_routes6
= 0;
55 int bgp_configured
= 0;
56 struct bgp_peer
*bgp_peers
= 0;
58 /* prepare peer structure, globals */
62 struct bgp_peer
*peer
;
64 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
67 memset(peer
, 0, sizeof(*peer
));
69 peer
->addr
= INADDR_NONE
;
71 peer
->state
= peer
->next_state
= Disabled
;
73 if (!((peer
->outbuf
= malloc(sizeof(*peer
->outbuf
)))
74 && (peer
->inbuf
= malloc(sizeof(*peer
->inbuf
)))))
76 LOG(0, 0, 0, "Can't allocate buffers for bgp peer (%s)\n",
82 peer
->edata
.type
= FD_TYPE_BGP
;
83 peer
->edata
.index
= i
;
95 bgp_configured
= 0; /* set by bgp_start */
100 /* start connection with a peer */
101 int bgp_start(struct bgp_peer
*peer
, char *name
, int as
, int keepalive
,
102 int hold
, struct in_addr update_source
, int enable
)
107 struct bgp_path_attr a
;
109 char *p
= path_attrs
;
111 uint32_t metric
= htonl(BGP_METRIC
);
112 uint32_t no_export
= htonl(BGP_COMMUNITY_NO_EXPORT
);
117 if (peer
->state
!= Disabled
)
120 snprintf(peer
->name
, sizeof(peer
->name
), "%s", name
);
122 if (!(h
= gethostbyname(name
)) || h
->h_addrtype
!= AF_INET
)
124 LOG(0, 0, 0, "Can't get address for BGP peer %s (%s)\n",
125 name
, h
? "no address" : hstrerror(h_errno
));
130 memcpy(&peer
->addr
, h
->h_addr
, sizeof(peer
->addr
));
131 peer
->source_addr
= update_source
.s_addr
;
132 peer
->as
= as
> 0 ? as
: our_as
;
133 ibgp
= peer
->as
== our_as
;
135 /* set initial timer values */
136 peer
->init_keepalive
= keepalive
== -1 ? BGP_KEEPALIVE_TIME
: keepalive
;
137 peer
->init_hold
= hold
== -1 ? BGP_HOLD_TIME
: hold
;
139 if (peer
->init_hold
< 3)
142 if (peer
->init_keepalive
* 3 > peer
->init_hold
)
143 peer
->init_keepalive
= peer
->init_hold
/ 3;
145 /* clear buffers, go to Idle state */
146 peer
->next_state
= Idle
;
149 /* set initial routing state */
150 peer
->routing
= enable
;
152 /* all our routes use the same attributes, so prepare it in advance */
153 if (peer
->path_attrs
)
154 free(peer
->path_attrs
);
156 peer
->path_attr_len
= 0;
159 a
.flags
= BGP_PATH_ATTR_FLAG_TRANS
;
160 a
.code
= BGP_PATH_ATTR_CODE_ORIGIN
;
162 a
.data
.s
.value
[0] = BGP_PATH_ATTR_CODE_ORIGIN_IGP
;
164 #define ADD_ATTRIBUTE() do { \
165 i = BGP_PATH_ATTR_SIZE(a); \
168 peer->path_attr_len += i; } while (0)
173 a
.flags
= BGP_PATH_ATTR_FLAG_TRANS
;
174 a
.code
= BGP_PATH_ATTR_CODE_AS_PATH
;
188 BGP_PATH_ATTR_CODE_AS_PATH_AS_SEQUENCE
,
193 a
.data
.s
.len
= sizeof(as_path
);
194 memcpy(&a
.data
.s
.value
, &as_path
, sizeof(as_path
));
199 /* MULTI_EXIT_DISC */
200 a
.flags
= BGP_PATH_ATTR_FLAG_OPTIONAL
;
201 a
.code
= BGP_PATH_ATTR_CODE_MULTI_EXIT_DISC
;
202 a
.data
.s
.len
= sizeof(metric
);
203 memcpy(a
.data
.s
.value
, &metric
, sizeof(metric
));
209 uint32_t local_pref
= htonl(BGP_LOCAL_PREF
);
212 a
.flags
= BGP_PATH_ATTR_FLAG_TRANS
;
213 a
.code
= BGP_PATH_ATTR_CODE_LOCAL_PREF
;
214 a
.data
.s
.len
= sizeof(local_pref
);
215 memcpy(a
.data
.s
.value
, &local_pref
, sizeof(local_pref
));
221 a
.flags
= BGP_PATH_ATTR_FLAG_OPTIONAL
| BGP_PATH_ATTR_FLAG_TRANS
;
222 a
.code
= BGP_PATH_ATTR_CODE_COMMUNITIES
;
223 a
.data
.s
.len
= sizeof(no_export
);
224 memcpy(a
.data
.s
.value
, &no_export
, sizeof(no_export
));
228 /* remember the len before adding NEXT_HOP */
229 peer
->path_attr_len_without_nexthop
= peer
->path_attr_len
;
232 a
.flags
= BGP_PATH_ATTR_FLAG_TRANS
;
233 a
.code
= BGP_PATH_ATTR_CODE_NEXT_HOP
;
234 if (config
->nexthop_address
)
236 ip
= config
->nexthop_address
;
240 ip
= my_address
; /* we're it */
242 a
.data
.s
.len
= sizeof(ip
);
243 memcpy(a
.data
.s
.value
, &ip
, sizeof(ip
));
247 if (!(peer
->path_attrs
= malloc(peer
->path_attr_len
)))
249 LOG(0, 0, 0, "Can't allocate path_attrs for %s (%s)\n",
250 name
, strerror(errno
));
255 memcpy(peer
->path_attrs
, path_attrs
, peer
->path_attr_len
);
257 /* multiprotocol attributes initialization */
258 if (config
->ipv6_prefix
.s6_addr
[0])
260 struct bgp_attr_mp_reach_nlri_partial mp_reach_nlri_partial
;
261 struct bgp_attr_mp_unreach_nlri_partial mp_unreach_nlri_partial
;
263 a
.flags
= BGP_PATH_ATTR_FLAG_OPTIONAL
;
264 a
.code
= BGP_PATH_ATTR_CODE_MP_REACH_NLRI
;
265 a
.data
.s
.len
= 0; /* will be set on UPDATE */
267 mp_reach_nlri_partial
.afi
= htons(BGP_MP_AFI_IPv6
);
268 mp_reach_nlri_partial
.safi
= BGP_MP_SAFI_UNICAST
;
269 mp_reach_nlri_partial
.reserved
= 0;
270 mp_reach_nlri_partial
.next_hop_len
= 16;
272 /* use the defined nexthop6, or our address in ipv6_prefix */
273 if (config
->nexthop6_address
.s6_addr
[0])
274 memcpy(&mp_reach_nlri_partial
.next_hop
,
275 &config
->nexthop6_address
.s6_addr
, 16);
278 /* our address is ipv6prefix::1 */
279 memcpy(&mp_reach_nlri_partial
.next_hop
,
280 &config
->ipv6_prefix
.s6_addr
, 16);
281 mp_reach_nlri_partial
.next_hop
[15] = 1;
284 memcpy(&a
.data
.s
.value
, &mp_reach_nlri_partial
,
285 sizeof(struct bgp_attr_mp_reach_nlri_partial
));
286 memcpy(&peer
->mp_reach_nlri_partial
, &a
,
287 BGP_PATH_ATTR_MP_REACH_NLRI_PARTIAL_SIZE
);
289 a
.flags
= BGP_PATH_ATTR_FLAG_OPTIONAL
| BGP_PATH_ATTR_FLAG_EXTLEN
;
290 a
.code
= BGP_PATH_ATTR_CODE_MP_UNREACH_NLRI
;
291 a
.data
.e
.len
= 0; /* will be set on UPDATE */
293 mp_unreach_nlri_partial
.afi
= htons(BGP_MP_AFI_IPv6
);
294 mp_unreach_nlri_partial
.safi
= BGP_MP_SAFI_UNICAST
;
296 memcpy(&a
.data
.e
.value
, &mp_unreach_nlri_partial
,
297 sizeof(struct bgp_attr_mp_unreach_nlri_partial
));
298 memcpy(&peer
->mp_unreach_nlri_partial
, &a
,
299 BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE
);
302 peer
->mp_handling
= HandlingUnknown
;
304 LOG(4, 0, 0, "Initiating BGP connection to %s (routing %s)\n",
305 name
, enable
? "enabled" : "suspended");
307 /* we have at least one peer configured */
311 return bgp_connect(peer
);
314 /* clear counters, timers, routes and buffers; close socket; move to
315 next_state, which may be Disabled or Idle */
316 static void bgp_clear(struct bgp_peer
*peer
)
318 if (peer
->sock
!= -1)
324 peer
->keepalive_time
= 0;
325 peer
->expire_time
= 0;
327 peer
->keepalive
= peer
->init_keepalive
;
328 peer
->hold
= peer
->init_hold
;
330 bgp_free_routes(peer
->routes
);
332 bgp_free_routes6(peer
->routes6
);
335 peer
->outbuf
->packet
.header
.len
= 0;
336 peer
->outbuf
->done
= 0;
337 peer
->inbuf
->packet
.header
.len
= 0;
338 peer
->inbuf
->done
= 0;
343 if (peer
->state
!= peer
->next_state
)
345 peer
->state
= peer
->next_state
;
346 peer
->state_time
= time_now
;
348 LOG(4, 0, 0, "BGP peer %s: state %s\n", peer
->name
,
349 bgp_state_str(peer
->next_state
));
353 /* initiate a clean shutdown */
354 void bgp_stop(struct bgp_peer
*peer
)
356 LOG(4, 0, 0, "Terminating BGP connection to %s\n", peer
->name
);
357 bgp_send_notification(peer
, BGP_ERR_CEASE
, 0);
360 /* drop connection (if any) and set state to Disabled */
361 void bgp_halt(struct bgp_peer
*peer
)
363 LOG(4, 0, 0, "Aborting BGP connection to %s\n", peer
->name
);
364 peer
->next_state
= Disabled
;
368 /* drop connection (if any) and set to Idle for connection retry */
369 int bgp_restart(struct bgp_peer
*peer
)
371 peer
->next_state
= Idle
;
375 peer
->retry_time
= time_now
;
376 peer
->retry_count
= 0;
379 return bgp_connect(peer
);
382 static void bgp_set_retry(struct bgp_peer
*peer
)
384 if (peer
->retry_count
++ < BGP_MAX_RETRY
)
386 peer
->retry_time
= time_now
+ (BGP_RETRY_BACKOFF
* peer
->retry_count
);
387 peer
->next_state
= Idle
;
391 bgp_halt(peer
); /* give up */
394 /* insert route into list; sorted */
395 static struct bgp_route_list
*bgp_insert_route(struct bgp_route_list
*head
,
396 struct bgp_route_list
*new)
398 struct bgp_route_list
*p
= head
;
399 struct bgp_route_list
*e
= 0;
401 while (p
&& memcmp(&p
->dest
, &new->dest
, sizeof(p
->dest
)) < 0)
421 /* insert route6 into list; sorted */
422 static struct bgp_route6_list
*bgp_insert_route6(struct bgp_route6_list
*head
,
423 struct bgp_route6_list
*new)
425 struct bgp_route6_list
*p
= head
;
426 struct bgp_route6_list
*e
= 0;
428 while (p
&& memcmp(&p
->dest
, &new->dest
, sizeof(p
->dest
)) < 0)
448 /* add route to list for peers */
450 * Note: this doesn't do route aggregation, nor drop routes if a less
451 * specific match already exists (partly because I'm lazy, but also so
452 * that if that route is later deleted we don't have to be concerned
453 * about adding back the more specific one).
455 int bgp_add_route(in_addr_t ip
, int prefixlen
)
457 struct bgp_route_list
*r
= bgp_routes
;
458 struct bgp_route_list add
;
461 add
.dest
.prefix
= ip
;
462 add
.dest
.len
= prefixlen
;
465 /* check for duplicate */
468 i
= memcmp(&r
->dest
, &add
.dest
, sizeof(r
->dest
));
470 return 1; /* already covered */
478 /* insert into route list; sorted */
479 if (!(r
= malloc(sizeof(*r
))))
481 LOG(0, 0, 0, "Can't allocate route for %s/%d (%s)\n",
482 fmtaddr(add
.dest
.prefix
, 0), add
.dest
.len
, strerror(errno
));
487 memcpy(r
, &add
, sizeof(*r
));
488 bgp_routes
= bgp_insert_route(bgp_routes
, r
);
490 /* flag established peers for update */
491 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
492 if (bgp_peers
[i
].state
== Established
)
493 bgp_peers
[i
].update_routes
= 1;
495 LOG(4, 0, 0, "Registered BGP route %s/%d\n",
496 fmtaddr(add
.dest
.prefix
, 0), add
.dest
.len
);
501 /* add route to list for peers */
503 * Note: same provisions as above
505 int bgp_add_route6(struct in6_addr ip
, int prefixlen
)
507 struct bgp_route6_list
*r
= bgp_routes6
;
508 struct bgp_route6_list add
;
510 char ipv6addr
[INET6_ADDRSTRLEN
];
512 memcpy(&add
.dest
.prefix
, &ip
.s6_addr
, 16);
513 add
.dest
.len
= prefixlen
;
516 /* check for duplicate */
519 i
= memcmp(&r
->dest
, &add
.dest
, sizeof(r
->dest
));
521 return 1; /* already covered */
529 /* insert into route list; sorted */
530 if (!(r
= malloc(sizeof(*r
))))
532 LOG(0, 0, 0, "Can't allocate route for %s/%d (%s)\n",
533 inet_ntop(AF_INET6
, &ip
, ipv6addr
, INET6_ADDRSTRLEN
), add
.dest
.len
,
539 memcpy(r
, &add
, sizeof(*r
));
540 bgp_routes6
= bgp_insert_route6(bgp_routes6
, r
);
542 /* flag established peers for update */
543 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
544 if (bgp_peers
[i
].state
== Established
545 && bgp_peers
[i
].mp_handling
== HandleIPv6Routes
)
546 bgp_peers
[i
].update_routes6
= 1;
548 LOG(4, 0, 0, "Registered BGP route %s/%d\n",
549 inet_ntop(AF_INET6
, &ip
, ipv6addr
, INET6_ADDRSTRLEN
), add
.dest
.len
);
554 /* remove route from list for peers */
555 int bgp_del_route(in_addr_t ip
, int prefixlen
)
557 struct bgp_route_list
*r
= bgp_routes
;
558 struct bgp_route_list
*e
= 0;
559 struct bgp_route_list del
;
562 del
.dest
.prefix
= ip
;
563 del
.dest
.len
= prefixlen
;
566 /* find entry in routes list and remove */
569 i
= memcmp(&r
->dest
, &del
.dest
, sizeof(r
->dest
));
575 bgp_routes
= r
->next
;
593 /* flag established peers for update */
594 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
595 if (bgp_peers
[i
].state
== Established
)
596 bgp_peers
[i
].update_routes
= 1;
598 LOG(4, 0, 0, "Removed BGP route %s/%d\n",
599 fmtaddr(del
.dest
.prefix
, 0), del
.dest
.len
);
604 /* remove route from list for peers */
605 int bgp_del_route6(struct in6_addr ip
, int prefixlen
)
607 struct bgp_route6_list
*r
= bgp_routes6
;
608 struct bgp_route6_list
*e
= 0;
609 struct bgp_route6_list del
;
611 char ipv6addr
[INET6_ADDRSTRLEN
];
613 memcpy(&del
.dest
.prefix
, &ip
.s6_addr
, 16);
614 del
.dest
.len
= prefixlen
;
617 /* find entry in routes list and remove */
620 i
= memcmp(&r
->dest
, &del
.dest
, sizeof(r
->dest
));
626 bgp_routes6
= r
->next
;
644 /* flag established peers for update */
645 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
646 if (bgp_peers
[i
].state
== Established
647 && bgp_peers
[i
].mp_handling
== HandleIPv6Routes
)
648 bgp_peers
[i
].update_routes6
= 1;
650 LOG(4, 0, 0, "Removed BGP route %s/%d\n",
651 inet_ntop(AF_INET6
, &ip
, ipv6addr
, INET6_ADDRSTRLEN
), del
.dest
.len
);
656 /* enable or disable routing */
657 void bgp_enable_routing(int enable
)
661 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
663 bgp_peers
[i
].routing
= enable
;
665 /* flag established peers for update */
666 if (bgp_peers
[i
].state
== Established
)
667 bgp_peers
[i
].update_routes
= 1;
670 LOG(4, 0, 0, "%s BGP routing\n", enable
? "Enabled" : "Suspended");
674 # include <sys/epoll.h>
676 # include "fake_epoll.h"
679 /* return a bitmask of the events required to poll this peer's fd */
687 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
689 struct bgp_peer
*peer
= &bgp_peers
[i
];
692 if (peer
->state
== Disabled
|| peer
->state
== Idle
)
695 if (peer
->inbuf
->done
< BGP_MAX_PACKET_SIZE
)
698 if (peer
->state
== Connect
|| /* connection in progress */
699 peer
->update_routes
|| /* routing updates */
700 peer
->outbuf
->packet
.header
.len
) /* pending output */
703 if (peer
->events
!= events
)
705 struct epoll_event ev
;
707 ev
.events
= peer
->events
= events
;
708 ev
.data
.ptr
= &peer
->edata
;
709 epoll_ctl(epollfd
, EPOLL_CTL_MOD
, peer
->sock
, &ev
);
716 /* process bgp events/timers */
717 int bgp_process(uint32_t events
[])
724 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
726 struct bgp_peer
*peer
= &bgp_peers
[i
];
728 if (*peer
->name
&& peer
->cli_flag
== BGP_CLI_RESTART
)
734 if (peer
->state
== Disabled
)
739 switch (peer
->cli_flag
)
741 case BGP_CLI_SUSPEND
:
745 if (peer
->state
== Established
)
746 peer
->update_routes
= 1;
755 if (peer
->state
== Established
)
756 peer
->update_routes
= 1;
765 /* handle empty/fill of buffers */
766 if (events
[i
] & EPOLLOUT
)
769 if (peer
->state
== Connect
)
770 r
= bgp_handle_connect(peer
);
771 else if (peer
->outbuf
->packet
.header
.len
)
778 if (events
[i
] & (EPOLLIN
|EPOLLHUP
))
784 /* process input buffer contents */
785 while (peer
->inbuf
->done
>= sizeof(peer
->inbuf
->packet
.header
)
786 && !peer
->outbuf
->packet
.header
.len
) /* may need to queue a response */
788 if (bgp_handle_input(peer
) < 0)
792 /* process pending updates */
793 if (peer
->update_routes
794 && !peer
->outbuf
->packet
.header
.len
) /* ditto */
796 if (!bgp_send_update(peer
))
800 /* process pending IPv6 updates */
801 if (peer
->update_routes6
802 && !peer
->outbuf
->packet
.header
.len
) /* ditto */
804 if (!bgp_send_update6(peer
))
809 bgp_process_timers(peer
);
815 /* process bgp timers only */
816 void bgp_process_peers_timers()
823 for (i
= 0; i
< BGP_NUM_PEERS
; i
++)
825 struct bgp_peer
*peer
= &bgp_peers
[i
];
827 if (peer
->state
== Disabled
)
830 bgp_process_timers(peer
);
834 static void bgp_process_timers(struct bgp_peer
*peer
)
836 if (peer
->state
== Established
)
838 if (time_now
> peer
->expire_time
)
840 LOG(1, 0, 0, "No message from BGP peer %s in %ds\n",
841 peer
->name
, peer
->hold
);
843 bgp_send_notification(peer
, BGP_ERR_HOLD_TIMER_EXP
, 0);
847 if (time_now
> peer
->keepalive_time
&& !peer
->outbuf
->packet
.header
.len
)
848 bgp_send_keepalive(peer
);
850 else if (peer
->state
== Idle
)
852 if (time_now
> peer
->retry_time
)
855 else if (time_now
> peer
->state_time
+ BGP_STATE_TIME
)
857 LOG(1, 0, 0, "%s timer expired for BGP peer %s\n",
858 bgp_state_str(peer
->state
), peer
->name
);
864 static void bgp_free_routes(struct bgp_route_list
*routes
)
866 struct bgp_route_list
*tmp
;
868 while ((tmp
= routes
))
875 static void bgp_free_routes6(struct bgp_route6_list
*routes
)
877 struct bgp_route6_list
*tmp
;
879 while ((tmp
= routes
))
886 char const *bgp_state_str(enum bgp_state state
)
890 case Disabled
: return "Disabled";
891 case Idle
: return "Idle";
892 case Connect
: return "Connect";
893 case Active
: return "Active";
894 case OpenSent
: return "OpenSent";
895 case OpenConfirm
: return "OpenConfirm";
896 case Established
: return "Established";
902 static char const *bgp_msg_type_str(uint8_t type
)
906 case BGP_MSG_OPEN
: return "OPEN";
907 case BGP_MSG_UPDATE
: return "UPDATE";
908 case BGP_MSG_NOTIFICATION
: return "NOTIFICATION";
909 case BGP_MSG_KEEPALIVE
: return "KEEPALIVE";
915 /* attempt to connect to peer */
916 static int bgp_connect(struct bgp_peer
*peer
)
918 static int bgp_port
= 0;
919 struct sockaddr_in addr
;
920 struct sockaddr_in source_addr
;
921 struct epoll_event ev
;
925 struct servent
*serv
;
926 if (!(serv
= getservbyname("bgp", "tcp")))
928 LOG(0, 0, 0, "Can't get bgp service (%s)\n", strerror(errno
));
932 bgp_port
= serv
->s_port
;
935 if ((peer
->sock
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) < 0)
937 LOG(0, 0, 0, "Can't create a socket for BGP peer %s (%s)\n",
938 peer
->name
, strerror(errno
));
940 peer
->state
= peer
->next_state
= Disabled
;
944 /* add to poll set */
945 ev
.events
= peer
->events
= EPOLLOUT
;
946 ev
.data
.ptr
= &peer
->edata
;
947 epoll_ctl(epollfd
, EPOLL_CTL_ADD
, peer
->sock
, &ev
);
949 /* set to non-blocking */
950 fcntl(peer
->sock
, F_SETFL
, fcntl(peer
->sock
, F_GETFL
, 0) | O_NONBLOCK
);
952 /* set source address */
953 memset(&source_addr
, 0, sizeof(source_addr
));
954 source_addr
.sin_family
= AF_INET
;
955 source_addr
.sin_addr
.s_addr
= peer
->source_addr
; /* defaults to INADDR_ANY */
956 if (bind(peer
->sock
, (struct sockaddr
*) &source_addr
, sizeof(source_addr
)) < 0)
958 LOG(1, 0, 0, "Can't set source address to %s: %s\n",
959 inet_ntoa(source_addr
.sin_addr
), strerror(errno
));
966 memset(&addr
, 0, sizeof(addr
));
967 addr
.sin_family
= AF_INET
;
968 addr
.sin_port
= bgp_port
;
969 addr
.sin_addr
.s_addr
= peer
->addr
;
971 while (connect(peer
->sock
, (struct sockaddr
*) &addr
, sizeof(addr
)) == -1)
973 if (errno
== EINTR
) /* SIGALARM handler */
976 if (errno
!= EINPROGRESS
)
978 LOG(1, 0, 0, "Can't connect to BGP peer %s (%s)\n",
979 inet_ntoa(addr
.sin_addr
), strerror(errno
));
985 peer
->state
= Connect
;
986 peer
->state_time
= time_now
;
988 LOG(4, 0, 0, "BGP peer %s: state Connect\n", peer
->name
);
992 peer
->state
= Active
;
993 peer
->state_time
= time_now
;
994 peer
->retry_time
= peer
->retry_count
= 0;
996 LOG(4, 0, 0, "BGP peer %s: state Active\n", inet_ntoa(addr
.sin_addr
));
998 return bgp_send_open(peer
);
1001 /* complete partial connection (state = Connect) */
1002 static int bgp_handle_connect(struct bgp_peer
*peer
)
1005 socklen_t len
= sizeof(int);
1006 getsockopt(peer
->sock
, SOL_SOCKET
, SO_ERROR
, &err
, &len
);
1009 LOG(1, 0, 0, "Can't connect to BGP peer %s (%s)\n", peer
->name
,
1012 bgp_set_retry(peer
);
1016 peer
->state
= Active
;
1017 peer
->state_time
= time_now
;
1019 LOG(4, 0, 0, "BGP peer %s: state Active\n", peer
->name
);
1021 return bgp_send_open(peer
);
1024 /* initiate a write */
1025 static int bgp_write(struct bgp_peer
*peer
)
1027 int len
= htons(peer
->outbuf
->packet
.header
.len
);
1030 while ((r
= write(peer
->sock
, &peer
->outbuf
->packet
+ peer
->outbuf
->done
,
1031 len
- peer
->outbuf
->done
)) == -1)
1036 if (errno
== EAGAIN
)
1040 LOG(1, 0, 0, "Connection to BGP peer %s closed\n", peer
->name
);
1042 LOG(1, 0, 0, "Can't write to BGP peer %s (%s)\n", peer
->name
,
1045 bgp_set_retry(peer
);
1051 peer
->outbuf
->done
+= r
;
1055 LOG(4, 0, 0, "Sent %s to BGP peer %s\n",
1056 bgp_msg_type_str(peer
->outbuf
->packet
.header
.type
), peer
->name
);
1058 peer
->outbuf
->packet
.header
.len
= 0;
1059 peer
->outbuf
->done
= 0;
1061 if (peer
->state
== Established
)
1062 peer
->keepalive_time
= time_now
+ peer
->keepalive
;
1064 if (peer
->state
!= peer
->next_state
)
1066 if (peer
->next_state
== Disabled
|| peer
->next_state
== Idle
)
1072 peer
->state
= peer
->next_state
;
1073 peer
->state_time
= time_now
;
1075 LOG(4, 0, 0, "BGP peer %s: state %s\n", peer
->name
,
1076 bgp_state_str(peer
->state
));
1082 /* initiate a read */
1083 static int bgp_read(struct bgp_peer
*peer
)
1087 while ((r
= read(peer
->sock
, &peer
->inbuf
->packet
+ peer
->inbuf
->done
,
1088 BGP_MAX_PACKET_SIZE
- peer
->inbuf
->done
)) < 1)
1092 LOG(1, 0, 0, "Connection to BGP peer %s closed\n", peer
->name
);
1099 if (errno
== EAGAIN
)
1102 LOG(1, 0, 0, "Can't read from BGP peer %s (%s)\n", peer
->name
,
1106 bgp_set_retry(peer
);
1110 peer
->inbuf
->done
+= r
;
1114 /* process buffered packets */
1115 static int bgp_handle_input(struct bgp_peer
*peer
)
1117 struct bgp_packet
*p
= &peer
->inbuf
->packet
;
1118 int len
= ntohs(p
->header
.len
);
1120 if (len
> BGP_MAX_PACKET_SIZE
)
1122 LOG(1, 0, 0, "Bad header length from BGP %s\n", peer
->name
);
1123 bgp_send_notification(peer
, BGP_ERR_HEADER
, BGP_ERR_HDR_BAD_LEN
);
1127 if (peer
->inbuf
->done
< len
)
1130 LOG(4, 0, 0, "Received %s from BGP peer %s\n",
1131 bgp_msg_type_str(p
->header
.type
), peer
->name
);
1133 switch (p
->header
.type
)
1137 struct bgp_data_open data
;
1140 off_t param_offset
, capability_offset
;
1141 struct bgp_opt_param
*param
;
1142 uint8_t capabilities_len
;
1143 char *capabilities
= NULL
;
1144 struct bgp_capability
*capability
;
1145 struct bgp_mp_cap_param
*mp_cap
;
1147 for (i
= 0; i
< sizeof(p
->header
.marker
); i
++)
1149 if ((unsigned char) p
->header
.marker
[i
] != 0xff)
1151 LOG(1, 0, 0, "Invalid marker from BGP peer %s\n",
1154 bgp_send_notification(peer
, BGP_ERR_HEADER
,
1155 BGP_ERR_HDR_NOT_SYNC
);
1161 if (peer
->state
!= OpenSent
)
1163 LOG(1, 0, 0, "OPEN from BGP peer %s in %s state\n",
1164 peer
->name
, bgp_state_str(peer
->state
));
1166 bgp_send_notification(peer
, BGP_ERR_FSM
, 0);
1170 memcpy(&data
, p
->data
, len
- sizeof(p
->header
));
1172 if (data
.version
!= BGP_VERSION
)
1174 LOG(1, 0, 0, "Bad version (%d) sent by BGP peer %s\n",
1175 (int) data
.version
, peer
->name
);
1177 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_OPN_VERSION
);
1181 if (ntohs(data
.as
) != peer
->as
)
1183 LOG(1, 0, 0, "Bad AS sent by BGP peer %s (got %d, "
1184 "expected %d)\n", peer
->name
, (int) htons(data
.as
),
1187 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_OPN_BAD_AS
);
1191 if ((hold
= ntohs(data
.hold_time
)) < 3)
1193 LOG(1, 0, 0, "Bad hold time (%d) from BGP peer %s\n",
1196 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_OPN_HOLD_TIME
);
1200 /* pick lowest hold time */
1201 if (hold
< peer
->hold
)
1204 /* adjust our keepalive based on negotiated hold value */
1205 if (peer
->keepalive
* 3 > peer
->hold
)
1206 peer
->keepalive
= peer
->hold
/ 3;
1208 /* check for optional parameters */
1209 /* 2 is for the size of type + len (both uint8_t) */
1210 for (param_offset
= 0;
1211 param_offset
< data
.opt_len
;
1212 param_offset
+= 2 + param
->len
)
1214 param
= (struct bgp_opt_param
*)((char *)&data
.opt_params
+ param_offset
);
1216 /* sensible check */
1217 if (data
.opt_len
- param_offset
< 2
1218 || param
->len
> data
.opt_len
- param_offset
- 2)
1220 LOG(1, 0, 0, "Malformed Optional Parameter list from BGP peer %s\n",
1223 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_UNSPEC
);
1227 /* we know only one parameter type */
1228 if (param
->type
!= BGP_PARAM_TYPE_CAPABILITY
)
1230 LOG(1, 0, 0, "Unsupported Optional Parameter type %d from BGP peer %s\n",
1231 param
->type
, peer
->name
);
1233 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_OPN_UNSUP_PARAM
);
1237 capabilities_len
= param
->len
;
1238 capabilities
= (char *)¶m
->value
;
1240 /* look for BGP multiprotocol capability */
1241 for (capability_offset
= 0;
1242 capability_offset
< capabilities_len
;
1243 capability_offset
+= 2 + capability
->len
)
1245 capability
= (struct bgp_capability
*)(capabilities
+ capability_offset
);
1247 /* sensible check */
1248 if (capabilities_len
- capability_offset
< 2
1249 || capability
->len
> capabilities_len
- capability_offset
- 2)
1251 LOG(1, 0, 0, "Malformed Capabilities list from BGP peer %s\n",
1254 bgp_send_notification(peer
, BGP_ERR_OPEN
, BGP_ERR_UNSPEC
);
1258 /* we only know one capability code */
1259 if (capability
->code
!= BGP_CAP_CODE_MP
1260 && capability
->len
!= sizeof(struct bgp_mp_cap_param
))
1262 LOG(4, 0, 0, "Unsupported Capability code %d from BGP peer %s\n",
1263 capability
->code
, peer
->name
);
1265 /* we don't terminate, still; we just jump to the next one */
1269 mp_cap
= (struct bgp_mp_cap_param
*)&capability
->value
;
1270 /* the only <AFI, SAFI> tuple we support */
1271 if (ntohs(mp_cap
->afi
) != BGP_MP_AFI_IPv6
&& mp_cap
->safi
!= BGP_MP_SAFI_UNICAST
)
1273 LOG(4, 0, 0, "Unsupported multiprotocol AFI %d and SAFI %d from BGP peer %s\n",
1274 mp_cap
->afi
, mp_cap
->safi
, peer
->name
);
1276 /* we don't terminate, still; we just jump to the next one */
1281 peer
->mp_handling
= HandleIPv6Routes
;
1285 if (peer
->mp_handling
!= HandleIPv6Routes
)
1287 peer
->mp_handling
= DoesntHandleIPv6Routes
;
1288 if (config
->ipv6_prefix
.s6_addr
[0])
1289 LOG(1, 0, 0, "Warning: BGP peer %s doesn't handle IPv6 prefixes updates\n",
1293 /* next transition requires an exchange of keepalives */
1294 bgp_send_keepalive(peer
);
1299 case BGP_MSG_KEEPALIVE
:
1300 if (peer
->state
== OpenConfirm
)
1302 peer
->state
= peer
->next_state
= Established
;
1303 peer
->state_time
= time_now
;
1304 peer
->keepalive_time
= time_now
+ peer
->keepalive
;
1305 peer
->update_routes
= 1;
1306 peer
->retry_count
= 0;
1307 peer
->retry_time
= 0;
1309 LOG(4, 0, 0, "BGP peer %s: state Established\n", peer
->name
);
1314 case BGP_MSG_NOTIFICATION
:
1315 if (len
> sizeof(p
->header
))
1317 struct bgp_data_notification
*notification
=
1318 (struct bgp_data_notification
*) p
->data
;
1320 if (notification
->error_code
== BGP_ERR_CEASE
)
1322 LOG(4, 0, 0, "BGP peer %s sent CEASE\n", peer
->name
);
1323 bgp_set_retry(peer
);
1327 if (notification
->error_code
== BGP_ERR_OPEN
1328 && notification
->error_subcode
== BGP_ERR_OPN_UNSUP_PARAM
)
1330 LOG(4, 0, 0, "BGP peer %s doesn't support BGP Capabilities\n", peer
->name
);
1331 peer
->mp_handling
= DoesntHandleIPv6Routes
;
1332 bgp_set_retry(peer
);
1336 if (notification
->error_code
== BGP_ERR_OPEN
1337 && notification
->error_subcode
== BGP_ERR_OPN_UNSUP_CAP
)
1339 /* the only capability we advertise is this one, so upon receiving
1340 an "unsupported capability" message, we disable IPv6 routes for
1342 LOG(4, 0, 0, "BGP peer %s doesn't support IPv6 routes advertisement\n", peer
->name
);
1343 peer
->mp_handling
= DoesntHandleIPv6Routes
;
1347 /* FIXME: should handle more notifications */
1348 LOG(4, 0, 0, "BGP peer %s sent unhandled NOTIFICATION %d\n",
1349 peer
->name
, (int) notification
->error_code
);
1356 peer
->expire_time
= time_now
+ peer
->hold
;
1358 /* see if there's another message in the same packet/buffer */
1359 if (peer
->inbuf
->done
> len
)
1361 peer
->inbuf
->done
-= len
;
1362 memmove(p
, (char *) p
+ len
, peer
->inbuf
->done
);
1366 peer
->inbuf
->packet
.header
.len
= 0;
1367 peer
->inbuf
->done
= 0;
1370 return peer
->inbuf
->done
;
1373 /* send/buffer OPEN message */
1374 static int bgp_send_open(struct bgp_peer
*peer
)
1376 struct bgp_data_open data
;
1377 struct bgp_mp_cap_param mp_ipv6
= { htons(BGP_MP_AFI_IPv6
), 0, BGP_MP_SAFI_UNICAST
};
1378 struct bgp_capability cap_mp_ipv6
;
1379 struct bgp_opt_param param_cap_mp_ipv6
;
1380 uint16_t len
= sizeof(peer
->outbuf
->packet
.header
);
1382 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1383 sizeof(peer
->outbuf
->packet
.header
.marker
));
1385 peer
->outbuf
->packet
.header
.type
= BGP_MSG_OPEN
;
1387 data
.version
= BGP_VERSION
;
1388 data
.as
= htons(our_as
);
1389 data
.hold_time
= htons(peer
->hold
);
1390 /* use the source IP we use as identifier, if available */
1391 if (peer
->source_addr
!= INADDR_ANY
)
1392 data
.identifier
= peer
->source_addr
;
1394 data
.identifier
= my_address
;
1396 /* if we know peer doesn't support MP (mp_handling == DoesntHandleIPv6Routes)
1397 then don't add this parameter */
1398 if (config
->ipv6_prefix
.s6_addr
[0]
1399 && (peer
->mp_handling
== HandlingUnknown
1400 || peer
->mp_handling
== HandleIPv6Routes
))
1402 /* construct the param and capability */
1403 cap_mp_ipv6
.code
= BGP_CAP_CODE_MP
;
1404 cap_mp_ipv6
.len
= sizeof(mp_ipv6
);
1405 memcpy(&cap_mp_ipv6
.value
, &mp_ipv6
, cap_mp_ipv6
.len
);
1407 param_cap_mp_ipv6
.type
= BGP_PARAM_TYPE_CAPABILITY
;
1408 param_cap_mp_ipv6
.len
= 2 + sizeof(mp_ipv6
);
1409 memcpy(¶m_cap_mp_ipv6
.value
, &cap_mp_ipv6
, param_cap_mp_ipv6
.len
);
1411 data
.opt_len
= 2 + param_cap_mp_ipv6
.len
;
1412 memcpy(&data
.opt_params
, ¶m_cap_mp_ipv6
, data
.opt_len
);
1417 memcpy(peer
->outbuf
->packet
.data
, &data
, BGP_DATA_OPEN_SIZE
+ data
.opt_len
);
1418 len
+= BGP_DATA_OPEN_SIZE
+ data
.opt_len
;
1420 peer
->outbuf
->packet
.header
.len
= htons(len
);
1421 peer
->outbuf
->done
= 0;
1422 peer
->next_state
= OpenSent
;
1424 return bgp_write(peer
);
1427 /* send/buffer KEEPALIVE message */
1428 static int bgp_send_keepalive(struct bgp_peer
*peer
)
1430 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1431 sizeof(peer
->outbuf
->packet
.header
.marker
));
1433 peer
->outbuf
->packet
.header
.type
= BGP_MSG_KEEPALIVE
;
1434 peer
->outbuf
->packet
.header
.len
=
1435 htons(sizeof(peer
->outbuf
->packet
.header
));
1437 peer
->outbuf
->done
= 0;
1438 peer
->next_state
= (peer
->state
== OpenSent
) ? OpenConfirm
: peer
->state
;
1440 return bgp_write(peer
);
1443 /* send/buffer UPDATE message */
1444 static int bgp_send_update(struct bgp_peer
*peer
)
1446 uint16_t unf_len
= 0;
1448 uint16_t len
= sizeof(peer
->outbuf
->packet
.header
);
1449 struct bgp_route_list
*have
= peer
->routes
;
1450 struct bgp_route_list
*want
= peer
->routing
? bgp_routes
: 0;
1451 struct bgp_route_list
*e
= 0;
1452 struct bgp_route_list
*add
= 0;
1455 char *data
= (char *) &peer
->outbuf
->packet
.data
;
1457 /* need leave room for attr_len, bgp_path_attrs and one prefix */
1458 char *max
= (char *) &peer
->outbuf
->packet
.data
1459 + sizeof(peer
->outbuf
->packet
.data
)
1460 - sizeof(attr_len
) - peer
->path_attr_len
- sizeof(struct bgp_ip_prefix
);
1462 /* skip over unf_len */
1463 data
+= sizeof(unf_len
);
1464 len
+= sizeof(unf_len
);
1466 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1467 sizeof(peer
->outbuf
->packet
.header
.marker
));
1469 peer
->outbuf
->packet
.header
.type
= BGP_MSG_UPDATE
;
1471 peer
->update_routes
= 0; /* tentatively clear */
1473 /* find differences */
1474 while ((have
|| want
) && data
< (max
- sizeof(struct bgp_ip_prefix
)))
1478 ? memcmp(&have
->dest
, &want
->dest
, sizeof(have
->dest
))
1483 if (s
< 0) /* found one to delete */
1485 struct bgp_route_list
*tmp
= have
;
1488 s
= BGP_IP_PREFIX_SIZE(tmp
->dest
);
1489 memcpy(data
, &tmp
->dest
, s
);
1494 LOG(5, 0, 0, "Withdrawing route %s/%d from BGP peer %s\n",
1495 fmtaddr(tmp
->dest
.prefix
, 0), tmp
->dest
.len
, peer
->name
);
1502 peer
->routes
= have
;
1508 e
= have
; /* stash the last found to relink above */
1512 else if (s
> 0) /* addition reqd. */
1516 peer
->update_routes
= 1; /* only one add per packet */
1530 peer
->update_routes
= 1; /* more to do */
1532 /* anything changed? */
1533 if (!(unf_len
|| add
))
1536 /* go back and insert unf_len */
1537 unf_len
= htons(unf_len
);
1538 memcpy(&peer
->outbuf
->packet
.data
, &unf_len
, sizeof(unf_len
));
1542 if (!(e
= malloc(sizeof(*e
))))
1544 LOG(0, 0, 0, "Can't allocate route for %s/%d (%s)\n",
1545 fmtaddr(add
->dest
.prefix
, 0), add
->dest
.len
, strerror(errno
));
1550 memcpy(e
, add
, sizeof(*e
));
1552 peer
->routes
= bgp_insert_route(peer
->routes
, e
);
1554 attr_len
= htons(peer
->path_attr_len
);
1555 memcpy(data
, &attr_len
, sizeof(attr_len
));
1556 data
+= sizeof(attr_len
);
1557 len
+= sizeof(attr_len
);
1559 memcpy(data
, peer
->path_attrs
, peer
->path_attr_len
);
1560 data
+= peer
->path_attr_len
;
1561 len
+= peer
->path_attr_len
;
1563 s
= BGP_IP_PREFIX_SIZE(add
->dest
);
1564 memcpy(data
, &add
->dest
, s
);
1568 LOG(5, 0, 0, "Advertising route %s/%d to BGP peer %s\n",
1569 fmtaddr(add
->dest
.prefix
, 0), add
->dest
.len
, peer
->name
);
1574 memcpy(data
, &attr_len
, sizeof(attr_len
));
1575 data
+= sizeof(attr_len
);
1576 len
+= sizeof(attr_len
);
1579 peer
->outbuf
->packet
.header
.len
= htons(len
);
1580 peer
->outbuf
->done
= 0;
1582 return bgp_write(peer
);
1585 /* send/buffer UPDATE message for IPv6 routes */
1586 static int bgp_send_update6(struct bgp_peer
*peer
)
1589 uint16_t unreach_len
= 0;
1590 char *unreach_len_pos
;
1592 uint16_t len
= sizeof(peer
->outbuf
->packet
.header
);
1593 struct bgp_route6_list
*have
= peer
->routes6
;
1594 struct bgp_route6_list
*want
= peer
->routing
? bgp_routes6
: 0;
1595 struct bgp_route6_list
*e
= 0;
1596 struct bgp_route6_list
*add
= 0;
1598 char ipv6addr
[INET6_ADDRSTRLEN
];
1600 char *data
= (char *) &peer
->outbuf
->packet
.data
;
1602 /* need leave room for attr_len, bgp_path_attrs and one prefix */
1603 char *max
= (char *) &peer
->outbuf
->packet
.data
1604 + sizeof(peer
->outbuf
->packet
.data
)
1605 - sizeof(attr_len
) - peer
->path_attr_len_without_nexthop
1606 - BGP_PATH_ATTR_MP_REACH_NLRI_PARTIAL_SIZE
- sizeof(struct bgp_ip6_prefix
);
1608 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1609 sizeof(peer
->outbuf
->packet
.header
.marker
));
1611 peer
->outbuf
->packet
.header
.type
= BGP_MSG_UPDATE
;
1613 /* insert non-MP unfeasible routes length */
1614 memcpy(data
, &unreach_len
, sizeof(unreach_len
));
1615 /* skip over it and attr_len too; it will be filled when known */
1616 data
+= sizeof(unreach_len
) + sizeof(attr_len
);
1617 len
+= sizeof(unreach_len
) + sizeof(attr_len
);
1619 /* copy usual attributes */
1620 memcpy(data
, peer
->path_attrs
, peer
->path_attr_len_without_nexthop
);
1621 data
+= peer
->path_attr_len_without_nexthop
;
1622 attr_len
= peer
->path_attr_len_without_nexthop
;
1624 /* copy MP unreachable NLRI heading */
1625 memcpy(data
, peer
->mp_unreach_nlri_partial
,
1626 BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE
);
1627 /* remember where to update this attr len */
1628 unreach_len_pos
= data
+ 2;
1629 data
+= BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE
;
1630 attr_len
+= BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE
;
1632 peer
->update_routes6
= 0; /* tentatively clear */
1634 /* find differences */
1635 while ((have
|| want
) && data
< (max
- sizeof(struct bgp_ip6_prefix
)))
1639 ? memcmp(&have
->dest
, &want
->dest
, sizeof(have
->dest
))
1644 if (s
< 0) /* found one to delete */
1646 struct bgp_route6_list
*tmp
= have
;
1649 s
= BGP_IP_PREFIX_SIZE(tmp
->dest
);
1650 memcpy(data
, &tmp
->dest
, s
);
1655 LOG(5, 0, 0, "Withdrawing route %s/%d from BGP peer %s\n",
1656 inet_ntop(AF_INET6
, &tmp
->dest
.prefix
, ipv6addr
, INET6_ADDRSTRLEN
),
1657 tmp
->dest
.len
, peer
->name
);
1664 peer
->routes6
= have
;
1670 e
= have
; /* stash the last found to relink above */
1674 else if (s
> 0) /* addition reqd. */
1678 peer
->update_routes6
= 1; /* only one add per packet */
1692 peer
->update_routes6
= 1; /* more to do */
1694 /* anything changed? */
1695 if (!(unreach_len
|| add
))
1700 /* go back and insert MP unreach_len */
1701 unreach_len
+= sizeof(struct bgp_attr_mp_unreach_nlri_partial
);
1702 unreach_len
= htons(unreach_len
);
1703 memcpy(unreach_len_pos
, &unreach_len
, sizeof(unreach_len
));
1707 /* we can remove this attribute, then */
1708 data
-= BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE
;
1709 attr_len
-= BGP_PATH_ATTR_MP_UNREACH_NLRI_PARTIAL_SIZE
;
1714 if (!(e
= malloc(sizeof(*e
))))
1716 LOG(0, 0, 0, "Can't allocate route for %s/%d (%s)\n",
1717 inet_ntop(AF_INET6
, &add
->dest
.prefix
, ipv6addr
, INET6_ADDRSTRLEN
),
1718 add
->dest
.len
, strerror(errno
));
1723 memcpy(e
, add
, sizeof(*e
));
1725 peer
->routes6
= bgp_insert_route6(peer
->routes6
, e
);
1727 /* copy MP reachable NLRI heading */
1728 memcpy(data
, peer
->mp_reach_nlri_partial
,
1729 BGP_PATH_ATTR_MP_REACH_NLRI_PARTIAL_SIZE
);
1730 /* with proper len */
1731 reach_len
= BGP_IP_PREFIX_SIZE(add
->dest
);
1732 data
[2] = sizeof(struct bgp_attr_mp_reach_nlri_partial
) + reach_len
;
1733 data
+= BGP_PATH_ATTR_MP_REACH_NLRI_PARTIAL_SIZE
;
1734 attr_len
+= BGP_PATH_ATTR_MP_REACH_NLRI_PARTIAL_SIZE
;
1736 memcpy(data
, &add
->dest
, reach_len
);
1738 attr_len
+= reach_len
;
1740 LOG(5, 0, 0, "Advertising route %s/%d to BGP peer %s\n",
1741 inet_ntop(AF_INET6
, &add
->dest
.prefix
, ipv6addr
, INET6_ADDRSTRLEN
),
1742 add
->dest
.len
, peer
->name
);
1745 /* update len with attributes we added */
1748 /* go back and insert attr_len */
1749 attr_len
= htons(attr_len
);
1750 memcpy((char *)&peer
->outbuf
->packet
.data
+ 2, &attr_len
, sizeof(attr_len
));
1752 peer
->outbuf
->packet
.header
.len
= htons(len
);
1753 peer
->outbuf
->done
= 0;
1755 return bgp_write(peer
);
1758 /* send/buffer NOTIFICATION message */
1759 static int bgp_send_notification(struct bgp_peer
*peer
, uint8_t code
,
1762 struct bgp_data_notification data
;
1765 data
.error_code
= code
;
1766 len
+= sizeof(data
.error_code
);
1768 data
.error_subcode
= subcode
;
1769 len
+= sizeof(data
.error_code
);
1771 memset(peer
->outbuf
->packet
.header
.marker
, 0xff,
1772 sizeof(peer
->outbuf
->packet
.header
.marker
));
1774 peer
->outbuf
->packet
.header
.type
= BGP_MSG_NOTIFICATION
;
1775 peer
->outbuf
->packet
.header
.len
=
1776 htons(sizeof(peer
->outbuf
->packet
.header
) + len
);
1778 memcpy(peer
->outbuf
->packet
.data
, &data
, len
);
1780 peer
->outbuf
->done
= 0;
1781 peer
->next_state
= code
== BGP_ERR_CEASE
? Disabled
: Idle
;
1783 /* we're dying; ignore any pending input */
1784 peer
->inbuf
->packet
.header
.len
= 0;
1785 peer
->inbuf
->done
= 0;
1787 return bgp_write(peer
);