/* Dump BGP status change. */ void bgp_dump_state (struct peer *peer, int status_old, int status_new) { struct stream *obuf; /* If dump file pointer is disabled return immediately. */ if (bgp_dump_all.fp == NULL) return; /* Make dump stream. */ obuf = bgp_dump_obuf; stream_reset (obuf); bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4, bgp_dump_all.type); bgp_dump_common (obuf, peer, 1);/* force this in as4speak*/ stream_putw (obuf, status_old); stream_putw (obuf, status_new); /* Set length. */ bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP); /* Write to the stream. */ fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_all.fp); fflush (bgp_dump_all.fp); }
void bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer, struct stream *packet) { struct stream *obuf; /* If dump file pointer is disabled return immediately. */ if (bgp_dump->fp == NULL) return; /* Make dump stream. */ obuf = bgp_dump_obuf; stream_reset (obuf); /* Dump header and common part. */ bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE); bgp_dump_common (obuf, peer); /* Packet contents. */ stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet)); /* Set length. */ bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP); /* Write to the stream. */ fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump->fp); fflush (bgp_dump->fp); }
/* Dump BGP status change. */ void bgp_dump_state (struct peer *peer, int status_old, int status_new) { int ret; struct stream *obuf; /* If dump file pointer is disabled return immediately. */ if (bgp_dump_all.fp == NULL) return; /* Make dump stream. */ obuf = bgp_dump_obuf; stream_reset (obuf); bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_STATE_CHANGE_AS4); bgp_dump_common (obuf, peer, 1);/* force this in as4speak*/ stream_putw (obuf, status_old); stream_putw (obuf, status_new); /* Set length. */ bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP); /* Write to the stream. */ ret = fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_all.fp); if (ret != 1) { zlog_warn ("bgp_dump_state: fwrite returned %d, expected 1: %s", ret, strerror (errno)); } fflush (bgp_dump_all.fp); }
static void bgp_dump_packet_func (struct bgp_dump *bgp_dump, struct peer *peer, struct stream *packet) { int ret; struct stream *obuf; /* If dump file pointer is disabled return immediately. */ if (bgp_dump->fp == NULL) return; /* Make dump stream. */ obuf = bgp_dump_obuf; stream_reset (obuf); /* Dump header and common part. */ if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) ) { bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE_AS4); } else { bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_MESSAGE); } bgp_dump_common (obuf, peer, 0); /* Packet contents. */ stream_put (obuf, STREAM_DATA (packet), stream_get_endp (packet)); /* Set length. */ bgp_dump_set_size (obuf, MSG_PROTOCOL_BGP4MP); /* Write to the stream. */ ret = fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump->fp); if (ret != 1) { zlog_warn ("bgp_dump_packet_func: fwrite returned %d, expected 1: %s", ret, strerror (errno)); } fflush (bgp_dump->fp); }
/* Runs under child process. */ static unsigned int bgp_dump_routes_func (int afi, int first_run, unsigned int seq) { struct stream *obuf; struct bgp_info *info; struct bgp_node *rn; struct bgp *bgp; struct bgp_table *table; bgp = bgp_get_default (); if (!bgp) return seq; if (bgp_dump_routes.fp == NULL) return seq; /* Note that bgp_dump_routes_index_table will do ipv4 and ipv6 peers, so this should only be done on the first call to bgp_dump_routes_func. ( this function will be called once for ipv4 and once for ipv6 ) */ if(first_run) bgp_dump_routes_index_table(bgp); obuf = bgp_dump_obuf; stream_reset(obuf); /* Walk down each BGP route. */ table = bgp->rib[afi][SAFI_UNICAST]; for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) { if(!rn->info) continue; stream_reset(obuf); /* MRT header */ if (afi == AFI_IP) bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST, BGP_DUMP_ROUTES); else if (afi == AFI_IP6) bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST, BGP_DUMP_ROUTES); /* Sequence number */ stream_putl(obuf, seq); /* Prefix length */ stream_putc (obuf, rn->p.prefixlen); /* Prefix */ if (afi == AFI_IP) { /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */ stream_write(obuf, (u_char *)&rn->p.u.prefix4, (rn->p.prefixlen+7)/8); } else if (afi == AFI_IP6) { /* We'll dump only the useful bits (those not 0), but have to align on 8 bits */ stream_write (obuf, (u_char *)&rn->p.u.prefix6, (rn->p.prefixlen+7)/8); } /* Save where we are now, so we can overwride the entry count later */ int sizep = stream_get_endp(obuf); /* Entry count */ uint16_t entry_count = 0; /* Entry count, note that this is overwritten later */ stream_putw(obuf, 0); for (info = rn->info; info; info = info->next) { entry_count++; /* Peer index */ stream_putw(obuf, info->peer->table_dump_index); /* Originated */ #ifdef HAVE_CLOCK_MONOTONIC stream_putl (obuf, time(NULL) - (bgp_clock() - info->uptime)); #else stream_putl (obuf, info->uptime); #endif /* HAVE_CLOCK_MONOTONIC */ /* Dump attribute. */ /* Skip prefix & AFI/SAFI for MP_NLRI */ bgp_dump_routes_attr (obuf, info->attr, &rn->p); } /* Overwrite the entry count, now that we know the right number */ stream_putw_at (obuf, sizep, entry_count); seq++; bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2); fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp); } fflush (bgp_dump_routes.fp); return seq; }
static void bgp_dump_routes_index_table(struct bgp *bgp) { struct peer *peer; struct listnode *node; uint16_t peerno = 0; struct stream *obuf; obuf = bgp_dump_obuf; stream_reset (obuf); /* MRT header */ bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_PEER_INDEX_TABLE, BGP_DUMP_ROUTES); /* Collector BGP ID */ stream_put_in_addr (obuf, &bgp->router_id); /* View name */ if(bgp->name) { stream_putw (obuf, strlen(bgp->name)); stream_put(obuf, bgp->name, strlen(bgp->name)); } else { stream_putw(obuf, 0); } /* Peer count */ stream_putw (obuf, listcount(bgp->peer)); /* Walk down all peers */ for(ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer)) { /* Peer's type */ if (sockunion_family(&peer->su) == AF_INET) { stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP); } else if (sockunion_family(&peer->su) == AF_INET6) { stream_putc (obuf, TABLE_DUMP_V2_PEER_INDEX_TABLE_AS4+TABLE_DUMP_V2_PEER_INDEX_TABLE_IP6); } /* Peer's BGP ID */ stream_put_in_addr (obuf, &peer->remote_id); /* Peer's IP address */ if (sockunion_family(&peer->su) == AF_INET) { stream_put_in_addr (obuf, &peer->su.sin.sin_addr); } else if (sockunion_family(&peer->su) == AF_INET6) { stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN); } /* Peer's AS number. */ /* Note that, as this is an AS4 compliant quagga, the RIB is always AS4 */ stream_putl (obuf, peer->as); /* Store the peer number for this peer */ peer->table_dump_index = peerno; peerno++; } bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2); fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp); fflush (bgp_dump_routes.fp); }
void bgp_dump_routes_entry (struct prefix *p, struct bgp_info *info, int afi, int type, unsigned int seq) { struct stream *obuf; struct attr *attr; struct peer *peer; int plen; int safi = 0; /* Make dump stream. */ obuf = bgp_dump_obuf; stream_reset (obuf); attr = info->attr; peer = info->peer; /* We support MRT's old format. */ if (type == MSG_TABLE_DUMP) { bgp_dump_header (obuf, MSG_TABLE_DUMP, afi); stream_putw (obuf, 0); /* View # */ stream_putw (obuf, seq); /* Sequence number. */ } else { bgp_dump_header (obuf, MSG_PROTOCOL_BGP4MP, BGP4MP_ENTRY); stream_putl (obuf, info->uptime); /* Time Last Change */ stream_putw (obuf, afi); /* Address Family */ stream_putc (obuf, safi); /* SAFI */ } if (afi == AFI_IP) { if (type == MSG_TABLE_DUMP) { /* Prefix */ stream_put_in_addr (obuf, &p->u.prefix4); stream_putc (obuf, p->prefixlen); /* Status */ stream_putc (obuf, 1); /* Originated */ stream_putl (obuf, info->uptime); /* Peer's IP address */ stream_put_in_addr (obuf, &peer->su.sin.sin_addr); /* Peer's AS number. */ stream_putw (obuf, peer->as); /* Dump attribute. */ bgp_dump_routes_attr (obuf, attr, p); } else { /* Next-Hop-Len */ stream_putc (obuf, IPV4_MAX_BYTELEN); stream_put_in_addr (obuf, &attr->nexthop); stream_putc (obuf, p->prefixlen); plen = PSIZE (p->prefixlen); stream_put (obuf, &p->u.prefix4, plen); bgp_dump_routes_attr (obuf, attr, p); } } #ifdef HAVE_IPV6 else if (afi == AFI_IP6) { if (type == MSG_TABLE_DUMP) { /* Prefix */ stream_write (obuf, (u_char *)&p->u.prefix6, IPV6_MAX_BYTELEN); stream_putc (obuf, p->prefixlen); /* Status */ stream_putc (obuf, 1); /* Originated */ stream_putl (obuf, info->uptime); /* Peer's IP address */ stream_write (obuf, (u_char *)&peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN); /* Peer's AS number. */ stream_putw (obuf, peer->as); /* Dump attribute. */ bgp_dump_routes_attr (obuf, attr, p); } else { ; } } #endif /* HAVE_IPV6 */ /* Set length. */ bgp_dump_set_size (obuf, type); fwrite (STREAM_DATA (obuf), stream_get_putp (obuf), 1, bgp_dump_routes.fp); fflush (bgp_dump_routes.fp); }
static struct bgp_info * bgp_dump_route_node_record (int afi, struct bgp_node *rn, struct bgp_info *info, unsigned int seq) { struct stream *obuf; size_t sizep; size_t endp; obuf = bgp_dump_obuf; stream_reset (obuf); /* MRT header */ if (afi == AFI_IP) bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV4_UNICAST, BGP_DUMP_ROUTES); else if (afi == AFI_IP6) bgp_dump_header (obuf, MSG_TABLE_DUMP_V2, TABLE_DUMP_V2_RIB_IPV6_UNICAST, BGP_DUMP_ROUTES); /* Sequence number */ stream_putl (obuf, seq); /* Prefix length */ stream_putc (obuf, rn->p.prefixlen); /* Prefix */ if (afi == AFI_IP) { /* We'll dump only the useful bits (those not 0), but have to * align on 8 bits */ stream_write (obuf, (u_char *) &rn->p.u.prefix4, (rn->p.prefixlen + 7) / 8); } else if (afi == AFI_IP6) { /* We'll dump only the useful bits (those not 0), but have to * align on 8 bits */ stream_write (obuf, (u_char *) &rn->p.u.prefix6, (rn->p.prefixlen + 7) / 8); } /* Save where we are now, so we can overwride the entry count later */ sizep = stream_get_endp (obuf); /* Entry count */ uint16_t entry_count = 0; /* Entry count, note that this is overwritten later */ stream_putw (obuf, 0); endp = stream_get_endp (obuf); for (; info; info = info->next) { size_t cur_endp; /* Peer index */ stream_putw (obuf, info->peer->table_dump_index); /* Originated */ #ifdef HAVE_CLOCK_MONOTONIC stream_putl (obuf, time (NULL) - (bgp_clock () - info->uptime)); #else stream_putl (obuf, info->uptime); #endif /* HAVE_CLOCK_MONOTONIC */ /* Dump attribute. */ /* Skip prefix & AFI/SAFI for MP_NLRI */ bgp_dump_routes_attr (obuf, info->attr, &rn->p); cur_endp = stream_get_endp (obuf); if (cur_endp > BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER + BGP_DUMP_HEADER_SIZE) { stream_set_endp (obuf, endp); break; } entry_count++; endp = cur_endp; } /* Overwrite the entry count, now that we know the right number */ stream_putw_at (obuf, sizep, entry_count); bgp_dump_set_size (obuf, MSG_TABLE_DUMP_V2); fwrite (STREAM_DATA (obuf), stream_get_endp (obuf), 1, bgp_dump_routes.fp); return info; }