コード例 #1
0
ファイル: telemetry_util.c プロジェクト: tacgomes/pmacct
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);
}
コード例 #2
0
ファイル: bgp_lookup.c プロジェクト: CrackerJackMack/pmacct
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));
}
コード例 #3
0
ファイル: bmp_msg.c プロジェクト: jwestfall69/pmacct
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);
    }
  }
}
コード例 #4
0
ファイル: bmp_msg.c プロジェクト: CodethinkLabs/pmacct
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);
      }
    }
  }
}
コード例 #5
0
ファイル: bmp_msg.c プロジェクト: CodethinkLabs/pmacct
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);
      }
    }
  }
}
コード例 #6
0
ファイル: bmp_msg.c プロジェクト: CodethinkLabs/pmacct
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;
}
コード例 #7
0
ファイル: bmp_msg.c プロジェクト: CodethinkLabs/pmacct
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);
      }
    }
  }
}
コード例 #8
0
ファイル: bmp_msg.c プロジェクト: CodethinkLabs/pmacct
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);
    }
  }
}
コード例 #9
0
ファイル: bmp_msg.c プロジェクト: CodethinkLabs/pmacct
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() */
}
コード例 #10
0
ファイル: bmp_msg.c プロジェクト: CodethinkLabs/pmacct
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));
  }
}
コード例 #11
0
ファイル: bmp_msg.c プロジェクト: jwestfall69/pmacct
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);
    } 
  }
}
コード例 #12
0
ファイル: bgp_lookup.c プロジェクト: bzed/pkg-pmacct
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);
  }
}
コード例 #13
0
ファイル: bgp_lookup.c プロジェクト: bzed/pkg-pmacct
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;
}
コード例 #14
0
ファイル: bgp_logdump.c プロジェクト: bzed/pkg-pmacct
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);
}
コード例 #15
0
ファイル: bgp_logdump.c プロジェクト: bzed/pkg-pmacct
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);
}
コード例 #16
0
ファイル: bgp_logdump.c プロジェクト: bzed/pkg-pmacct
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);
}