예제 #1
0
u_char mstream_getc(struct mstream *s, u_char *d) {
    u_char data;

    mstream_get(s, &data, sizeof(data));
    if(d!=NULL) memcpy(d,&data,sizeof(data));
    return data;
}
예제 #2
0
u_int32_t mstream_get_ipv4(struct mstream *s, u_int32_t *d) {
    u_int32_t data;

    mstream_get(s, &data, sizeof(data));
    if(d!=NULL) memcpy(d,&data,sizeof(data));
    return data;
}
예제 #3
0
u_int16_t mstream_getw(struct mstream *s, u_int16_t *d) {
    u_int16_t data;

    mstream_get(s, &data, sizeof(data));
    data=ntohs(data);
    if(d!=NULL) memcpy(d,&data,sizeof(data));
    return data;
}
예제 #4
0
int process_zebra_bgp_message_notify(struct mstream *s, BGPDUMP_ENTRY *entry) {
    mstream_getc(s, &entry->body.zebra_message.error_code);
    mstream_getc(s, &entry->body.zebra_message.sub_error_code);
    entry->body.zebra_message.notify_len = entry->body.zebra_message.size - 21;

    if(entry->body.zebra_message.notify_len > 0) {
	entry->body.zebra_message.notify_data = malloc(entry->body.zebra_message.notify_len);
	mstream_get(s, entry->body.zebra_message.notify_data, entry->body.zebra_message.notify_len);
    }

    return 1;
}
예제 #5
0
int process_zebra_bgp_message_open(struct mstream *s, BGPDUMP_ENTRY *entry, u_int8_t asn_len) {
    mstream_getc(s, &entry->body.zebra_message.version);
    read_asn(s, &entry->body.zebra_message.my_as, asn_len);
    mstream_getw(s, &entry->body.zebra_message.hold_time);
    mstream_get_ipv4(s, &entry->body.zebra_message.bgp_id.s_addr);
    mstream_getc(s, &entry->body.zebra_message.opt_len);

    if(entry->body.zebra_message.opt_len) {
	entry->body.zebra_message.opt_data = malloc(entry->body.zebra_message.opt_len);
	mstream_get(s, entry->body.zebra_message.opt_data, entry->body.zebra_message.opt_len);
    }

    return 1;
}
예제 #6
0
int process_mrtd_table_dump_v2_ipv6_unicast(struct mstream *s, BGPDUMP_ENTRY *entry){
#ifdef BGPDUMP_HAVE_IPV6
	BGPDUMP_TABLE_DUMP_V2_PREFIX *prefixdata;
	prefixdata = &entry->body.mrtd_table_dump_v2_prefix;
	uint16_t i;

	prefixdata->afi = AFI_IP6;
	prefixdata->safi = SAFI_UNICAST;

	mstream_getl(s, &prefixdata->seq);

	mstream_getc(s, &prefixdata->prefix_length);
	bzero(&prefixdata->prefix.v6_addr.s6_addr, 16);
	mstream_get(s, &prefixdata->prefix.v6_addr.s6_addr, (prefixdata->prefix_length+7)/8);

	mstream_getw(s, &prefixdata->entry_count);

	prefixdata->entries = malloc(sizeof(BGPDUMP_TABLE_DUMP_V2_ROUTE_ENTRY) * prefixdata->entry_count);
	if(prefixdata->entries == NULL){
	    syslog(LOG_ERR, "process_mrtd_table_dump_v2_ipv6_unicast: failed to allocate memory for entry table");
		return 0;
	}

	for(i=0; i < prefixdata->entry_count; i++){
		BGPDUMP_TABLE_DUMP_V2_ROUTE_ENTRY *e;
		e = &prefixdata->entries[i];

		mstream_getw(s, &e->peer_index);
		e->peer = &table_dump_v2_peer_index_table->entries[e->peer_index];
		mstream_getl(s, &e->originated_time);

    	process_attr_init(entry);
		entry->attr->len = e->attribute_length;
		process_attr_read(s, entry->attr, 4, NULL, 1);
		e->attr = entry->attr;
		entry->attr = NULL;
	}

#endif
	return 1;
}
예제 #7
0
// construct a partial mstream
mstream_t mstream_copy(mstream_t *s, int len) {
    mstream_t copy = {0};
    copy.start = s->start + s->position;
    copy.len = mstream_get(s, NULL, len);
    return copy;
}
예제 #8
0
struct in_addr mstream_get_ipv4(struct mstream *s) {
    struct in_addr addr;

