16 #include <arpa/inet.h>    20 const char* bgp_fsm_state_str[] = {
    28 BgpFsm::BgpFsm(
const BgpConfig &config) : in_sink(config.use_4b_asn) {
    29     this->config = config;
    31     out_buffer = (uint8_t *) malloc(BGP_FSM_BUFFER_SIZE);
    35         config.rev_bus->subscribe(
this);
    36     } 
else rev_bus_exist = 
false;
    39         clock = 
new RealtimeClock();
    46     if (!config.log_handler) {
    47         logger = 
new BgpLogHandler();
    50         logger = config.log_handler;
    54     in_sink.setLogger(logger);
    57         rib4 = 
new BgpRib4(logger);
    65         rib6 = 
new BgpRib6(logger);
    79     if (rib4_local) 
delete rib4;
    80     if (rib6_local) 
delete rib6;
    81     if (clock_local) 
delete clock;
    82     if (rev_bus_exist) config.rev_bus->unsubscribe(
this);
    83     if (log_local) 
delete logger;
    91     return config.router_id;
   107     return rib4_local ? *rib4 : *(config.rib4);
   111     return rib4_local ? *rib6 : *(config.rib6);
   119     if (state == BROKEN) {
   120         logger->log(ERROR, 
"BgpFsm::start: FSM is broken, consider reset.\n");
   125         logger->log(ERROR, 
"BgpFsm::start: not in IDLE state.\n");
   129     logger->log(DEBUG, 
"BgpFsm::start: sending OPEN message to peer.\n");
   131     uint16_t my_asn_2b = config.asn >= 0xffff ? 23456 : config.asn;
   133     BgpOpenMessage msg(logger, config.use_4b_asn, my_asn_2b, config.hold_timer, config.router_id);
   134     if (config.use_4b_asn) {
   138     if (config.mp_bgp_ipv4) {
   145     if (config.mp_bgp_ipv6) {
   153     if(!writeMessage(msg)) 
return -1;
   158     if (state == BROKEN) {
   159         logger->log(ERROR, 
"BgpFsm::stop: FSM is broken, consider reset.\n");
   163     if (state == IDLE) 
return 1;
   164     if (state != ESTABLISHED) {
   165         logger->log(ERROR, 
"BgpFsm::stop: FSM in not ESTABLISED nor IDLE, can't stop. To force stop, do a reset.\n");
   169     logger->log(INFO, 
"BgpFsm::stop: de-peering...\n");
   175     if(!writeMessage(notify)) 
return -1;
   179 int BgpFsm::run(
const uint8_t *buffer, 
const size_t buffer_size) {
   180     if (state == BROKEN) {
   181         logger->log(ERROR, 
"BgpFsm::run: FSM is broken, consider reset.\n");
   185     ssize_t fill_ret = in_sink.fill(buffer, buffer_size);
   186     if (fill_ret != (ssize_t) buffer_size) {
   187         logger->log(ERROR, 
"BgpFsm::run: failed to fill() sink.\n");
   193     if (!config.no_autotick) {
   194         int tick_ret = tick();
   195         if (tick_ret <= 0) 
return tick_ret;
   198     last_recv = clock->getTime();
   200     int final_ret_val = -1;
   203     while (in_sink.getBytesInSink() > 0) {
   205         ssize_t poured = in_sink.pour(&packet);
   208             logger->log(ERROR, 
"BgpFsm::run: sink seems to be broken, please reset.\n");
   213         if (poured == 0) 
return 3;
   215         LIBBGP_LOG(logger, DEBUG) {
   216             logger->log(DEBUG, 
"BgpFsm::run: got message (Current state: %s):\n", bgp_fsm_state_str[state]);
   217             logger->log(DEBUG, *packet);
   226             if (msg->type == NOTIFICATION) {
   227                 logger->log(ERROR, 
"BgpFsm::run: got invalid NOTIFICATION message.\n");
   228                 if (state == ESTABLISHED) {
   229                     logger->log(ERROR, 
"BgpFsm::run: discarding all routes.\n");
   236             BgpNotificationMessage notify (logger, msg->getErrorCode(), msg->getErrorSubCode(), msg->getError(), msg->getErrorLength());
   238             if(!writeMessage(notify)) 
return -1;
   243         if (msg->type == NOTIFICATION) {
   254             logger->log(ERROR, 
"BgpFsm::run: got NOTIFICATION: %s (%d): %s (%d).\n", err_msg, notify->
errcode, err_sub_msg, notify->
subcode);
   262         int vald_ret = validateState(msg->type);
   269             case IDLE: retval = fsmEvalIdle(msg); 
break;
   270             case OPEN_SENT: retval = fsmEvalOpenSent(msg); 
break;
   271             case OPEN_CONFIRM: retval = fsmEvalOpenConfirm(msg); 
break;
   272             case ESTABLISHED: retval = fsmEvalEstablished(msg); 
break;
   274                 logger->log(ERROR, 
"BgpFsm::run: FSM in invalid state: %d.\n", state);
   281         if (retval < 0) 
return retval;
   282         if (retval == 0) final_ret_val = 0;
   283         if (retval == 1 && final_ret_val != 0 && final_ret_val != 2) final_ret_val = 1;
   284         if (retval == 2) final_ret_val = 2;
   287     return final_ret_val;
   291     if (state != ESTABLISHED) 
return 1;
   294     uint64_t now = clock->getTime();
   295     if (hold_timer > 0 && now - last_recv > hold_timer) {
   296         logger->log(ERROR, 
"BgpFsm::tick: peer hold timer expired (last_recv: %d, now: %d, diff: %d, hold: %d).\n", last_recv, now, now - last_recv, hold_timer);
   299         if(!writeMessage(notify)) 
return -1;
   304     if (hold_timer > 0 && now - last_sent > hold_timer / 3) {
   306         if(!writeMessage(keep)) 
return -1;
   315     if(!writeMessage(notify)) 
return -1;
   326     if (open_msg->version != 4) {
   329         if(!writeMessage(notify)) 
return -1;
   333     peer_asn = open_msg->
getAsn();
   335     if (config.peer_asn != 0 && peer_asn != config.peer_asn) {
   338         if(!writeMessage(notify)) 
return -1;
   342     ibgp = config.asn == peer_asn;
   344     if (!validAddr4(open_msg->bgp_id)) {
   345         LIBBGP_LOG(logger, ERROR) {
   346             char ip_str[INET_ADDRSTRLEN];
   347             inet_ntop(AF_INET, &(open_msg->bgp_id), ip_str, INET_ADDRSTRLEN);
   348             logger->log(ERROR, 
"BgpFsm::openRecv: peer BGP ID (%s) invalid.\n", ip_str);
   352         if(!writeMessage(notify)) 
return -1;
   357     if (open_msg->hold_time < 3 && open_msg->hold_time != 0) {
   358         logger->log(ERROR, 
"BgpFsm::openRecv: invalid hold timer %d.\n", open_msg->hold_time);
   361         if(!writeMessage(notify)) 
return -1;
   365     if (!config.no_collision_detection && rev_bus_exist) {
   367         col.peer_bgp_id = open_msg->bgp_id;
   374         if(config.rev_bus->publish(
this, col) > 0) {
   375             int res_result = resloveCollision(open_msg->bgp_id, 
true);
   377             if(res_result == -1) 
return -1;
   378             if(res_result == 0) 
return 0;
   381             if(res_result == 1) {
   383                     "BgpFsm::openRecv: collision found, and some other FSM feels like they should live"   384                     "while we feel like we should live too. is there duplicated FSMs?\n"   392     hold_timer = config.hold_timer > open_msg->hold_time ? open_msg->hold_time : config.hold_timer;
   393     peer_bgp_id = open_msg->bgp_id;
   394     use_4b_asn = open_msg->
hasCapability(ASN_4B) && config.use_4b_asn;
   395     send_ipv4_routes = 
true;
   396     if (open_msg->
hasCapability(MP_BGP) && (config.mp_bgp_ipv6 || config.mp_bgp_ipv4)) {
   397         send_ipv4_routes = send_ipv6_routes = 
false;
   399         const std::vector<std::shared_ptr<BgpCapability>> &capabilities = open_msg->
getCapabilities();
   401         for (
const std::shared_ptr<BgpCapability> &cap : capabilities) {
   402             if (cap->code == MP_BGP) {
   404                 if (mp_cap.
safi != UNICAST) 
continue;
   405                 if (mp_cap.
afi == IPV6) send_ipv6_routes = 
true && config.mp_bgp_ipv6;
   406                 if (mp_cap.
afi == IPV4) send_ipv4_routes = 
true && config.mp_bgp_ipv4;
   410         send_ipv4_routes = 
true && !(config.mp_bgp_ipv6 && !config.mp_bgp_ipv4);
   411         send_ipv6_routes = 
false;
   417 int BgpFsm::resloveCollision(uint32_t peer_bgp_id, 
bool is_new) {
   419         if (ntohl(config.router_id) > ntohl(peer_bgp_id)) {
   424             if(!writeMessage(notify)) 
return -1;
   426             logger->log(INFO, 
"(new_session) we have higher router id, dispose this new session.\n");
   435             logger->log(INFO, 
"(new_session) peer has higher router id, ask the other fsm to dispose session.\n");
   439         if (ntohl(config.router_id) > ntohl(peer_bgp_id)) {
   442             logger->log(INFO, 
"(old_session) we have higher router id, keep this old session.\n");
   449             logger->log(INFO, 
"(old_session) peer has higher router id, dispose this session.\n");
   451             if(!writeMessage(notify)) 
return -1;
   460     logger->log(ERROR, 
"BgpFsm::resloveCollison: ??? :( \n");
   464 bool BgpFsm::handleRouteEvent(
const RouteEvent &ev) {
   465     if (ev.
type == ADD4) 
return handleRoute4AddEvent(dynamic_cast <const Route4AddEvent&>(ev));
   466     if (ev.
type == WITHDRAW4) 
return handleRoute4WithdrawEvent(dynamic_cast <const Route4WithdrawEvent&>(ev));
   467     if (ev.
type == ADD6) 
return handleRoute6AddEvent(dynamic_cast <const Route6AddEvent&>(ev));
   468     if (ev.
type == WITHDRAW6) 
return handleRoute6WithdrawEvent(dynamic_cast <const Route6WithdrawEvent&>(ev));
   469     if (ev.
type == COLLISION) 
return handleRouteCollisionEvent(dynamic_cast <const RouteCollisionEvent&>(ev));
   475     if (state != OPEN_CONFIRM || peer_bgp_id != ev.peer_bgp_id) 
return false;
   477     LIBBGP_LOG(logger, INFO) {
   478         logger->log(INFO, 
"BgpFsm::handleRouteCollisionEvent: detecting collision with %s.\n", inet_ntoa(*(
const struct in_addr*) &(ev.peer_bgp_id)));
   480     return resloveCollision(ev.peer_bgp_id, 
false) == 1;
   484     if (state != ESTABLISHED) 
return false;
   485     if (!send_ipv6_routes) 
return false; 
   492     logger->log(DEBUG, 
"BgpFsm::handleRoute6AddEvent: got route-add event with %zu routes.\n", nroutes);
   496             std::vector<Prefix6> routes;
   499             alterNexthop6(nh_local, nh_global);
   503                     routes.push_back(route);
   505                     LIBBGP_LOG(logger, DEBUG) {
   507                         route.getPrefix(prefix);
   508                         char prefix_str[INET6_ADDRSTRLEN];
   509                         inet_ntop(AF_INET6, &prefix, prefix_str, INET6_ADDRSTRLEN);
   510                         logger->log(DEBUG, 
"BgpFsm::handleRoute6AddEvent: route %s/%d filtered by out_filter.\n", prefix_str, route.getLength());
   515             if (routes.size() > 0) {
   518                 prepareUpdateMessage(update);
   519                 update.setNlri6(routes, nh_global, nh_local);
   521                 if(!writeMessage(update)) 
return false;
   525             logger->log(DEBUG, 
"BgpFsm::handleRoute6AddEvent: ignoring new_routes in add event since remote is IBGP.\n");
   528         logger->log(DEBUG, 
"BgpFsm::handleRoute6AddEvent: new_routes or shared_attribs is NULL.\n");
   532         logger->log(DEBUG, 
"BgpFsm::handleRoute6AddEvent: replaced_entries is NULL.\n");
   538         if (entry.src_router_id == peer_bgp_id) 
continue;
   540         if (ibgp && entry.ibgp_peer_asn == peer_asn) {
   541             LIBBGP_LOG(logger, DEBUG) {
   543                 entry.route.getPrefix(prefix);
   544                 char prefix_str[INET6_ADDRSTRLEN];
   545                 inet_ntop(AF_INET6, &prefix, prefix_str, INET6_ADDRSTRLEN);
   546                 logger->log(DEBUG, 
"BgpFsm::handleRoute6AddEvent: route %s/%d in replaced_entries ignored as it is IBGP.\n", prefix_str, entry.route.getLength());
   552         if (config.out_filters6.apply(entry.route, entry.attribs) != 
ACCEPT) {
   553             LIBBGP_LOG(logger, DEBUG) {
   555                 entry.route.getPrefix(prefix);
   556                 char prefix_str[INET6_ADDRSTRLEN];
   557                 inet_ntop(AF_INET6, &prefix, prefix_str, INET6_ADDRSTRLEN);
   558                 logger->log(DEBUG, 
"BgpFsm::handleRoute6AddEvent: route %s/%d in replaced_entries filtered.\n", prefix_str, entry.route.getLength());
   566         const uint8_t *nh_global = entry.nexthop_global;
   567         const uint8_t *nh_local = entry.nexthop_linklocal;
   568         alterNexthop6(nh_local, nh_global);
   569         std::vector<Prefix6> routes;
   570         routes.push_back(entry.route);
   571         update.setNlri6(routes, nh_global, nh_local);
   572         prepareUpdateMessage(update);
   573         if(!writeMessage(update)) 
return false;
   580     if (state != ESTABLISHED) 
return false;
   581     if (!send_ipv6_routes) 
return false;
   582     if (ev.
routes == NULL) 
return false;
   584     logger->log(DEBUG, 
"BgpFsm::handleRoute6WithdrawEvent: got route-withdraw event with %zu routes.\n", ev.
routes->size());
   588     withdraw.setWithdrawn6(*(ev.
routes));
   590     if(!writeMessage(withdraw)) 
return false;
   595     if (state != ESTABLISHED) 
return false;
   596     if (!send_ipv4_routes) 
return false;
   603     logger->log(DEBUG, 
"BgpFsm::handleRoute4AddEvent: got route-add event with %zu routes.\n", nroutes);
   614                     LIBBGP_LOG(logger, DEBUG) {
   615                         uint32_t prefix = route.getPrefix();
   616                         char ip_str[INET_ADDRSTRLEN];
   617                         inet_ntop(AF_INET, &prefix, ip_str, INET_ADDRSTRLEN);
   618                         logger->log(DEBUG, 
"BgpFsm::handleRoute4AddEvent: route %s/%d filtered by out_filter.\n", ip_str, route.getLength());
   623             if (update.nlri.size() > 0) {
   624                 alterNexthop4(update);
   625                 prepareUpdateMessage(update);
   627                 if(!writeMessage(update)) 
return false;
   630             logger->log(DEBUG, 
"BgpFsm::handleRoute4AddEvent: ignoring new_routes in add event since remote is IBGP.\n");
   633         logger->log(DEBUG, 
"BgpFsm::handleRoute4AddEvent: new_routes or shared_attribs is NULL.\n");
   637         logger->log(DEBUG, 
"BgpFsm::handleRoute4AddEvent: replaced_entries is NULL.\n");
   643         if (entry.src_router_id == peer_bgp_id) 
continue;
   645         if (ibgp && entry.ibgp_peer_asn == peer_asn) {
   646             LIBBGP_LOG(logger, DEBUG) {
   647                 uint32_t prefix = entry.route.getPrefix();
   648                 char ip_str[INET_ADDRSTRLEN];
   649                 inet_ntop(AF_INET, &prefix, ip_str, INET_ADDRSTRLEN);
   650                 logger->log(DEBUG, 
"BgpFsm::handleRoute4AddEvent: route %s/%d ignored since remote is IBGP.\n", ip_str, entry.route.getLength());
   656         if (config.out_filters4.apply(entry.route, entry.attribs) != 
ACCEPT) {
   657             LIBBGP_LOG(logger, DEBUG) {
   658                 uint32_t prefix = entry.route.getPrefix();
   659                 char ip_str[INET_ADDRSTRLEN];
   660                 inet_ntop(AF_INET, &prefix, ip_str, INET_ADDRSTRLEN);
   661                 logger->log(DEBUG, 
"BgpFsm::handleRoute4AddEvent: route %s/%d filtered by out_filter.\n", ip_str, entry.route.getLength());
   670         alterNexthop4(update);
   671         prepareUpdateMessage(update);
   672         if(!writeMessage(update)) 
return false;
   679     if (state != ESTABLISHED) 
return false;
   680     if (!send_ipv4_routes) 
return false;
   681     if (ev.
routes == NULL) 
return false;
   683     logger->log(DEBUG, 
"BgpFsm::handleRoute4AddEvent: got route-withdraw event with %zu routes.\n", ev.
routes->size());
   688     if(!writeMessage(withdraw)) 
return false;
   694     if (ibgp && !config.ibgp_alter_nexthop) 
return;
   697     if (config.forced_default_nexthop4 || !update.
hasAttrib(NEXT_HOP)) {
   698         LIBBGP_LOG(logger, INFO) {
   699             char ip_str[INET_ADDRSTRLEN];
   700             inet_ntop(AF_INET, &(config.default_nexthop4), ip_str, INET_ADDRSTRLEN);
   701             if (config.forced_default_nexthop4) {
   702                 logger->log(INFO, 
"BgpFsm::alterNexthop4: forced_default_nexthop4 set, using %s as nexthop.\n", ip_str);
   704                 logger->log(INFO, 
"BgpFsm::alterNexthop4: no nethop attribute set, using %s as nexthop.\n", ip_str);
   711         if (!config.peering_lan4.includes(nh.
next_hop)) {
   712             LIBBGP_LOG(logger, INFO) {
   713                 char def_nexthop[INET_ADDRSTRLEN];
   714                 char cur_nexthop[INET_ADDRSTRLEN];
   715                 inet_ntop(AF_INET, &(config.default_nexthop4), def_nexthop, INET_ADDRSTRLEN);
   716                 inet_ntop(AF_INET, &(nh.
next_hop), cur_nexthop, INET_ADDRSTRLEN);
   717                 logger->log(INFO, 
"BgpFsm::alterNexthop4: nexthop %s not in peering lan, using %s.\n", cur_nexthop, def_nexthop);
   719             nh.
next_hop = config.default_nexthop4;
   724 void BgpFsm::alterNexthop6 (
const uint8_t* &nh_global, 
const uint8_t* &nh_local) {
   725     if (config.forced_default_nexthop6 && !config.peering_lan6.includes(nh_global) && !ibgp && !config.ibgp_alter_nexthop) {
   726         LIBBGP_LOG(logger, INFO) {
   727             char nh_old_str[INET6_ADDRSTRLEN];
   728             char nh_def_str[INET6_ADDRSTRLEN];
   729             inet_ntop(AF_INET6, &nh_global, nh_old_str, INET6_ADDRSTRLEN);
   730             inet_ntop(AF_INET6, &nh_def_str, nh_def_str, INET6_ADDRSTRLEN);
   732             if (config.forced_default_nexthop6) {
   733                 logger->log(INFO, 
"BgpFsm::alterNexthop6: forced_default_nexthop6 set, default (%s) will be used.\n", nh_def_str);
   735             else logger->log(INFO, 
"BgpFsm::alterNexthop6: nexthop %s is not in peering lan, default (%s) will be used.\n", nh_old_str, nh_def_str);
   738         nh_global = config.default_nexthop6_global;
   739         nh_local = config.default_nexthop6_linklocal;
   746     if (config.use_4b_asn && use_4b_asn) {                
   754     if (!ibgp) update.
prepend(config.asn);
   757 int BgpFsm::validateState(uint8_t type) {
   761                 logger->log(ERROR, 
"BgpFsm::validateState: got non-OPEN message in IDLE state.\n");
   767                 logger->log(ERROR, 
"BgpFsm::validateState: got non-OPEN message in OPEN_SENT state.\n");
   770                 if(!writeMessage(notify)) 
return -1;
   776             if (type != KEEPALIVE) {
   777                 logger->log(ERROR, 
"BgpFsm::validateState: got non-KEEPALIVE message in OPEN_CONFIRM state.\n");
   780                 if(!writeMessage(notify)) 
return -1;
   786             if (type != UPDATE && type != KEEPALIVE) {
   787                 logger->log(ERROR, 
"BgpFsm::validateState: got invalid message (type %d) in ESTABLISHED state.\n", type);
   790                 if(!writeMessage(notify)) 
return -1;
   796             logger->log(ERROR, 
"BgpFsm::validateState: got message in bad state. consider reset.\n");
   801 int BgpFsm::fsmEvalIdle(
const BgpMessage *msg) {
   804     int retval = openRecv(open_msg);
   805     if (retval != 1) 
return retval;
   807     uint16_t my_asn_2b = config.asn >= 0xffff ? 23456 : config.asn;
   808     BgpOpenMessage open_reply (logger, use_4b_asn, my_asn_2b, hold_timer, config.router_id);
   811         open_reply.
setAsn(config.asn);
   814     if (config.mp_bgp_ipv4) {
   818         open_reply.
addCapability(std::shared_ptr<BgpCapability>(cap));
   821     if (config.mp_bgp_ipv6) {
   825         open_reply.
addCapability(std::shared_ptr<BgpCapability>(cap));
   828     setState(OPEN_CONFIRM);
   829     if(!writeMessage(open_reply)) 
return -1;
   834 int BgpFsm::fsmEvalOpenSent(
const BgpMessage *msg) {
   837     int retval = openRecv(open_msg);
   838     if (retval != 1) 
return retval;
   841     setState(OPEN_CONFIRM);
   842     if(!writeMessage(keep)) 
return -1;
   847 int BgpFsm::fsmEvalOpenConfirm(__attribute__((unused)) 
const BgpMessage *msg) {
   849     setState(ESTABLISHED);
   850     if(!writeMessage(keep)) 
return -1;
   852     if (send_ipv4_routes) {
   853         rib4_t::const_iterator iter = rib4->get().begin();
   854         rib4_t::const_iterator last_iter = iter;
   855         const rib4_t::const_iterator end = rib4->get().end();
   858         while (iter != end) {
   859             uint64_t cur_group_id = iter->second.update_id;
   862             alterNexthop4(update);
   863             prepareUpdateMessage(update);
   866             size_t msg_len = 19 + 4;
   868             for (
const std::shared_ptr<BgpPathAttrib> &attrib : update.path_attribute) {
   869                 msg_len += attrib->length(); 
   872             for (; iter != end && cur_group_id == iter->second.update_id && msg_len < 4096; iter++) {
   875                 if (e.
status == RS_STANDBY) 
continue;
   878                     LIBBGP_LOG(logger, DEBUG) {
   880                         char ip_str[INET_ADDRSTRLEN];
   881                         inet_ntop(AF_INET, &prefix, ip_str, INET_ADDRSTRLEN);
   882                         logger->log(DEBUG, 
"BgpFsm::fsmEvalOpenConfirm: ignored IBGP route %s/%d.\n", ip_str, r.
getLength());
   888                 if (iter->second.src_router_id == peer_bgp_id) {
   889                     LIBBGP_LOG(logger, WARN) {
   891                         char ip_str[INET_ADDRSTRLEN];
   892                         inet_ntop(AF_INET, &prefix, ip_str, INET_ADDRSTRLEN);
   893                         logger->log(WARN, 
"BgpFsm::fsmEvalOpenConfirm: route %s/%d has src_bgp_id same as peer, ignore.\n", ip_str, r.
getLength());
   898                 if (config.out_filters4.apply(r, update.path_attribute) == 
ACCEPT) {
   900                     if (msg_len > 4096) {
   907                     LIBBGP_LOG(logger, DEBUG) {
   909                         char ip_str[INET_ADDRSTRLEN];
   910                         inet_ntop(AF_INET, &prefix, ip_str, INET_ADDRSTRLEN);
   911                         logger->log(DEBUG, 
"BgpFsm::fsmEvalOpenConfirm: route %s/%d filtered by out_filter.\n", ip_str, r.
getLength());
   917             if (update.nlri.size() > 0) {
   918                 if(!writeMessage(update)) 
return -1;
   923     if (send_ipv6_routes) {
   924         rib6_t::const_iterator iter = rib6->get().begin();
   925         rib6_t::const_iterator last_iter = iter;
   926         const rib6_t::const_iterator end = rib6->get().end();
   928         while (iter != end) {
   929             uint64_t cur_group_id = iter->second.update_id;
   930             const uint8_t *nh_global = iter->second.nexthop_global;
   931             const uint8_t *nh_linklocal = iter->second.nexthop_linklocal;
   935             prepareUpdateMessage(update);
   936             std::vector<Prefix6> filtered_nlri;
   940             size_t msg_len = 19 + 4 + 8 + 32;
   941             for (
const std::shared_ptr<BgpPathAttrib> &attrib : update.path_attribute) {
   942                 msg_len += attrib->length(); 
   945             for (; iter != end && cur_group_id == iter->second.update_id && msg_len < 4096; iter++) {
   948                 if (e.
status != RS_ACTIVE) 
continue;
   950                     LIBBGP_LOG(logger, DEBUG) {
   953                         char ip_str[INET6_ADDRSTRLEN];
   954                         inet_ntop(AF_INET6, &prefix, ip_str, INET6_ADDRSTRLEN);
   955                         logger->log(DEBUG, 
"BgpFsm::fsmEvalOpenConfirm: ignored IBGP route %s/%d.\n", ip_str, r.
getLength());
   960                 if (iter->second.src_router_id == peer_bgp_id) {
   961                     LIBBGP_LOG(logger, WARN) {
   964                         char ip_str[INET6_ADDRSTRLEN];
   965                         inet_ntop(AF_INET6, &prefix, ip_str, INET6_ADDRSTRLEN);
   966                         logger->log(WARN, 
"BgpFsm::fsmEvalOpenConfirm: route %s/%d has src_bgp_id same as peer, ignore.\n", ip_str, r.
getLength());
   972                 if (config.out_filters6.apply(r, update.path_attribute) == 
ACCEPT) {
   974                     if (msg_len > 4096) {
   979                     filtered_nlri.push_back(r);
   981                     LIBBGP_LOG(logger, DEBUG) {
   984                         char ip_str[INET6_ADDRSTRLEN];
   985                         inet_ntop(AF_INET6, &prefix, ip_str, INET6_ADDRSTRLEN);
   986                         logger->log(DEBUG, 
"BgpFsm::fsmEvalOpenConfirm: route %s/%d filtered by out_filter.\n", ip_str, r.
getLength());
   992             if (filtered_nlri.size() > 0) {
   993                 alterNexthop6(nh_global, nh_linklocal);
   994                 update.setNlri6(filtered_nlri, nh_global, nh_linklocal);
   995                 if(!writeMessage(update)) 
return -1;
  1004 int BgpFsm::fsmEvalEstablished(
const BgpMessage *msg) {
  1005     if (msg->type == KEEPALIVE) 
return 1;
  1009     bool ignore_routes = 
false;
  1012     if (update->
hasAttrib(AS_PATH) && update->nlri.size() > 0) {
  1016             int8_t local_count = 0;
  1018             for (uint32_t asn : seg.
value) {
  1019                 if (asn == config.asn) local_count++;
  1022             if (local_count > config.allow_local_as) {
  1023                 logger->log(WARN, 
"BgpFsm::fsmEvalEstablished: ignoring routes with %d local asn in as_path (max %d are allowed).\n", local_count, config.allow_local_as);
  1024                 ignore_routes = 
true;
  1028     } 
else ignore_routes = 
true; 
  1030     if (send_ipv4_routes) {
  1031         std::vector<Prefix4> unreach;
  1032         std::vector<BgpRib4Entry> changed_entries;
  1033         for (
const Prefix4 &r : update->withdrawn_routes) {
  1034             std::pair<bool, const BgpRib4Entry*> w_ret = rib4->withdraw(peer_bgp_id, r);
  1035             if (!rev_bus_exist) 
continue;
  1036             if (!w_ret.first) unreach.push_back(r);
  1037             else if (w_ret.second != NULL) {
  1038                 changed_entries.push_back(*(w_ret.second));
  1043         if (update->nlri.size() > 0) {
  1046             if (!ignore_routes && !validAddr4(nh.
next_hop)) {
  1047                 LIBBGP_LOG(logger, WARN) {
  1048                     char ip_str[INET_ADDRSTRLEN];
  1049                     inet_ntop(AF_INET, &(nh.
next_hop), ip_str, INET_ADDRSTRLEN);
  1050                     logger->log(WARN, 
"BgpFsm::fsmEvalEstablished: ignored %zu routes with invalid nexthop %s\n", update->nlri.size(), ip_str);
  1052                 ignore_routes = 
true;
  1055             if (!ignore_routes && !config.no_nexthop_check4 && !config.peering_lan4.includes(nh.
next_hop) && !ibgp) {
  1056                 LIBBGP_LOG(logger, WARN) {
  1057                     char ip_str_nh[INET_ADDRSTRLEN];
  1058                     char ip_str_lan[INET_ADDRSTRLEN];
  1059                     inet_ntop(AF_INET, &(nh.
next_hop), ip_str_nh, INET_ADDRSTRLEN);
  1060                     uint32_t peering_lan_pfx = config.peering_lan4.getPrefix();
  1061                     inet_ntop(AF_INET, &peering_lan_pfx, ip_str_lan, INET_ADDRSTRLEN);
  1062                     logger->log(WARN, 
"BgpFsm::fsmEvalEstablished: ignored %zu routes with nexthop outside peering LAN. (%s not in %s/%d)\n", 
  1063                         update->nlri.size(), ip_str_nh, ip_str_lan, config.peering_lan4.getLength());
  1065                 ignore_routes = 
true;
  1070         if (!ignore_routes) {
  1071             std::vector<Prefix4> routes = std::vector<Prefix4> ();
  1072             for (
const Prefix4 &route : update->nlri) {
  1073                 if(config.in_filters4.apply(route, update->path_attribute) == 
ACCEPT) {
  1074                     routes.push_back(route);
  1076                     LIBBGP_LOG(logger, DEBUG) {
  1078                         char ip_str[INET_ADDRSTRLEN];
  1079                         inet_ntop(AF_INET, &prefix, ip_str, INET_ADDRSTRLEN);
  1080                         logger->log(DEBUG, 
"BgpFsm::fsmEvalEstablished: route %s/%d filtered by in_filters4.\n", ip_str, route.
getLength());
  1085             std::pair<std::vector<BgpRib4Entry>, std::vector<Prefix4>> rslt;
  1086             if (routes.size() > 0) {
  1087                 rslt = rib4->insert(peer_bgp_id, routes, update->path_attribute, config.weight, ibgp ? peer_asn : 0);
  1089                     changed_entries.push_back(entry);
  1091                 logger->log(DEBUG, 
"BgpFsm::fsmEvalEstablished: rib4.insert(): %zu altered and %zu added in %zu routes.\n", rslt.first.size(), rslt.second.size(), routes.size());
  1094             if (rev_bus_exist && (changed_entries.size() > 0 || rslt.second.size() > 0)) {
  1095                 logger->log(DEBUG, 
"BgpFsm::fsmEvalEstablished: publishing new v4 routes on event bus...\n");
  1097                 aev.
replaced_entries = changed_entries.size() > 0 ? &changed_entries : NULL;
  1099                 aev.
new_routes = rslt.second.size() > 0 ? &(rslt.second) : NULL;
  1101                 config.rev_bus->publish(
this, aev);
  1104             if (rev_bus_exist && unreach.size() > 0) {
  1105                 logger->log(DEBUG, 
"BgpFsm::fsmEvalEstablished: publishing dropped v4 routes on event bus...\n");
  1108                 config.rev_bus->publish(
this, wev);
  1113     if (send_ipv6_routes) {
  1114         std::vector<Prefix6> unreach;
  1115         std::vector<BgpRib6Entry> changed_entries;
  1116         if (update->
hasAttrib(MP_UNREACH_NLRI)) {
  1119             if (mp_unreach.
afi == IPV6 && mp_unreach.
safi == UNICAST) {
  1122                 for (
const Prefix6 &r : u.withdrawn_routes) {
  1123                     std::pair<bool, const BgpRib6Entry*> w_ret = rib6->withdraw(peer_bgp_id, r);
  1124                     if (!rev_bus_exist) 
continue;
  1125                     if (!w_ret.first) unreach.push_back(r);
  1126                     else if (w_ret.second != NULL) {
  1127                         changed_entries.push_back(*(w_ret.second));
  1133         if (!ignore_routes && update->
hasAttrib(MP_REACH_NLRI)) {
  1136             if (mp_reach.
afi == IPV6 && mp_reach.
safi == UNICAST) {
  1139                 if (!validAddr6(reach.nexthop_global) || (!
v6addr_is_zero(reach.nexthop_linklocal) && !validAddr6(reach.nexthop_linklocal))) {
  1140                     logger->log(WARN, 
"BgpFsm::fsmEvalEstablished: ignored %zu routes with invalid nexthop:\n", reach.nlri.size());
  1141                     logger->log(WARN, reach);
  1146                 std::vector<Prefix6> filtered_routes;
  1147                 for (
const Prefix6 &route : reach.nlri) {
  1148                     if (config.in_filters6.apply(route, update->path_attribute) == 
ACCEPT) filtered_routes.push_back(route);
  1151                 if (filtered_routes.size() <= 0) 
return 1;
  1156                 std::vector<std::shared_ptr<BgpPathAttrib>> attrs;
  1158                 for (
const std::shared_ptr<BgpPathAttrib> &attr : update->path_attribute) {
  1159                     if (attr->type_code == MP_REACH_NLRI || attr->type_code == MP_UNREACH_NLRI || attr->type_code == NEXT_HOP) 
continue;
  1160                     attrs.push_back(attr);
  1163                 std::pair<std::vector<BgpRib6Entry>, std::vector<Prefix6>> rslt = rib6->insert(peer_bgp_id, filtered_routes, reach.nexthop_global, reach.nexthop_linklocal, attrs, config.weight, ibgp ? peer_asn : 0);
  1164                 logger->log(DEBUG, 
"BgpFsm::fsmEvalEstablished: rib6.insert(): %zu altered and %zu added in %zu routes.\n", rslt.first.size(), rslt.second.size(), filtered_routes.size());
  1167                     changed_entries.push_back(e);
  1170                 if (rev_bus_exist && (changed_entries.size() > 0 || rslt.second.size() > 0)) {
  1174                     aev.
new_routes = rslt.second.size() > 0 ? &(rslt.second) : NULL;
  1175                     aev.
replaced_entries = changed_entries.size() > 0 ? &changed_entries : NULL;
  1178                     config.rev_bus->publish(
this, aev);
  1181                 if (rev_bus_exist && unreach.size() > 0) {
  1182                     logger->log(DEBUG, 
"BgpFsm::fsmEvalEstablished: publishing dropped v6 routes on event bus...\n");
  1185                     config.rev_bus->publish(
this, wev);
  1194 void BgpFsm::dropAllRoutes() {
  1195     if (peer_bgp_id != 0) {
  1196         std::pair<std::vector<Prefix4>, std::vector<BgpRib4Entry>> rslt4 = rib4->discard(peer_bgp_id);
  1197         if (rev_bus_exist && rslt4.first.size() > 0) {
  1199             wev.
routes = &(rslt4.first);
  1200             config.rev_bus->publish(
this, wev);
  1202         if (rev_bus_exist && rslt4.second.size() > 0) {
  1205             config.rev_bus->publish(
this, aev);
  1207         std::pair<std::vector<Prefix6>, std::vector<BgpRib6Entry>> rslt6 = rib6->discard(peer_bgp_id);
  1208         if (rev_bus_exist && rslt6.first.size() > 0) {
  1210             wev.
routes = &(rslt6.first);
  1211             config.rev_bus->publish(
this, wev);
  1213         if (rev_bus_exist && rslt6.second.size() > 0) {
  1216             config.rev_bus->publish(
this, aev);
  1221 void BgpFsm::setState(
BgpState new_state) {
  1222     if (state == new_state) 
return;
  1224     if (config.out_handler) config.out_handler->notifyStateChange(state, new_state);
  1226     logger->log(INFO, 
"BgpFsm::setState: changing state: %s -> %s\n", bgp_fsm_state_str[state], bgp_fsm_state_str[new_state]); 
  1228     if (state == ESTABLISHED) {
  1229         logger->log(INFO, 
"BgpFsm::setState: dropping all routes received from peer...\n");
  1238 bool BgpFsm::validAddr4(uint32_t addr)
 const {
  1239     if (addr == config.default_nexthop4 || addr == config.router_id) {
  1243     uint32_t addr_host = ntohl(addr);
  1244     uint32_t first = addr_host >> 24;
  1246     if (first == 0 || first == 127 || (first >= 224 && first <= 239) || first > 240) {
  1253 bool BgpFsm::validAddr6(
const uint8_t addr[16])
 const {
  1254     static Prefix6 bad_range(
"0000::", 8);
  1259 bool BgpFsm::writeMessage(
const BgpMessage &msg) {
  1260     BgpPacket pkt(logger, use_4b_asn, &msg);
  1261     LIBBGP_LOG(logger, DEBUG) {
  1262         logger->log(DEBUG, 
"BgpFsm::writeMessage: write (Current state: %s):\n", bgp_fsm_state_str[state]);
  1263         logger->log(DEBUG, pkt);
  1266     std::lock_guard<std::recursive_mutex> lock(out_buffer_mutex);
  1268     ssize_t pkt_len = pkt.
write(out_buffer, BGP_FSM_BUFFER_SIZE);
  1269     last_sent = clock->getTime();
  1272         logger->log(ERROR, 
"BgpFsm::writeMessage: failed to write message, abort.\n");
  1277     if (config.out_handler && !config.out_handler->handleOut(out_buffer, pkt_len)) {
  1278         logger->log(ERROR, 
"BgpFsm::writeMessage: out_handler failed, abort.\n");
 std::vector< std::shared_ptr< BgpPathAttrib > > * shared_attribs
Path attribues of the route. 
 
int run(const uint8_t *buffer, const size_t buffer_size)
Run the FSM on buffer. 
 
uint8_t errcode
Notification message error code. 
 
IPv6 Route/Prefix related utilities. 
 
uint32_t getPrefix() const
Get prefix. 
 
const std::vector< BgpRib4Entry > * replaced_entries
Pointer to the route replacement entries vector. 
 
bool setAsn(uint32_t my_asn)
Set ASN. 
 
bool setNextHop(uint32_t nexthop)
Set/Create nexthop attribtue. 
 
bool restoreAsPath()
Restore the AS_PATH attribute to four octets ASN flavor. 
 
The BgpRib4 (IPv4 BGP Routing Information Base) class. 
 
BgpRib4 & getRib4() const
Get the IPv4 Routing Information Base. 
 
const char * bgp_error_code_str[7]
Error strings for BGP error codes. 
 
const std::vector< Prefix4 > * new_routes
Newly added routes. 
 
The BgpOpenMessage class. 
 
const std::vector< std::shared_ptr< BgpPathAttrib > > * shared_attribs
Shared attributes for the new routes. 
 
std::vector< uint32_t > value
The segment value. 
 
RouteEventType type
Type of this event. 
 
MP-BGP ReachNlri IPv6 NLRI class. 
 
The BGP Finite State Machine. 
 
int stop()
Stop the FSM. (Any -> Idle) 
 
Prefix4 route
The prefix of this entry. 
 
bool setWithdrawn4(const std::vector< Prefix4 > &routes)
Set withdrawn routes. 
 
BgpPathAttrib & getAttrib(uint8_t type)
Get mutable reference to attribute by typecode. 
 
uint32_t getBgpId() const
Get local BGP ID. 
 
The BgpCapabilityMpBgp class. 
 
uint32_t getPeerAsn() const
Get peer ASN. 
 
void resetHard()
Perform a hard reset. 
 
uint8_t getLength() const
Get netmask. 
 
The BgpNotificationMessage object. 
 
Probe for collision detection. 
 
uint16_t afi
Address Family Identifier. 
 
const BgpMessage * getMessage() const
Get pointer to the contained message. 
 
BgpState
BGP Finite State Machine status. 
 
uint32_t getPeerBgpId() const
Get peer BGP ID. 
 
std::vector< BgpAsPathSegment > as_paths
The AS Path segments. 
 
const std::vector< std::shared_ptr< BgpCapability > > & getCapabilities() const
Get capabilities list. 
 
uint8_t subcode
Notification message error subcode. 
 
bool downgradeAggregator()
Downgrade aggregator to two octets. 
 
uint8_t getLength() const
Get netmask. 
 
bool includes(const uint8_t address[16]) const
Test if an address is inside this prefix. 
 
BgpRouteSource src
Source of this entry. 
 
bool restoreAggregator()
Restore aggregator attribute from as4_aggregator. 
 
bool prepend(uint32_t asn)
Prepend ASN to AS_PATH and AS4_PATH (if in 2b-mode ans AS4_PATH exists) 
 
std::vector< Prefix6 > * routes
Routes to withdraw. 
 
const char * bgp_fsm_error_str[4]
Error strings for BGP FSM error subcodes. 
 
uint8_t nexthop_global[16]
Global IPv6 nexthop. 
 
uint32_t ibgp_peer_asn
ASN of the IBGP peer. (Valid iff src == SRC_IBGP) 
 
The BgpMessage base class. 
 
const char * bgp_cease_error_str[9]
Error strings for BGP cease error subcodes. 
 
IPv4 Route/Prefix related utilities. 
 
bool v6addr_is_zero(const uint8_t prefix[16])
Test if a IPv6 addresss is all zero. 
 
Buffer operation helpers. 
 
The BgpRib6 (IPv6 BGP Routing Information Base) class. 
 
uint8_t safi
Subsequent Address Family Identifier. 
 
The BgpKeepaliveMessage class. 
 
const char * bgp_open_error_subcode_str[8]
Error strings for BGP open message error subcodes. 
 
A Clock implementation to use system time as time. 
 
MP-BGP Reach/Unreach NLRI base class. 
 
uint16_t afi
Address Family Identifier. 
 
int start()
send OPEN message to peer. (IDLE -> OpenSent) 
 
bool hasCapability(uint8_t code) const
Check if open message has a capability. 
 
bool dropNonTransitive()
Drop all non-transitive attributes from the update message. 
 
uint32_t getAsn() const
Get local ASN. 
 
BgpState getState() const
Get current FSM state. 
 
An AS_PATH or AS4_PATH segment. 
 
const char * bgp_update_error_str[12]
Error strings for BGP update message error subcodes. 
 
void getPrefix(uint8_t prefix[16]) const
Get prefix. 
 
bool addNlri4(uint32_t prefix, uint8_t length)
Add NLRI route. 
 
uint16_t getHoldTimer() const
Get the negotiated hold timer. 
 
uint8_t nexthop_linklocal[16]
Link-local IPv6 nexthop. 
 
Prefix6 route
The prefix of this entry. 
 
bool hasAttrib(uint8_t type) const
Test if update message has an attribute. 
 
std::vector< Prefix6 > * new_routes
Routes to add. 
 
BgpRouteStatus status
Status of this entry. 
 
uint32_t getAsn() const
Get ASN. 
 
std::vector< Prefix4 > * routes
Routes to withdraw. 
 
uint32_t next_hop
The nexthop in network byte order. 
 
const char * bgp_header_error_subcode_str[4]
Error strings for BGP header error subcodes. 
 
uint8_t safi
Subsequent Address Family Identifier. 
 
BgpRib6 & getRib6() const
Get the IPv6 Routing Information Base. 
 
bool setAttribs(const std::vector< std::shared_ptr< BgpPathAttrib >> &attrs)
Replace the attributes list with another attribute list. 
 
uint32_t ibgp_peer_asn
ASN of the IBGP peer if the originating session is a IBGP session. 
 
uint32_t ibgp_peer_asn
ASN of the IBGP peer if the originating session is a IBGP session. 
 
ssize_t write(uint8_t *to, size_t buf_sz) const
Serialize a BGP message. 
 
bool addCapability(std::shared_ptr< BgpCapability > capability)
Add a capability. 
 
bool downgradeAsPath()
Downgrade the AS_PATH to two octets flavor. 
 
int resetSoft()
Perform a soft reset. 
 
int tick()
Tick the clock (Check for time-based events) 
 
The BgpUpdateMessage class. 
 
const std::vector< BgpRib6Entry > * replaced_entries
Pointer to the route replacement entries vector. 
 
MP-BGP UnreachNlri IPv6 class.