void telemetry_peer_close(telemetry_peer *peer, int type) { telemetry_dump_se_ll *tdsell; telemetry_misc_structs *tms; if (!peer) return; tms = bgp_select_misc_db(peer->type); if (!tms) return; if (tms->dump_file || tms->dump_amqp_routing_key || tms->dump_kafka_topic) { tdsell = (telemetry_dump_se_ll *) peer->bmp_se; if (tdsell && tdsell->start) telemetry_dump_se_ll_destroy(tdsell); free(peer->bmp_se); peer->bmp_se = NULL; } if (config.telemetry_port_udp) { telemetry_peer_udp_cache tpuc; memcpy(&tpuc.addr, &peer->addr, sizeof(struct host_addr)); pm_tdelete(&tpuc, &telemetry_peers_udp_cache, telemetry_tpuc_addr_cmp); peer->fd = ERR; /* dirty trick to prevent close() a valid fd in bgp_peer_close() */ } bgp_peer_close(peer, type); }
u_int32_t bgp_route_info_modulo_pathid(struct bgp_peer *peer, path_id_t *path_id) { struct bgp_misc_structs *bms = bgp_select_misc_db(peer->type); path_id_t local_path_id = 1; if (path_id && *path_id) local_path_id = *path_id; return (((peer->fd * bms->table_per_peer_buckets) + ((local_path_id - 1) % bms->table_per_peer_buckets)) % (bms->table_peer_buckets * bms->table_per_peer_buckets)); }
void bmp_process_msg_route_monitor(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer, *bmpp_bgp_peer; struct bmp_data bdata; struct bmp_peer_hdr *bph; char tstamp_str[SRVBUFLEN], peer_ip[INET6_ADDRSTRLEN]; int bgp_update_len; void *ret; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; if (!(bph = (struct bmp_peer_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_hdr)))) { Log(LOG_INFO, "INFO ( %s/core/BMP ): [%s] [route] packet discarded: failed bmp_get_and_check_length() BMP peer hdr\n", config.name, peer->addr_str); return; } bmp_peer_hdr_get_family(bph, &bdata.family); bmp_peer_hdr_get_peer_ip(bph, &bdata.peer_ip, bdata.family); bmp_peer_hdr_get_bgp_id(bph, &bdata.bgp_id); bmp_peer_hdr_get_tstamp(bph, &bdata.tstamp); bmp_peer_hdr_get_peer_asn(bph, &bdata.peer_asn); bmp_peer_hdr_get_peer_type(bph, &bdata.peer_type); if (bdata.family) { /* If no timestamp in BMP then let's generate one */ if (!bdata.tstamp.tv_sec) gettimeofday(&bdata.tstamp, NULL); compose_timestamp(tstamp_str, SRVBUFLEN, &bdata.tstamp, TRUE, config.timestamps_since_epoch); addr_to_str(peer_ip, &bdata.peer_ip); ret = pm_tfind(&bdata.peer_ip, &bmpp->bgp_peers, bmp_bmpp_bgp_peer_host_addr_cmp); if (ret) { char peer_str[] = "peer_ip", *saved_peer_str = bms->peer_str; bmpp_bgp_peer = (*(struct bgp_peer **) ret); bms->peer_str = peer_str; bgp_update_len = bgp_parse_update_msg(bmpp_bgp_peer, (*bmp_packet)); bms->peer_str = saved_peer_str; bmp_get_and_check_length(bmp_packet, len, bgp_update_len); } } }
void bmp_process_msg_stats(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer; struct bmp_data bdata; struct bmp_peer_hdr *bph; struct bmp_stats_hdr *bsh; struct bmp_stats_cnt_hdr *bsch; u_int64_t cnt_data64; u_int32_t index, count = 0, cnt_data32; u_int16_t cnt_type, cnt_len; u_int8_t got_data; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; memset(&bdata, 0, sizeof(bdata)); if (!(bph = (struct bmp_peer_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [stats] packet discarded: failed bmp_get_and_check_length() BMP peer hdr\n", config.name, bms->log_str, peer->addr_str); return; } if (!(bsh = (struct bmp_stats_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_stats_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [stats] packet discarded: failed bmp_get_and_check_length() BMP stats hdr\n", config.name, bms->log_str, peer->addr_str); return; } bmp_peer_hdr_get_v_flag(bph, &bdata.family); bmp_peer_hdr_get_peer_ip(bph, &bdata.peer_ip, bdata.family); bmp_peer_hdr_get_bgp_id(bph, &bdata.bgp_id); bmp_peer_hdr_get_l_flag(bph, &bdata.is_post); bmp_peer_hdr_get_tstamp(bph, &bdata.tstamp); bmp_peer_hdr_get_peer_asn(bph, &bdata.peer_asn); bmp_peer_hdr_get_peer_type(bph, &bdata.peer_type); bmp_stats_hdr_get_count(bsh, &count); if (bdata.family) { /* If no timestamp in BMP then let's generate one */ if (!bdata.tstamp.tv_sec) gettimeofday(&bdata.tstamp, NULL); for (index = 0; index < count; index++) { if (!(bsch = (struct bmp_stats_cnt_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_stats_cnt_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [stats] packet discarded: failed bmp_get_and_check_length() BMP stats cnt hdr #%u\n", config.name, bms->log_str, peer->addr_str, index); return; } bmp_stats_cnt_hdr_get_type(bsch, &cnt_type); bmp_stats_cnt_hdr_get_len(bsch, &cnt_len); cnt_data32 = 0; cnt_data64 = 0, got_data = TRUE; switch (cnt_type) { case BMP_STATS_TYPE0: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE1: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE2: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE3: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE4: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE5: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE6: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); break; case BMP_STATS_TYPE7: if (cnt_len == 8) bmp_stats_cnt_get_data64(bmp_packet, len, &cnt_data64); break; case BMP_STATS_TYPE8: if (cnt_len == 8) bmp_stats_cnt_get_data64(bmp_packet, len, &cnt_data64); break; default: if (cnt_len == 4) bmp_stats_cnt_get_data32(bmp_packet, len, &cnt_data32); else if (cnt_len == 8) bmp_stats_cnt_get_data64(bmp_packet, len, &cnt_data64); else { bmp_get_and_check_length(bmp_packet, len, cnt_len); got_data = FALSE; } break; } if (cnt_data32 && !cnt_data64) cnt_data64 = cnt_data32; { struct bmp_log_stats blstats; blstats.cnt_type = cnt_type; blstats.cnt_data = cnt_data64; blstats.got_data = got_data; if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, &blstats, bms->log_seq, event_type, config.nfacctd_bmp_msglog_output, BMP_LOG_TYPE_STATS); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, &blstats, BMP_LOG_TYPE_STATS); if (bms->msglog_backend_methods || bms->dump_backend_methods) bgp_peer_log_seq_increment(&bms->log_seq); } } } }
void bmp_process_msg_route_monitor(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer, *bmpp_bgp_peer; struct bmp_data bdata; struct bmp_peer_hdr *bph; char tstamp_str[SRVBUFLEN], peer_ip[INET6_ADDRSTRLEN]; int bgp_update_len; void *ret; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; if (!(bph = (struct bmp_peer_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [route] packet discarded: failed bmp_get_and_check_length() BMP peer hdr\n", config.name, bms->log_str, peer->addr_str); return; } bmp_peer_hdr_get_v_flag(bph, &bdata.family); bmp_peer_hdr_get_peer_ip(bph, &bdata.peer_ip, bdata.family); bmp_peer_hdr_get_l_flag(bph, &bdata.is_post); bmp_peer_hdr_get_a_flag(bph, &bdata.is_2b_asn); bmp_peer_hdr_get_bgp_id(bph, &bdata.bgp_id); bmp_peer_hdr_get_tstamp(bph, &bdata.tstamp); bmp_peer_hdr_get_peer_asn(bph, &bdata.peer_asn); bmp_peer_hdr_get_peer_type(bph, &bdata.peer_type); if (bdata.family) { /* If no timestamp in BMP then let's generate one */ if (!bdata.tstamp.tv_sec) gettimeofday(&bdata.tstamp, NULL); compose_timestamp(tstamp_str, SRVBUFLEN, &bdata.tstamp, TRUE, config.timestamps_since_epoch); addr_to_str(peer_ip, &bdata.peer_ip); ret = pm_tfind(&bdata.peer_ip, &bmpp->bgp_peers, bgp_peer_host_addr_cmp); if (ret) { char peer_str[] = "peer_ip", *saved_peer_str = bms->peer_str; struct bgp_msg_extra_data_bmp bmed_bmp; struct bgp_msg_data bmd; bmpp_bgp_peer = (*(struct bgp_peer **) ret); memset(&bmd, 0, sizeof(bmd)); memset(&bmed_bmp, 0, sizeof(bmed_bmp)); bms->peer_str = peer_str; bmed_bmp.bdata = &bdata; bmd.peer = bmpp_bgp_peer; bmd.extra.id = BGP_MSG_EXTRA_DATA_BMP; bmd.extra.len = sizeof(bmed_bmp); bmd.extra.data = &bmed_bmp; // XXX: set extra data funcs bgp_update_len = bgp_parse_update_msg(&bmd, (*bmp_packet)); bms->peer_str = saved_peer_str; bmp_get_and_check_length(bmp_packet, len, bgp_update_len); } /* missing BMP peer up message, ie. case of replay/replication of BMP messages */ else { if (!log_notification_isset(&bmpp->missing_peer_up, bdata.tstamp.tv_sec)) { log_notification_set(&bmpp->missing_peer_up, bdata.tstamp.tv_sec, BMP_MISSING_PEER_UP_LOG_TOUT); Log(LOG_INFO, "INFO ( %s/%s ): [%s] [route] packet discarded: missing peer up BMP message for peer %s\n", config.name, bms->log_str, peer->addr_str, peer_ip); } } } }
u_int32_t bmp_process_packet(char *bmp_packet, u_int32_t len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer; char *bmp_packet_ptr = bmp_packet; u_int32_t pkt_remaining_len, msg_len, msg_start_len; struct bmp_common_hdr *bch = NULL; if (!bmpp) return FALSE; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return FALSE; if (len < sizeof(struct bmp_common_hdr)) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] packet discarded: failed bmp_get_and_check_length() BMP common hdr\n", config.name, bms->log_str, peer->addr_str); return FALSE; } for (msg_start_len = pkt_remaining_len = len; pkt_remaining_len; msg_start_len = pkt_remaining_len) { if (!(bch = (struct bmp_common_hdr *) bmp_get_and_check_length(&bmp_packet_ptr, &pkt_remaining_len, sizeof(struct bmp_common_hdr)))) return msg_start_len; if (bch->version != BMP_V3) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] packet discarded: BMP version != %u\n", config.name, bms->log_str, peer->addr_str, BMP_V3); return FALSE; } bmp_common_hdr_get_len(bch, &msg_len); if (pkt_remaining_len < msg_len) return msg_start_len; if (bch->type <= BMP_MSG_TYPE_MAX) { Log(LOG_DEBUG, "DEBUG ( %s/%s ): [%s] [common] type: %s (%u)\n", config.name, bms->log_str, peer->addr_str, bmp_msg_types[bch->type], bch->type); } switch (bch->type) { case BMP_MSG_ROUTE_MONITOR: bmp_process_msg_route_monitor(&bmp_packet_ptr, &pkt_remaining_len, bmpp); break; case BMP_MSG_STATS: bmp_process_msg_stats(&bmp_packet_ptr, &pkt_remaining_len, bmpp); break; case BMP_MSG_PEER_DOWN: bmp_process_msg_peer_down(&bmp_packet_ptr, &pkt_remaining_len, bmpp); break; case BMP_MSG_PEER_UP: bmp_process_msg_peer_up(&bmp_packet_ptr, &pkt_remaining_len, bmpp); break; case BMP_MSG_INIT: bmp_process_msg_init(&bmp_packet_ptr, &pkt_remaining_len, msg_len, bmpp); break; case BMP_MSG_TERM: bmp_process_msg_term(&bmp_packet_ptr, &pkt_remaining_len, msg_len, bmpp); break; case BMP_MSG_ROUTE_MIRROR: bmp_process_msg_route_mirror(&bmp_packet_ptr, &pkt_remaining_len, bmpp); break; default: Log(LOG_INFO, "INFO ( %s/%s ): [%s] packet discarded: unknown message type (%u)\n", config.name, bms->log_str, peer->addr_str, bch->type); break; } if ((msg_start_len - pkt_remaining_len) < msg_len) { /* let's jump forward: we may have been unable to parse some (sub-)element */ bmp_jump_offset(&bmp_packet_ptr, &pkt_remaining_len, (msg_len - (msg_start_len - pkt_remaining_len))); } } return FALSE; }
void bmp_process_msg_peer_down(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer, *bmpp_bgp_peer; struct bmp_data bdata; struct bmp_peer_hdr *bph; struct bmp_peer_down_hdr *bpdh; void *ret; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; memset(&bdata, 0, sizeof(bdata)); if (!(bph = (struct bmp_peer_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer down] packet discarded: failed bmp_get_and_check_length() BMP peer hdr\n", config.name, bms->log_str, peer->addr_str); return; } if (!(bpdh = (struct bmp_peer_down_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_down_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer down] packet discarded: failed bmp_get_and_check_length() BMP peer down hdr\n", config.name, bms->log_str, peer->addr_str); return; } bmp_peer_hdr_get_v_flag(bph, &bdata.family); bmp_peer_hdr_get_peer_ip(bph, &bdata.peer_ip, bdata.family); bmp_peer_hdr_get_l_flag(bph, &bdata.is_post); bmp_peer_hdr_get_bgp_id(bph, &bdata.bgp_id); bmp_peer_hdr_get_tstamp(bph, &bdata.tstamp); bmp_peer_hdr_get_peer_asn(bph, &bdata.peer_asn); bmp_peer_hdr_get_peer_type(bph, &bdata.peer_type); if (bdata.family) { /* If no timestamp in BMP then let's generate one */ if (!bdata.tstamp.tv_sec) gettimeofday(&bdata.tstamp, NULL); { struct bmp_log_peer_down blpd; bmp_peer_down_hdr_get_reason(bpdh, &blpd.reason); if (blpd.reason == BMP_PEER_DOWN_LOC_CODE) bmp_peer_down_hdr_get_loc_code(bmp_packet, len, &blpd.loc_code); if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, &blpd, bms->log_seq, event_type, config.nfacctd_bmp_msglog_output, BMP_LOG_TYPE_PEER_DOWN); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, &blpd, BMP_LOG_TYPE_PEER_DOWN); if (bms->msglog_backend_methods || bms->dump_backend_methods) bgp_peer_log_seq_increment(&bms->log_seq); } ret = pm_tfind(&bdata.peer_ip, &bmpp->bgp_peers, bgp_peer_host_addr_cmp); if (ret) { char peer_str[] = "peer_ip", *saved_peer_str = bms->peer_str; bmpp_bgp_peer = (*(struct bgp_peer **) ret); bms->peer_str = peer_str; bgp_peer_info_delete(bmpp_bgp_peer); bms->peer_str = saved_peer_str; pm_tdelete(&bdata.peer_ip, &bmpp->bgp_peers, bgp_peer_host_addr_cmp); } /* missing BMP peer up message, ie. case of replay/replication of BMP messages */ else { char peer_ip[INET6_ADDRSTRLEN]; addr_to_str(peer_ip, &bdata.peer_ip); if (!log_notification_isset(&bmpp->missing_peer_up, bdata.tstamp.tv_sec)) { log_notification_set(&bmpp->missing_peer_up, bdata.tstamp.tv_sec, BMP_MISSING_PEER_UP_LOG_TOUT); Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer down] packet discarded: missing peer up BMP message for peer %s\n", config.name, bms->log_str, peer->addr_str, peer_ip); } } } }
void bmp_process_msg_peer_up(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer; struct bmp_data bdata; struct bmp_peer_hdr *bph; struct bmp_peer_up_hdr *bpuh; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; memset(&bdata, 0, sizeof(bdata)); if (!(bph = (struct bmp_peer_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer up] packet discarded: failed bmp_get_and_check_length() BMP peer hdr\n", config.name, bms->log_str, peer->addr_str); return; } if (!(bpuh = (struct bmp_peer_up_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_up_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [peer up] packet discarded: failed bmp_get_and_check_length() BMP peer up hdr\n", config.name, bms->log_str, peer->addr_str); return; } bmp_peer_hdr_get_v_flag(bph, &bdata.family); bmp_peer_hdr_get_peer_ip(bph, &bdata.peer_ip, bdata.family); bmp_peer_hdr_get_l_flag(bph, &bdata.is_post); bmp_peer_hdr_get_a_flag(bph, &bdata.is_2b_asn); bmp_peer_hdr_get_bgp_id(bph, &bdata.bgp_id); bmp_peer_hdr_get_tstamp(bph, &bdata.tstamp); bmp_peer_hdr_get_peer_asn(bph, &bdata.peer_asn); bmp_peer_hdr_get_peer_type(bph, &bdata.peer_type); if (bdata.family) { /* If no timestamp in BMP then let's generate one */ if (!bdata.tstamp.tv_sec) gettimeofday(&bdata.tstamp, NULL); { struct bmp_log_peer_up blpu; struct bgp_peer bgp_peer_loc, bgp_peer_rem, *bmpp_bgp_peer; struct bgp_msg_extra_data_bmp bmed_bmp; struct bgp_msg_data bmd; int bgp_open_len; void *ret, *alloc_key; memset(&bgp_peer_loc, 0, sizeof(bgp_peer_loc)); memset(&bgp_peer_rem, 0, sizeof(bgp_peer_rem)); memset(&bmd, 0, sizeof(bmd)); memset(&bmed_bmp, 0, sizeof(bmed_bmp)); bmp_peer_up_hdr_get_loc_port(bpuh, &blpu.loc_port); bmp_peer_up_hdr_get_rem_port(bpuh, &blpu.rem_port); bmp_peer_up_hdr_get_local_ip(bpuh, &blpu.local_ip, bdata.family); bmed_bmp.bdata = &bdata; bmd.peer = &bgp_peer_loc; bmd.extra.id = BGP_MSG_EXTRA_DATA_BMP; bmd.extra.len = sizeof(bmed_bmp); bmd.extra.data = &bmed_bmp; // XXX: set extra data funcs bgp_open_len = bgp_parse_open_msg(&bmd, (*bmp_packet), FALSE, FALSE); bmp_get_and_check_length(bmp_packet, len, bgp_open_len); memcpy(&bgp_peer_loc.addr, &blpu.local_ip, sizeof(struct host_addr)); bmd.peer = &bgp_peer_rem; bgp_open_len = bgp_parse_open_msg(&bmd, (*bmp_packet), FALSE, FALSE); bmp_get_and_check_length(bmp_packet, len, bgp_open_len); memcpy(&bgp_peer_rem.addr, &bdata.peer_ip, sizeof(struct host_addr)); bmpp_bgp_peer = bmp_sync_loc_rem_peers(&bgp_peer_loc, &bgp_peer_rem); bmpp_bgp_peer->log = bmpp->self.log; bmpp_bgp_peer->bmp_se = bmpp; /* using bmp_se field to back-point a BGP peer to its parent BMP peer */ ret = pm_tsearch(bmpp_bgp_peer, &bmpp->bgp_peers, bgp_peer_cmp, sizeof(struct bgp_peer)); if (!ret) Log(LOG_WARNING, "WARN ( %s/%s ): [%s] [peer up] tsearch() unable to insert.\n", config.name, bms->log_str, peer->addr_str); if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, &blpu, bms->log_seq, event_type, config.nfacctd_bmp_msglog_output, BMP_LOG_TYPE_PEER_UP); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, &blpu, BMP_LOG_TYPE_PEER_UP); if (bms->msglog_backend_methods || bms->dump_backend_methods) bgp_peer_log_seq_increment(&bms->log_seq); } } }
void bmp_process_msg_term(char **bmp_packet, u_int32_t *len, u_int32_t bmp_hdr_len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer; struct bmp_data bdata; struct bmp_term_hdr *bth; u_int16_t bmp_term_len, reason_type = 0; char *bmp_term_info; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; memset(&bdata, 0, sizeof(bdata)); gettimeofday(&bdata.tstamp, NULL); bmp_hdr_len -= sizeof(struct bmp_common_hdr); if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, NULL, bms->log_seq, event_type, config.nfacctd_bmp_msglog_output, BMP_LOG_TYPE_TERM); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, NULL, BMP_LOG_TYPE_TERM); if (bms->msglog_backend_methods || bms->dump_backend_methods) bgp_peer_log_seq_increment(&bms->log_seq); while (bmp_hdr_len) { if (!(bth = (struct bmp_term_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_term_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [term] packet discarded: failed bmp_get_and_check_length() BMP term hdr\n", config.name, bms->log_str, peer->addr_str); return; } bmp_term_hdr_get_len(bth, &bmp_term_len); if (!(bmp_term_info = bmp_get_and_check_length(bmp_packet, len, bmp_term_len))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [term] packet discarded: failed bmp_get_and_check_length() BMP term info\n", config.name, bms->log_str, peer->addr_str); return; } if (bth->type == BMP_TERM_INFO_REASON && bmp_term_len == 2) bmp_term_hdr_get_reason_type(bmp_packet, len, &reason_type); { struct bmp_log_term blterm; blterm.type = bth->type; blterm.len = bmp_term_len; blterm.val = bmp_term_info; blterm.reas_type = reason_type; if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, &blterm, bms->log_seq, event_type, config.nfacctd_bmp_msglog_output, BMP_LOG_TYPE_TERM); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, &blterm, BMP_LOG_TYPE_TERM); if (bms->msglog_backend_methods || bms->dump_backend_methods) bgp_peer_log_seq_increment(&bms->log_seq); } bmp_hdr_len -= (bmp_term_len + sizeof(struct bmp_term_hdr)); } /* BGP peers are deleted as part of bmp_peer_close() */ }
void bmp_process_msg_init(char **bmp_packet, u_int32_t *len, u_int32_t bmp_hdr_len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer; struct bmp_data bdata; struct bmp_init_hdr *bih; u_int16_t bmp_init_len; char *bmp_init_info; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; memset(&bdata, 0, sizeof(bdata)); gettimeofday(&bdata.tstamp, NULL); bmp_hdr_len -= sizeof(struct bmp_common_hdr); if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, NULL, bms->log_seq, event_type, config.nfacctd_bmp_msglog_output, BMP_LOG_TYPE_INIT); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, NULL, BMP_LOG_TYPE_INIT); if (bms->msglog_backend_methods || bms->dump_backend_methods) bgp_peer_log_seq_increment(&bms->log_seq); while (bmp_hdr_len) { if (!(bih = (struct bmp_init_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_init_hdr)))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [init] packet discarded: failed bmp_get_and_check_length() BMP init hdr\n", config.name, bms->log_str, peer->addr_str); return; } bmp_init_hdr_get_len(bih, &bmp_init_len); if (!(bmp_init_info = bmp_get_and_check_length(bmp_packet, len, bmp_init_len))) { Log(LOG_INFO, "INFO ( %s/%s ): [%s] [init] packet discarded: failed bmp_get_and_check_length() BMP init info\n", config.name, bms->log_str, peer->addr_str); return; } { struct bmp_log_init blinit; blinit.type = bih->type; blinit.len = bmp_init_len; blinit.val = bmp_init_info; if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, &blinit, bms->log_seq, event_type, config.nfacctd_bmp_msglog_output, BMP_LOG_TYPE_INIT); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, &blinit, BMP_LOG_TYPE_INIT); if (bms->msglog_backend_methods || bms->dump_backend_methods) bgp_peer_log_seq_increment(&bms->log_seq); } bmp_hdr_len -= (bmp_init_len + sizeof(struct bmp_init_hdr)); } }
void bmp_process_msg_peer_down(char **bmp_packet, u_int32_t *len, struct bmp_peer *bmpp) { struct bgp_misc_structs *bms; struct bgp_peer *peer, *bmpp_bgp_peer; struct bmp_data bdata; struct bmp_peer_hdr *bph; struct bmp_peer_down_hdr *bpdh; void *ret; if (!bmpp) return; peer = &bmpp->self; bms = bgp_select_misc_db(peer->type); if (!bms) return; memset(&bdata, 0, sizeof(bdata)); if (!(bph = (struct bmp_peer_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_hdr)))) { Log(LOG_INFO, "INFO ( %s/core/BMP ): [%s] [peer down] packet discarded: failed bmp_get_and_check_length() BMP peer hdr\n", config.name, peer->addr_str); return; } if (!(bpdh = (struct bmp_peer_down_hdr *) bmp_get_and_check_length(bmp_packet, len, sizeof(struct bmp_peer_down_hdr)))) { Log(LOG_INFO, "INFO ( %s/core/BMP ): [%s] [peer down] packet discarded: failed bmp_get_and_check_length() BMP peer down hdr\n", config.name, peer->addr_str); return; } bmp_peer_hdr_get_family(bph, &bdata.family); bmp_peer_hdr_get_peer_ip(bph, &bdata.peer_ip, bdata.family); bmp_peer_hdr_get_bgp_id(bph, &bdata.bgp_id); bmp_peer_hdr_get_tstamp(bph, &bdata.tstamp); bmp_peer_hdr_get_peer_asn(bph, &bdata.peer_asn); bmp_peer_hdr_get_peer_type(bph, &bdata.peer_type); if (bdata.family) { /* If no timestamp in BMP then let's generate one */ if (!bdata.tstamp.tv_sec) gettimeofday(&bdata.tstamp, NULL); { struct bmp_log_peer_down blpd; bmp_peer_down_hdr_get_reason(bpdh, &blpd.reason); if (blpd.reason == BMP_PEER_DOWN_LOC_CODE) bmp_peer_down_hdr_get_loc_code(bmp_packet, len, &blpd.loc_code); if (bms->msglog_backend_methods) { char event_type[] = "log"; bmp_log_msg(peer, &bdata, &blpd, event_type, config.nfacctd_bmp_msglog_output, BMP_LOG_TYPE_PEER_DOWN); } if (bms->dump_backend_methods) bmp_dump_se_ll_append(peer, &bdata, &blpd, BMP_LOG_TYPE_PEER_DOWN); } ret = pm_tfind(&bdata.peer_ip, &bmpp->bgp_peers, bmp_bmpp_bgp_peer_host_addr_cmp); if (ret) { char peer_str[] = "peer_ip", *saved_peer_str = bms->peer_str; bmpp_bgp_peer = (*(struct bgp_peer **) ret); bms->peer_str = peer_str; bgp_peer_info_delete(bmpp_bgp_peer); bms->peer_str = saved_peer_str; pm_tdelete(&bdata.peer_ip, &bmpp->bgp_peers, bmp_bmpp_bgp_peer_host_addr_cmp); } } }
void bgp_srcdst_lookup(struct packet_ptrs *pptrs, int type) { struct bgp_misc_structs *bms; struct bgp_rt_structs *inter_domain_routing_db; struct sockaddr *sa = (struct sockaddr *) pptrs->f_agent, sa_local; struct xflow_status_entry *xs_entry = (struct xflow_status_entry *) pptrs->f_status; struct bgp_peer *peer; struct bgp_node *default_node, *result; struct bgp_info *info; struct node_match_cmp_term2 nmct2; struct prefix default_prefix; int compare_bgp_port; int follow_default = config.nfacctd_bgp_follow_default; struct in_addr pref4; #if defined ENABLE_IPV6 struct in6_addr pref6; #endif safi_t safi; rd_t rd; bms = bgp_select_misc_db(type); inter_domain_routing_db = bgp_select_routing_db(type); if (!bms || !inter_domain_routing_db) return; pptrs->bgp_src = NULL; pptrs->bgp_dst = NULL; pptrs->bgp_src_info = NULL; pptrs->bgp_dst_info = NULL; pptrs->bgp_peer = NULL; pptrs->bgp_nexthop_info = NULL; compare_bgp_port = FALSE; safi = SAFI_UNICAST; memset(&rd, 0, sizeof(rd)); if (pptrs->bta || pptrs->bta2) { sa = &sa_local; if (pptrs->bta_af == ETHERTYPE_IP) { sa->sa_family = AF_INET; ((struct sockaddr_in *)sa)->sin_addr.s_addr = pptrs->bta; if (pptrs->lookup_bgp_port.set) { ((struct sockaddr_in *)sa)->sin_port = pptrs->lookup_bgp_port.n; compare_bgp_port = TRUE; } } #if defined ENABLE_IPV6 else if (pptrs->bta_af == ETHERTYPE_IPV6) { sa->sa_family = AF_INET6; ip6_addr_32bit_cpy(&((struct sockaddr_in6 *)sa)->sin6_addr, &pptrs->bta, 0, 0, 1); ip6_addr_32bit_cpy(&((struct sockaddr_in6 *)sa)->sin6_addr, &pptrs->bta2, 2, 0, 1); if (pptrs->lookup_bgp_port.set) { ((struct sockaddr_in6 *)sa)->sin6_port = pptrs->lookup_bgp_port.n; compare_bgp_port = TRUE; } } #endif } start_again_follow_default: peer = bms->bgp_lookup_find_peer(sa, xs_entry, pptrs->l3_proto, compare_bgp_port); pptrs->bgp_peer = (char *) peer; if (peer) { struct host_addr peer_dst_ip; memset(&peer_dst_ip, 0, sizeof(peer_dst_ip)); if (peer->cap_add_paths && (config.acct_type == ACCT_NF || config.acct_type == ACCT_SF)) { /* administrativia */ struct pkt_bgp_primitives pbgp, *pbgp_ptr = &pbgp; memset(&pbgp, 0, sizeof(struct pkt_bgp_primitives)); /* note: call to [NF|SF]_peer_dst_ip_handler for the purpose of code re-use effectively is defeating the concept of libbgp */ if (config.acct_type == ACCT_NF) NF_peer_dst_ip_handler(NULL, pptrs, (char **)&pbgp_ptr); else if (config.acct_type == ACCT_SF) SF_peer_dst_ip_handler(NULL, pptrs, (char **)&pbgp_ptr); memcpy(&peer_dst_ip, &pbgp.peer_dst_ip, sizeof(struct host_addr)); } if (pptrs->bitr) { safi = SAFI_MPLS_VPN; memcpy(&rd, &pptrs->bitr, sizeof(rd)); } /* XXX: can be further optimized for the case of no SAFI_UNICAST rib */ start_again_mpls_label: if (pptrs->l3_proto == ETHERTYPE_IP) { if (!pptrs->bgp_src) { memset(&nmct2, 0, sizeof(struct node_match_cmp_term2)); nmct2.peer = (struct bgp_peer *) pptrs->bgp_peer; nmct2.rd = &rd; nmct2.peer_dst_ip = NULL; memcpy(&pref4, &((struct pm_iphdr *)pptrs->iph_ptr)->ip_src, sizeof(struct in_addr)); bgp_node_match_ipv4(inter_domain_routing_db->rib[AFI_IP][safi], &pref4, (struct bgp_peer *) pptrs->bgp_peer, bgp_route_info_modulo_pathid, bms->bgp_lookup_node_match_cmp, &nmct2, &result, &info); } if (!pptrs->bgp_src_info && result) { pptrs->bgp_src = (char *) result; pptrs->bgp_src_info = (char *) info; if (result->p.prefixlen >= pptrs->lm_mask_src) { pptrs->lm_mask_src = result->p.prefixlen; pptrs->lm_method_src = NF_NET_BGP; } } if (!pptrs->bgp_dst) { memset(&nmct2, 0, sizeof(struct node_match_cmp_term2)); nmct2.peer = (struct bgp_peer *) pptrs->bgp_peer; nmct2.rd = &rd; nmct2.peer_dst_ip = &peer_dst_ip; memcpy(&pref4, &((struct pm_iphdr *)pptrs->iph_ptr)->ip_dst, sizeof(struct in_addr)); bgp_node_match_ipv4(inter_domain_routing_db->rib[AFI_IP][safi], &pref4, (struct bgp_peer *) pptrs->bgp_peer, bgp_route_info_modulo_pathid, bms->bgp_lookup_node_match_cmp, &nmct2, &result, &info); } if (!pptrs->bgp_dst_info && result) { pptrs->bgp_dst = (char *) result; pptrs->bgp_dst_info = (char *) info; if (result->p.prefixlen >= pptrs->lm_mask_dst) { pptrs->lm_mask_dst = result->p.prefixlen; pptrs->lm_method_dst = NF_NET_BGP; } } } #if defined ENABLE_IPV6 else if (pptrs->l3_proto == ETHERTYPE_IPV6) { if (!pptrs->bgp_src) { memset(&nmct2, 0, sizeof(struct node_match_cmp_term2)); nmct2.peer = (struct bgp_peer *) pptrs->bgp_peer; nmct2.rd = &rd; nmct2.peer_dst_ip = NULL; memcpy(&pref6, &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_src, sizeof(struct in6_addr)); bgp_node_match_ipv6(inter_domain_routing_db->rib[AFI_IP6][safi], &pref6, (struct bgp_peer *) pptrs->bgp_peer, bgp_route_info_modulo_pathid, bms->bgp_lookup_node_match_cmp, &nmct2, &result, &info); } if (!pptrs->bgp_src_info && result) { pptrs->bgp_src = (char *) result; pptrs->bgp_src_info = (char *) info; if (result->p.prefixlen >= pptrs->lm_mask_src) { pptrs->lm_mask_src = result->p.prefixlen; pptrs->lm_method_src = NF_NET_BGP; } } if (!pptrs->bgp_dst) { memset(&nmct2, 0, sizeof(struct node_match_cmp_term2)); nmct2.peer = (struct bgp_peer *) pptrs->bgp_peer; nmct2.rd = &rd; nmct2.peer_dst_ip = &peer_dst_ip; memcpy(&pref6, &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_dst, sizeof(struct in6_addr)); bgp_node_match_ipv6(inter_domain_routing_db->rib[AFI_IP6][safi], &pref6, (struct bgp_peer *) pptrs->bgp_peer, bgp_route_info_modulo_pathid, bms->bgp_lookup_node_match_cmp, &nmct2, &result, &info); } if (!pptrs->bgp_dst_info && result) { pptrs->bgp_dst = (char *) result; pptrs->bgp_dst_info = (char *) info; if (result->p.prefixlen >= pptrs->lm_mask_dst) { pptrs->lm_mask_dst = result->p.prefixlen; pptrs->lm_method_dst = NF_NET_BGP; } } } #endif if ((!pptrs->bgp_src || !pptrs->bgp_dst) && safi != SAFI_MPLS_LABEL) { if (pptrs->l3_proto == ETHERTYPE_IP && inter_domain_routing_db->rib[AFI_IP][SAFI_MPLS_LABEL]) { safi = SAFI_MPLS_LABEL; goto start_again_mpls_label; } #if defined ENABLE_IPV6 else if (pptrs->l3_proto == ETHERTYPE_IPV6 && inter_domain_routing_db->rib[AFI_IP6][SAFI_MPLS_LABEL]) { safi = SAFI_MPLS_LABEL; goto start_again_mpls_label; } #endif } if (follow_default && safi != SAFI_MPLS_VPN) { default_node = NULL; if (pptrs->l3_proto == ETHERTYPE_IP) { memset(&default_prefix, 0, sizeof(default_prefix)); default_prefix.family = AF_INET; result = (struct bgp_node *) pptrs->bgp_src; if (result && prefix_match(&result->p, &default_prefix)) { default_node = result; pptrs->bgp_src = NULL; pptrs->bgp_src_info = NULL; } result = (struct bgp_node *) pptrs->bgp_dst; if (result && prefix_match(&result->p, &default_prefix)) { default_node = result; pptrs->bgp_dst = NULL; pptrs->bgp_dst_info = NULL; } } #if defined ENABLE_IPV6 else if (pptrs->l3_proto == ETHERTYPE_IPV6) { memset(&default_prefix, 0, sizeof(default_prefix)); default_prefix.family = AF_INET6; result = (struct bgp_node *) pptrs->bgp_src; if (result && prefix_match(&result->p, &default_prefix)) { default_node = result; pptrs->bgp_src = NULL; pptrs->bgp_src_info = NULL; } result = (struct bgp_node *) pptrs->bgp_dst; if (result && prefix_match(&result->p, &default_prefix)) { default_node = result; pptrs->bgp_dst = NULL; pptrs->bgp_dst_info = NULL; } } #endif if (!pptrs->bgp_src || !pptrs->bgp_dst) { follow_default--; compare_bgp_port = FALSE; // XXX: fixme: follow default in NAT traversal scenarios if (default_node) { if (info && info->attr) { if (info->attr->mp_nexthop.family == AF_INET) { sa = &sa_local; memset(sa, 0, sizeof(struct sockaddr)); sa->sa_family = AF_INET; memcpy(&((struct sockaddr_in *)sa)->sin_addr, &info->attr->mp_nexthop.address.ipv4, 4); goto start_again_follow_default; } #if defined ENABLE_IPV6 else if (info->attr->mp_nexthop.family == AF_INET6) { sa = &sa_local; memset(sa, 0, sizeof(struct sockaddr)); sa->sa_family = AF_INET6; ip6_addr_cpy(&((struct sockaddr_in6 *)sa)->sin6_addr, &info->attr->mp_nexthop.address.ipv6); goto start_again_follow_default; } #endif else { sa = &sa_local; memset(sa, 0, sizeof(struct sockaddr)); sa->sa_family = AF_INET; memcpy(&((struct sockaddr_in *)sa)->sin_addr, &info->attr->nexthop, 4); goto start_again_follow_default; } } } } } if (config.nfacctd_bgp_follow_nexthop[0].family && pptrs->bgp_dst && safi != SAFI_MPLS_VPN) bgp_follow_nexthop_lookup(pptrs, type); } }
void bgp_follow_nexthop_lookup(struct packet_ptrs *pptrs, int type) { struct bgp_misc_structs *bms; struct bgp_rt_structs *inter_domain_routing_db; struct sockaddr *sa = (struct sockaddr *) pptrs->f_agent, sa_local; struct bgp_peer *nh_peer; struct bgp_node *result_node = NULL; struct bgp_info *info; struct node_match_cmp_term2 nmct2; char *saved_info = NULL; int peers_idx, ttl = MAX_HOPS_FOLLOW_NH, self = MAX_NH_SELF_REFERENCES; int nh_idx, matched = 0; struct prefix nh, ch; struct in_addr pref4; #if defined ENABLE_IPV6 struct in6_addr pref6; #endif char *saved_agent = pptrs->f_agent; pm_id_t bta; u_int32_t modulo, local_modulo, modulo_idx, modulo_max; bms = bgp_select_misc_db(type); inter_domain_routing_db = bgp_select_routing_db(type); if (!bms || !inter_domain_routing_db) return; start_again: if (config.nfacctd_bgp_to_agent_map && (*find_id_func)) { bta = 0; (*find_id_func)((struct id_table *)pptrs->bta_table, pptrs, &bta, NULL); if (bta) { sa = &sa_local; sa->sa_family = AF_INET; ((struct sockaddr_in *)sa)->sin_addr.s_addr = bta; } } for (nh_peer = NULL, peers_idx = 0; peers_idx < bms->max_peers; peers_idx++) { if (!sa_addr_cmp(sa, &peers[peers_idx].addr) || !sa_addr_cmp(sa, &peers[peers_idx].id)) { nh_peer = &peers[peers_idx]; break; } } if (nh_peer) { modulo = bms->route_info_modulo(nh_peer, NULL, bms->table_per_peer_buckets); // XXX: to be optimized if (bms->table_per_peer_hash == BGP_ASPATH_HASH_PATHID) modulo_max = bms->table_per_peer_buckets; else modulo_max = 1; memset(&ch, 0, sizeof(ch)); ch.family = AF_INET; ch.prefixlen = 32; memcpy(&ch.u.prefix4, &nh_peer->addr.address.ipv4, 4); if (!result_node) { struct host_addr peer_dst_ip; rd_t rd; /* XXX: SAFI_MPLS_LABEL, SAFI_MPLS_VPN and peer_dst_ip (add_paths capability) not supported */ memset(&peer_dst_ip, 0, sizeof(peer_dst_ip)); memset(&rd, 0, sizeof(rd)); memset(&nmct2, 0, sizeof(struct node_match_cmp_term2)); nmct2.peer = (struct bgp_peer *) nh_peer; nmct2.rd = &rd; nmct2.peer_dst_ip = &peer_dst_ip; if (pptrs->l3_proto == ETHERTYPE_IP) { memcpy(&pref4, &((struct pm_iphdr *)pptrs->iph_ptr)->ip_dst, sizeof(struct in_addr)); bgp_node_match_ipv4(inter_domain_routing_db->rib[AFI_IP][SAFI_UNICAST], &pref4, nh_peer, bgp_route_info_modulo_pathid, bms->bgp_lookup_node_match_cmp, &nmct2, &result_node, &info); } #if defined ENABLE_IPV6 else if (pptrs->l3_proto == ETHERTYPE_IPV6) { memcpy(&pref6, &((struct ip6_hdr *)pptrs->iph_ptr)->ip6_dst, sizeof(struct in6_addr)); bgp_node_match_ipv6(inter_domain_routing_db->rib[AFI_IP6][SAFI_UNICAST], &pref6, nh_peer, bgp_route_info_modulo_pathid, bms->bgp_lookup_node_match_cmp, &nmct2, &result_node, &info); } #endif } memset(&nh, 0, sizeof(nh)); // XXX: to be optimized if (result_node) { for (local_modulo = modulo, modulo_idx = 0; modulo_idx < modulo_max; local_modulo++, modulo_idx++) { for (info = result_node->info[modulo]; info; info = info->next) { if (info->peer == nh_peer) break; } } } else info = NULL; if (info && info->attr) { if (info->attr->mp_nexthop.family == AF_INET) { nh.family = AF_INET; nh.prefixlen = 32; memcpy(&nh.u.prefix4, &info->attr->mp_nexthop.address.ipv4, 4); for (nh_idx = 0; config.nfacctd_bgp_follow_nexthop[nh_idx].family && nh_idx < FOLLOW_BGP_NH_ENTRIES; nh_idx++) { matched = prefix_match(&config.nfacctd_bgp_follow_nexthop[nh_idx], &nh); if (matched) break; } if (matched && self > 0 && ttl > 0) { if (prefix_match(&ch, &nh)) self--; sa = &sa_local; pptrs->f_agent = (char *) &sa_local; memset(sa, 0, sizeof(struct sockaddr)); sa->sa_family = AF_INET; memcpy(&((struct sockaddr_in *)sa)->sin_addr, &info->attr->mp_nexthop.address.ipv4, 4); saved_info = (char *) info; ttl--; goto start_again; } else { if (config.nfacctd_bgp_follow_nexthop_external) saved_info = (char *) info; goto end; } } #if defined ENABLE_IPV6 else if (info->attr->mp_nexthop.family == AF_INET6) { nh.family = AF_INET6; nh.prefixlen = 128; memcpy(&nh.u.prefix6, &info->attr->mp_nexthop.address.ipv6, 16); for (nh_idx = 0; config.nfacctd_bgp_follow_nexthop[nh_idx].family && nh_idx < FOLLOW_BGP_NH_ENTRIES; nh_idx++) { matched = prefix_match(&config.nfacctd_bgp_follow_nexthop[nh_idx], &nh); if (matched) break; } if (matched && self > 0 && ttl > 0) { if (prefix_match(&ch, &nh)) self--; sa = &sa_local; pptrs->f_agent = (char *) &sa_local; memset(sa, 0, sizeof(struct sockaddr)); sa->sa_family = AF_INET6; ip6_addr_cpy(&((struct sockaddr_in6 *)sa)->sin6_addr, &info->attr->mp_nexthop.address.ipv6); saved_info = (char *) info; ttl--; goto start_again; } else { if (config.nfacctd_bgp_follow_nexthop_external) saved_info = (char *) info; goto end; } } #endif else { nh.family = AF_INET; nh.prefixlen = 32; memcpy(&nh.u.prefix4, &info->attr->nexthop, 4); for (nh_idx = 0; config.nfacctd_bgp_follow_nexthop[nh_idx].family && nh_idx < FOLLOW_BGP_NH_ENTRIES; nh_idx++) { matched = prefix_match(&config.nfacctd_bgp_follow_nexthop[nh_idx], &nh); if (matched) break; } if (matched && self > 0 && ttl > 0) { if (prefix_match(&ch, &nh)) self--; sa = &sa_local; pptrs->f_agent = (char *) &sa_local; memset(sa, 0, sizeof(struct sockaddr)); sa->sa_family = AF_INET; memcpy(&((struct sockaddr_in *)sa)->sin_addr, &info->attr->nexthop, 4); saved_info = (char *) info; ttl--; goto start_again; } else { if (config.nfacctd_bgp_follow_nexthop_external) saved_info = (char *) info; goto end; } } } } end: if (saved_info) pptrs->bgp_nexthop_info = saved_info; pptrs->f_agent = saved_agent; }
int bgp_peer_log_msg(struct bgp_node *route, struct bgp_info *ri, afi_t afi, safi_t safi, char *event_type, int output, int log_type) { struct bgp_misc_structs *bms; char log_rk[SRVBUFLEN]; struct bgp_peer *peer; struct bgp_attr *attr; int ret = 0, amqp_ret = 0, kafka_ret = 0, etype = BGP_LOGDUMP_ET_NONE; pid_t writer_pid = getpid(); if (!ri || !ri->peer || !ri->peer->log || !event_type) return ERR; peer = ri->peer; attr = ri->attr; bms = bgp_select_misc_db(peer->type); if (!bms) return ERR; if (!strcmp(event_type, "dump")) etype = BGP_LOGDUMP_ET_DUMP; else if (!strcmp(event_type, "log")) etype = BGP_LOGDUMP_ET_LOG; #ifdef WITH_RABBITMQ if ((bms->msglog_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP)) p_amqp_set_routing_key(peer->log->amqp_host, peer->log->filename); #endif #ifdef WITH_KAFKA if ((bms->msglog_kafka_topic && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_kafka_topic && etype == BGP_LOGDUMP_ET_DUMP)) p_kafka_set_topic(peer->log->kafka_host, peer->log->filename); #endif if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char ip_address[INET6_ADDRSTRLEN]; json_t *obj = json_object(); char empty[] = ""; char prefix_str[INET6_ADDRSTRLEN], nexthop_str[INET6_ADDRSTRLEN]; char *aspath; /* no need for seq for "dump" event_type */ if (etype == BGP_LOGDUMP_ET_LOG) { json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t)bms->log_seq)); bgp_peer_log_seq_increment(&bms->log_seq); switch (log_type) { case BGP_LOG_TYPE_UPDATE: json_object_set_new_nocheck(obj, "log_type", json_string("update")); break; case BGP_LOG_TYPE_WITHDRAW: json_object_set_new_nocheck(obj, "log_type", json_string("withdraw")); break; case BGP_LOG_TYPE_DELETE: json_object_set_new_nocheck(obj, "log_type", json_string("delete")); break; default: json_object_set_new_nocheck(obj, "log_type", json_integer((json_int_t)log_type)); break; } } if (etype == BGP_LOGDUMP_ET_LOG) json_object_set_new_nocheck(obj, "timestamp", json_string(bms->log_tstamp_str)); else if (etype == BGP_LOGDUMP_ET_DUMP) json_object_set_new_nocheck(obj, "timestamp", json_string(bms->dump.tstamp_str)); if (bms->bgp_peer_log_msg_extras) bms->bgp_peer_log_msg_extras(peer, output, obj); if (ri && ri->extra && ri->extra->bmed.id && bms->bgp_peer_logdump_extra_data) bms->bgp_peer_logdump_extra_data(&ri->extra->bmed, output, obj); addr_to_str(ip_address, &peer->addr); json_object_set_new_nocheck(obj, bms->peer_str, json_string(ip_address)); json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); json_object_set_new_nocheck(obj, "afi", json_integer((json_int_t)afi)); json_object_set_new_nocheck(obj, "safi", json_integer((json_int_t)safi)); if (route) { memset(prefix_str, 0, INET6_ADDRSTRLEN); prefix2str(&route->p, prefix_str, INET6_ADDRSTRLEN); json_object_set_new_nocheck(obj, "ip_prefix", json_string(prefix_str)); } if (ri && ri->extra && ri->extra->path_id) json_object_set_new_nocheck(obj, "as_path_id", json_integer((json_int_t)ri->extra->path_id)); if (attr) { memset(nexthop_str, 0, INET6_ADDRSTRLEN); if (attr->mp_nexthop.family) addr_to_str(nexthop_str, &attr->mp_nexthop); else inet_ntop(AF_INET, &attr->nexthop, nexthop_str, INET6_ADDRSTRLEN); json_object_set_new_nocheck(obj, "bgp_nexthop", json_string(nexthop_str)); aspath = attr->aspath ? attr->aspath->str : empty; json_object_set_new_nocheck(obj, "as_path", json_string(aspath)); if (attr->community) json_object_set_new_nocheck(obj, "comms", json_string(attr->community->str)); if (attr->ecommunity) json_object_set_new_nocheck(obj, "ecomms", json_string(attr->ecommunity->str)); if (attr->lcommunity) json_object_set_new_nocheck(obj, "lcomms", json_string(attr->lcommunity->str)); json_object_set_new_nocheck(obj, "origin", json_integer((json_int_t)attr->origin)); json_object_set_new_nocheck(obj, "local_pref", json_integer((json_int_t)attr->local_pref)); if (attr->med) json_object_set_new_nocheck(obj, "med", json_integer((json_int_t)attr->med)); } if (safi == SAFI_MPLS_LABEL || safi == SAFI_MPLS_VPN) { u_char label_str[SHORTSHORTBUFLEN]; if (safi == SAFI_MPLS_VPN) { u_char rd_str[SHORTSHORTBUFLEN]; bgp_rd2str(rd_str, &ri->extra->rd); json_object_set_new_nocheck(obj, "rd", json_string(rd_str)); } bgp_label2str(label_str, ri->extra->label); json_object_set_new_nocheck(obj, "label", json_string(label_str)); } if ((bms->msglog_file && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_file && etype == BGP_LOGDUMP_ET_DUMP)) write_and_free_json(peer->log->fd, obj); #ifdef WITH_RABBITMQ if ((bms->msglog_amqp_routing_key && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_amqp_routing_key && etype == BGP_LOGDUMP_ET_DUMP)) { add_writer_name_and_pid_json(obj, config.proc_name, writer_pid); amqp_ret = write_and_free_json_amqp(peer->log->amqp_host, obj); p_amqp_unset_routing_key(peer->log->amqp_host); } #endif #ifdef WITH_KAFKA if ((bms->msglog_kafka_topic && etype == BGP_LOGDUMP_ET_LOG) || (bms->dump_kafka_topic && etype == BGP_LOGDUMP_ET_DUMP)) { add_writer_name_and_pid_json(obj, config.proc_name, writer_pid); kafka_ret = write_and_free_json_kafka(peer->log->kafka_host, obj); p_kafka_unset_topic(peer->log->kafka_host); } #endif #endif } return (ret | amqp_ret | kafka_ret); }
int bgp_peer_log_close(struct bgp_peer *peer, int output, int type) { struct bgp_misc_structs *bms = bgp_select_misc_db(type); char event_type[] = "log_close"; struct bgp_peer_log *log_ptr; void *amqp_log_ptr, *kafka_log_ptr; int ret = 0, amqp_ret = 0, kafka_ret = 0; pid_t writer_pid = getpid(); if (!bms || !peer || !peer->log) return ERR; #ifdef WITH_RABBITMQ if (bms->msglog_amqp_routing_key) p_amqp_set_routing_key(peer->log->amqp_host, peer->log->filename); #endif #ifdef WITH_KAFKA if (bms->msglog_kafka_topic) p_kafka_set_topic(peer->log->kafka_host, peer->log->filename); #endif log_ptr = peer->log; amqp_log_ptr = peer->log->amqp_host; kafka_log_ptr = peer->log->kafka_host; assert(peer->log->refcnt); peer->log->refcnt--; peer->log = NULL; if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char ip_address[INET6_ADDRSTRLEN]; json_t *obj = json_object(); json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t)bms->log_seq)); bgp_peer_log_seq_increment(&bms->log_seq); json_object_set_new_nocheck(obj, "timestamp", json_string(bms->log_tstamp_str)); if (bms->bgp_peer_logdump_initclose_extras) bms->bgp_peer_logdump_initclose_extras(peer, output, obj); addr_to_str(ip_address, &peer->addr); json_object_set_new_nocheck(obj, bms->peer_str, json_string(ip_address)); json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); if (bms->msglog_file) write_and_free_json(log_ptr->fd, obj); #ifdef WITH_RABBITMQ if (bms->msglog_amqp_routing_key) { add_writer_name_and_pid_json(obj, config.proc_name, writer_pid); amqp_ret = write_and_free_json_amqp(amqp_log_ptr, obj); p_amqp_unset_routing_key(amqp_log_ptr); } #endif #ifdef WITH_KAFKA if (bms->msglog_kafka_topic) { add_writer_name_and_pid_json(obj, config.proc_name, writer_pid); kafka_ret = write_and_free_json_kafka(kafka_log_ptr, obj); p_kafka_unset_topic(kafka_log_ptr); } #endif #endif } if (!log_ptr->refcnt) { if (bms->msglog_file && !log_ptr->refcnt) { fclose(log_ptr->fd); memset(log_ptr, 0, sizeof(struct bgp_peer_log)); } } return (ret | amqp_ret | kafka_ret); }
int bgp_peer_log_init(struct bgp_peer *peer, int output, int type) { struct bgp_misc_structs *bms = bgp_select_misc_db(type); int peer_idx, have_it, ret = 0, amqp_ret = 0, kafka_ret = 0; char log_filename[SRVBUFLEN], event_type[] = "log_init"; pid_t writer_pid = getpid(); if (!bms || !peer) return ERR; if (bms->msglog_file) bgp_peer_log_dynname(log_filename, SRVBUFLEN, bms->msglog_file, peer); if (bms->msglog_amqp_routing_key) { bgp_peer_log_dynname(log_filename, SRVBUFLEN, bms->msglog_amqp_routing_key, peer); } if (bms->msglog_kafka_topic) { bgp_peer_log_dynname(log_filename, SRVBUFLEN, bms->msglog_kafka_topic, peer); } for (peer_idx = 0, have_it = 0; peer_idx < bms->max_peers; peer_idx++) { if (!bms->peers_log[peer_idx].refcnt) { if (bms->msglog_file) { bms->peers_log[peer_idx].fd = open_output_file(log_filename, "a", FALSE); setlinebuf(bms->peers_log[peer_idx].fd); } #ifdef WITH_RABBITMQ if (bms->msglog_amqp_routing_key) bms->peers_log[peer_idx].amqp_host = bms->msglog_amqp_host; #endif #ifdef WITH_KAFKA if (bms->msglog_kafka_topic) bms->peers_log[peer_idx].kafka_host = bms->msglog_kafka_host; #endif strcpy(bms->peers_log[peer_idx].filename, log_filename); have_it = TRUE; break; } else if (!strcmp(log_filename, bms->peers_log[peer_idx].filename)) { have_it = TRUE; break; } } if (have_it) { peer->log = &bms->peers_log[peer_idx]; bms->peers_log[peer_idx].refcnt++; #ifdef WITH_RABBITMQ if (bms->msglog_amqp_routing_key) p_amqp_set_routing_key(peer->log->amqp_host, peer->log->filename); if (bms->msglog_amqp_routing_key_rr && !p_amqp_get_routing_key_rr(peer->log->amqp_host)) { p_amqp_init_routing_key_rr(peer->log->amqp_host); p_amqp_set_routing_key_rr(peer->log->amqp_host, bms->msglog_amqp_routing_key_rr); } #endif #ifdef WITH_KAFKA if (bms->msglog_kafka_topic) p_kafka_set_topic(peer->log->kafka_host, peer->log->filename); if (bms->msglog_kafka_topic_rr && !p_kafka_get_topic_rr(peer->log->kafka_host)) { p_kafka_init_topic_rr(peer->log->kafka_host); p_kafka_set_topic_rr(peer->log->kafka_host, bms->msglog_kafka_topic_rr); } #endif if (output == PRINT_OUTPUT_JSON) { #ifdef WITH_JANSSON char ip_address[INET6_ADDRSTRLEN]; json_t *obj = json_object(); json_object_set_new_nocheck(obj, "seq", json_integer((json_int_t)bms->log_seq)); bgp_peer_log_seq_increment(&bms->log_seq); json_object_set_new_nocheck(obj, "timestamp", json_string(bms->log_tstamp_str)); if (bms->bgp_peer_logdump_initclose_extras) bms->bgp_peer_logdump_initclose_extras(peer, output, obj); addr_to_str(ip_address, &peer->addr); json_object_set_new_nocheck(obj, bms->peer_str, json_string(ip_address)); json_object_set_new_nocheck(obj, "event_type", json_string(event_type)); if (bms->bgp_peer_log_msg_extras) bms->bgp_peer_log_msg_extras(peer, output, obj); if (bms->msglog_file) write_and_free_json(peer->log->fd, obj); #ifdef WITH_RABBITMQ if (bms->msglog_amqp_routing_key) { add_writer_name_and_pid_json(obj, config.proc_name, writer_pid); amqp_ret = write_and_free_json_amqp(peer->log->amqp_host, obj); p_amqp_unset_routing_key(peer->log->amqp_host); } #endif #ifdef WITH_KAFKA if (bms->msglog_kafka_topic) { add_writer_name_and_pid_json(obj, config.proc_name, writer_pid); kafka_ret = write_and_free_json_kafka(peer->log->kafka_host, obj); p_kafka_unset_topic(peer->log->kafka_host); } #endif #endif } } return (ret | amqp_ret | kafka_ret); }