    mstream_get(s, &addr.s_addr, 4);
    return addr;
}
예제 #9
0
void process_attr_read(struct mstream *s, struct attr *attr, u_int8_t asn_len, struct zebra_incomplete *incomplete, char mp_only_nexthop) {
    u_char	flag;
    u_char	type;
    u_int32_t	len, end;
    u_int32_t	truelen;
    struct unknown_attr *unknown;

    mstream_getw(s, &attr->len);
    if(attr->len == 0)
      return;

    attr->data=malloc(attr->len);

    /* Check the attributes are not truncated */
    if(attr->len > mstream_can_read(s)) {
	truelen = mstream_can_read(s);
	memset(attr->data + truelen, 0, attr->len - truelen);
    } else {
	truelen = attr->len;
    }
    memcpy(attr->data, &s->start[s->position], truelen);

    end = s->position + truelen;

    while(s->position < end) {
	mstream_getc(s,&flag);
	mstream_getc(s,&type);

	if(flag & BGP_ATTR_FLAG_EXTLEN)
	    len=mstream_getw(s,NULL);
	else
	    len=mstream_getc(s,NULL);

	/* Take note of all attributes, including unknown ones */
	if(type <= sizeof(attr->flag) * 8)
	  attr->flag = attr->flag | ATTR_FLAG_BIT (type);

	switch(type) {
	    case BGP_ATTR_ORIGIN:
		mstream_getc(s,&attr->origin);
		break;
	    case BGP_ATTR_AS_PATH:
		attr->aspath = create_aspath(len, asn_len);
		mstream_get(s,attr->aspath->data,len);
		process_attr_aspath_string(attr->aspath);
		break;
	    case BGP_ATTR_NEXT_HOP:
		mstream_get_ipv4(s,&attr->nexthop.s_addr);
		break;
	    case BGP_ATTR_MULTI_EXIT_DISC:
		mstream_getl(s,&attr->med);
		break;
	    case BGP_ATTR_LOCAL_PREF:
		mstream_getl(s,&attr->local_pref);
		break;
	    case BGP_ATTR_ATOMIC_AGGREGATE:
		break;
	    case BGP_ATTR_AGGREGATOR:
		read_asn(s, &attr->aggregator_as, asn_len);
		mstream_get_ipv4(s,&attr->aggregator_addr.s_addr);
		break;
	    case BGP_ATTR_COMMUNITIES:
		attr->community		= malloc(sizeof(struct community));
		attr->community->size	= len / 4;
		attr->community->val	= malloc(len);
		mstream_get(s,attr->community->val,len);
		attr->community->str	= NULL;
		process_attr_community_string(attr->community);
		break;
	    case BGP_ATTR_MP_REACH_NLRI:
		if(attr->mp_info == NULL) {
		    attr->mp_info = malloc(sizeof(struct mp_info));
		    memset(attr->mp_info, 0, sizeof(struct mp_info));
		}
		if(mp_only_nexthop)
			process_mp_announce_only_nexthop(s, attr->mp_info, len, incomplete);
		else
			process_mp_announce(s, attr->mp_info, len, incomplete);
		break;
	    case BGP_ATTR_MP_UNREACH_NLRI:
		if(attr->mp_info == NULL) {
		    attr->mp_info = malloc(sizeof(struct mp_info));
		    memset(attr->mp_info, 0, sizeof(struct mp_info));
		}
		process_mp_withdraw(s, attr->mp_info, len, incomplete);
	    case BGP_ATTR_NEW_AS_PATH:
		attr->new_aspath = create_aspath(len, ASN32_LEN);
		mstream_get(s,attr->new_aspath->data,len);
		process_attr_aspath_string(attr->new_aspath);
                /* AS_CONFED_SEQUENCE and AS_CONFED_SET segments invalid in NEW_AS_PATH */
                check_new_aspath(attr->new_aspath);
		break;
	    case BGP_ATTR_NEW_AGGREGATOR:
		read_asn(s, &attr->new_aggregator_as, ASN32_LEN);
		mstream_get_ipv4(s,&attr->new_aggregator_addr.s_addr);
		break;

	    case BGP_ATTR_ORIGINATOR_ID:
		mstream_get_ipv4(s,&attr->originator_id.s_addr);
		break;
	    case BGP_ATTR_CLUSTER_LIST:
		attr->cluster		= malloc(sizeof(struct cluster_list));
		attr->cluster->length	= len/4;
		attr->cluster->list = malloc((attr->cluster->length) * sizeof(struct in_addr));
	
		int cluster_index;
		for (cluster_index=0;cluster_index<attr->cluster->length;cluster_index++)
			mstream_get_ipv4(s,&attr->cluster->list[cluster_index].s_addr);
		break;

	    default:
		/* Unknown attribute. Save as is */
		attr->unknown_num++;
		attr->unknown = realloc(attr->unknown, attr->unknown_num * sizeof(struct unknown_attr));

		/* Pointer to the unknown attribute we want to fill in */
		unknown = attr->unknown + attr->unknown_num - 1;

		/* Work around bogus attribute lengths */
		if(s->position + len > end)
		    unknown->real_len = end - s->position;
		else
		    unknown->real_len = len;

		unknown->flag = flag;
		unknown->type = type;
		unknown->len = len;

		unknown->raw = malloc(unknown->real_len + ((flag & BGP_ATTR_FLAG_EXTLEN) ? 4 : 3));

		unknown->raw[0] = flag;
		unknown->raw[1] = type;

		if(flag & BGP_ATTR_FLAG_EXTLEN) {
		    unknown->raw[2] = (len & 0xFF00) >> 8;
		    unknown->raw[3] = len & 0xFF;
		    mstream_get(s, unknown->raw + 4, unknown->real_len);
		} else {
		    unknown->raw[2] = len;
		    mstream_get(s, unknown->raw + 3, unknown->real_len);
		}
		break;
	}
예제 #10
0
int process_zebra_bgp_message(struct mstream *s,BGPDUMP_ENTRY *entry, u_int8_t asn_len) {
    u_char marker[16]; /* BGP marker */

    read_asn(s, &entry->body.zebra_message.source_as, asn_len);
    read_asn(s, &entry->body.zebra_message.destination_as, asn_len);
    mstream_getw(s,&entry->body.zebra_message.interface_index);
    mstream_getw(s,&entry->body.zebra_message.address_family);

    /* Initialize announce and withdraw arrays: if there is a
     * parse error, they will not be free()d, and we will not segfault. */
    entry->body.zebra_message.withdraw = NULL;
    entry->body.zebra_message.announce = NULL;

    entry->body.zebra_message.opt_len = 0;
    entry->body.zebra_message.opt_data = NULL;
    entry->body.zebra_message.notify_len = 0;
    entry->body.zebra_message.notify_data = NULL;

    switch(entry->body.zebra_message.address_family) {
	case AFI_IP:
	    mstream_get_ipv4(s,&entry->body.zebra_message.source_ip.v4_addr.s_addr);
	    mstream_get_ipv4(s,&entry->body.zebra_message.destination_ip.v4_addr.s_addr);
	    mstream_get (s, marker, 16);
	    break;
#ifdef BGPDUMP_HAVE_IPV6
	case AFI_IP6:
	    mstream_get(s,&entry->body.zebra_message.source_ip.v6_addr.s6_addr, 16);
	    mstream_get(s,&entry->body.zebra_message.destination_ip.v6_addr.s6_addr, 16);
	    mstream_get (s, marker, 16);
	    break;
#endif
	case 0xFFFF:
	    /* Zebra doesn't dump ifindex or src/dest IPs in OPEN
	     * messages. Work around it. */
	    if (entry->body.zebra_message.interface_index == 0xFFFF) {
		memset(marker, 0xFF, 4);
		mstream_get (s, marker + 4, 12);
		entry->body.zebra_message.interface_index = 0;
		entry->body.zebra_message.address_family = AFI_IP;
		entry->body.zebra_message.source_ip.v4_addr.s_addr = 0;
		entry->body.zebra_message.destination_ip.v4_addr.s_addr = 0;
		break;
	    }
	    /* Note fall through! If we don't recognize this type of data corruption, we say
	     * the address family is unsupported (since FFFF is not a valid address family) */
	default:
	    /* unsupported address family */
	    syslog(LOG_WARNING, "process_zebra_bgp_message: unsupported AFI %d",
		   entry->body.zebra_message.address_family);
	    return 0;
    }

    if(memcmp(marker, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377", 16) != 0) {
	/* bad marker... ignore packet */
	syslog(LOG_WARNING,
	       "bgp_message: bad marker: %02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x.%02x",
	       marker[0],marker[1],marker[2],marker[3],marker[4],marker[5],marker[6],marker[7],
	       marker[8],marker[9],marker[10],marker[11],marker[12],marker[13],marker[14],marker[15]);
	return 0;
    }

    mstream_getw (s,&entry->body.zebra_message.size);
    mstream_getc (s,&entry->body.zebra_message.type);

    entry->body.zebra_message.cut_bytes = entry->body.zebra_message.size - 19 - mstream_can_read(s);

    switch(entry->body.zebra_message.type) {
	case BGP_MSG_OPEN:
	    return process_zebra_bgp_message_open(s,entry, asn_len);
	case BGP_MSG_UPDATE:
	    return process_zebra_bgp_message_update(s,entry, asn_len);
	case BGP_MSG_NOTIFY:
	    return process_zebra_bgp_message_notify(s,entry);
	case BGP_MSG_KEEPALIVE:
	    /* Nothing to do */
	    return 1;
	case BGP_MSG_ROUTE_REFRESH_01:
	    /* Not implemented yet */
	    syslog(LOG_WARNING, "bgp_message: MSG_ROUTE_REFRESH_01 not implemented yet");
	    return 0;
	case BGP_MSG_ROUTE_REFRESH:
	    /* Not implemented yet */
	    syslog(LOG_WARNING, "bgp_message: MSG_ROUTE_REFRESH not implemented yet");
	    return 0;
	default:
	    syslog(LOG_WARNING, "bgp_message: unknown BGP message type %d",
		   entry->body.zebra_message.type);
	    return 0;
    }
}
예제 #11
0
int
process_zebra_bgp_state_change(struct mstream *s,BGPDUMP_ENTRY *entry, u_int8_t asn_len) {
    read_asn(s, &entry->body.zebra_state_change.source_as, asn_len);
    read_asn(s, &entry->body.zebra_state_change.destination_as, asn_len);

    /* Work around Zebra dump corruption.
     * N.B. I don't see this in quagga 0.96.4 any more. Is it fixed? */
    if (entry->length == 8) {
	syslog(LOG_NOTICE,
	       "process_zebra_bgp_state_change: 8-byte state change (zebra bug?)");

	mstream_getw(s,&entry->body.zebra_state_change.old_state);
	mstream_getw(s,&entry->body.zebra_state_change.new_state);

	/* Fill in with dummy values */
	entry->body.zebra_state_change.interface_index = 0;
	entry->body.zebra_state_change.address_family = AFI_IP;
	entry->body.zebra_state_change.source_ip.v4_addr.s_addr = 0;
	entry->body.zebra_state_change.destination_ip.v4_addr.s_addr = 0;

   	return 1;
    }

    mstream_getw(s,&entry->body.zebra_state_change.interface_index);
    mstream_getw(s,&entry->body.zebra_state_change.address_family);

    switch(entry->body.zebra_state_change.address_family) {
	case AFI_IP:
	    // length could be 20 or 24 (asn16 vs asn32)
	    if(entry->length != 20 && entry->length != 24) {
		syslog(LOG_WARNING, "process_zebra_bgp_state_change: bad length %d",
		       entry->length);
		return 0;
	    }

	    mstream_get_ipv4(s,&entry->body.zebra_state_change.source_ip.v4_addr.s_addr);
	    mstream_get_ipv4(s,&entry->body.zebra_state_change.destination_ip.v4_addr.s_addr);
	    break;
#ifdef BGPDUMP_HAVE_IPV6
	case AFI_IP6:
	    // length could be 44 or 48 (asn16 vs asn32)
	    if(entry->length != 44 && entry->length != 48) {
		syslog(LOG_WARNING, "process_zebra_bgp_state_change: bad length %d",
		       entry->length);
		return 0;
	    }

	    mstream_get(s, &entry->body.zebra_state_change.source_ip.v6_addr.s6_addr, 16);
	    mstream_get(s, &entry->body.zebra_state_change.destination_ip.v6_addr.s6_addr, 16);
	    break;
#endif
	default:
	    syslog(LOG_WARNING, "process_zebra_bgp_state_change: unknown AFI %d",
		   entry->body.zebra_state_change.address_family);
	    return 0;
    }
    mstream_getw(s,&entry->body.zebra_state_change.old_state);
    mstream_getw(s,&entry->body.zebra_state_change.new_state);

    return 1;
}
예제 #12
0
int process_mrtd_table_dump_v2_peer_index_table(struct mstream *s,BGPDUMP_ENTRY *entry) {
	BGPDUMP_TABLE_DUMP_V2_PEER_INDEX_TABLE *t;
	uint16_t i;
	uint8_t peertype;
	uint16_t view_name_len;

	if(table_dump_v2_peer_index_table){
		if(table_dump_v2_peer_index_table->entries)
			free(table_dump_v2_peer_index_table->entries);
		free(table_dump_v2_peer_index_table);
	}

	table_dump_v2_peer_index_table = malloc(sizeof(BGPDUMP_TABLE_DUMP_V2_PEER_INDEX_TABLE));
	t = table_dump_v2_peer_index_table;
	t->entries = NULL;

    mstream_get_ipv4(s,(uint32_t *)&t->local_bgp_id);

    mstream_getw(s,&view_name_len);
	strcpy(t->view_name, "");

	// view_name_len is without trailing \0
	if(view_name_len+1 > BGPDUMP_TYPE_TABLE_DUMP_V2_MAX_VIEWNAME_LEN) {
	    syslog(LOG_WARNING, "process_mrtd_table_dump_v2_peer_index_table: view name length more than maximum length (%d), ignoring view name", BGPDUMP_TYPE_TABLE_DUMP_V2_MAX_VIEWNAME_LEN);
	} else {
		mstream_get(s, t->view_name, view_name_len);
		t->view_name[view_name_len] = 0;
	}

    mstream_getw(s,&t->peer_count);

	t->entries = malloc(sizeof(BGPDUMP_TABLE_DUMP_V2_PEER_INDEX_TABLE_ENTRY) * t->peer_count);
	if(t->entries == NULL){
	    syslog(LOG_ERR, "process_mrtd_table_dump_v2_peer_index_table: failed to allocate memory for index table");
		return 0;
	}

	for(i=0; i < t->peer_count; i++) {
    	mstream_getc(s,&peertype);
#ifdef BGPDUMP_HAVE_IPV6
		if(peertype & BGPDUMP_PEERTYPE_TABLE_DUMP_V2_AFI_IP6)
			t->entries[i].afi = AFI_IP6;
		else
#endif
			t->entries[i].afi = AFI_IP;

    	mstream_get_ipv4(s,(uint32_t *)&t->entries[i].peer_bgp_id);

		if(t->entries[i].afi == AFI_IP)
			mstream_get_ipv4(s,&t->entries[i].peer_ip.v4_addr.s_addr);
#ifdef BGPDUMP_HAVE_IPV6
		else
			mstream_get(s, &t->entries[i].peer_ip.v6_addr.s6_addr, 16);
#endif


		if(peertype & BGPDUMP_PEERTYPE_TABLE_DUMP_V2_AS4)
			read_asn(s, &t->entries[i].peer_as, 4);
		else
			read_asn(s, &t->entries[i].peer_as, 2);

	}
	return 0;
}
예제 #13
0
int process_mrtd_table_dump(struct mstream *s,BGPDUMP_ENTRY *entry) {
    int afi = entry->subtype;
    u_int8_t asn_len;
    u_int32_t temp_time = 0;
    mstream_getw(s,&entry->body.mrtd_table_dump.view);
    mstream_getw(s,&entry->body.mrtd_table_dump.sequence);
    switch(afi) {
	case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP:
	case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP_32BIT_AS:
	    mstream_get_ipv4(s, &entry->body.mrtd_table_dump.prefix.v4_addr.s_addr);
	    break;
#ifdef BGPDUMP_HAVE_IPV6
	case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6:
	case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6_32BIT_AS:
	    mstream_get(s, &entry->body.mrtd_table_dump.prefix.v6_addr.s6_addr, 16);
	    break;
#endif
	default:
	    syslog(LOG_WARNING, "process_mrtd_table_dump: unknown AFI %d",  afi);
	    mstream_get(s, NULL, mstream_can_read(s));
	    return 0;
    }
    mstream_getc(s,&entry->body.mrtd_table_dump.mask);
    mstream_getc(s,&entry->body.mrtd_table_dump.status);
    mstream_getl(s,&temp_time);
    (entry->body).mrtd_table_dump.uptime = temp_time;

    switch(afi) {
      case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP:
      case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP_32BIT_AS:
	mstream_get_ipv4(s, &entry->body.mrtd_table_dump.peer_ip.v4_addr.s_addr);
	break;
#ifdef BGPDUMP_HAVE_IPV6
      case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6:
      case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6_32BIT_AS:
	mstream_get(s, &entry->body.mrtd_table_dump.peer_ip.v6_addr.s6_addr, 16);
	break;
#endif
    }

    switch(afi) {
      case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP:
      case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6:
	asn_len = ASN16_LEN;
	break;
      case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP_32BIT_AS:
      case BGPDUMP_SUBTYPE_MRTD_TABLE_DUMP_AFI_IP6_32BIT_AS:
	asn_len = ASN32_LEN;
	break;
      default:
	/* Not reached. Keep compiler happy */
	asn_len = 0;
	break;
    }

    read_asn(s,&entry->body.mrtd_table_dump.peer_as, asn_len);

    process_attr_init(entry);
    process_attr_read(s, entry->attr, asn_len, NULL, 0);

    return 1;
}