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) { 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); bgp_dump_common (obuf, peer); 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_putp (obuf), 1, bgp_dump_all.fp); fflush (bgp_dump_all.fp); }
/* * The zebra server sends the clients a ZEBRA_IPV4_ROUTE_ADD or a * ZEBRA_IPV6_ROUTE_ADD via zsend_route_multipath in the following * situations: * - when the client starts up, and requests default information * by sending a ZEBRA_REDISTRIBUTE_DEFAULT_ADD to the zebra server, in the * - case of rip, ripngd, ospfd and ospf6d, when the client sends a * ZEBRA_REDISTRIBUTE_ADD as a result of the "redistribute" vty cmd, * - when the zebra server redistributes routes after it updates its rib * * The zebra server sends clients a ZEBRA_IPV4_ROUTE_DELETE or a * ZEBRA_IPV6_ROUTE_DELETE via zsend_route_multipath when: * - a "ip route" or "ipv6 route" vty command is issued, a prefix is * - deleted from zebra's rib, and this info * has to be redistributed to the clients * * XXX The ZEBRA_IPV*_ROUTE_ADD message is also sent by the client to the * zebra server when the client wants to tell the zebra server to add a * route to the kernel (zapi_ipv4_add etc. ). Since it's essentially the * same message being sent back and forth, this function and * zapi_ipv{4,6}_{add, delete} should be re-written to avoid code * duplication. */ int zsend_route_multipath (int cmd, struct zserv *client, struct prefix *p, struct rib *rib) { int psize; struct stream *s; struct nexthop *nexthop; unsigned long nhnummark = 0; int nhnum = 0; u_char zapi_flags = ZAPI_MESSAGE_NEXTHOP | ZAPI_MESSAGE_IFINDEX; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); /* Put command, type and nexthop. */ stream_putc (s, cmd); stream_putc (s, rib->type); stream_putc (s, rib->flags); /* * XXX no need to set ZAPI_MESSAGE_NEXTHOP if we are going to * send empty nexthop? */ if (cmd == ZEBRA_IPV4_ROUTE_ADD || ZEBRA_IPV6_ROUTE_ADD) zapi_flags |= ZAPI_MESSAGE_METRIC; stream_putc (s, zapi_flags); /* Prefix. */ psize = PSIZE (p->prefixlen); stream_putc (s, p->prefixlen); stream_write (s, (u_char *) & p->u.prefix, psize); /* * XXX The message format sent by zebra below does not match the format * of the corresponding message expected by the zebra server * itself (e.g., see zread_ipv4_add). The nexthop_num is not set correctly, * (is there a bug on the client side if more than one segment is sent?) * nexthop ZEBRA_NEXTHOP_IPV4 is never set, ZEBRA_NEXTHOP_IFINDEX * is hard-coded. */ /* Nexthop */ for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) { if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) { nhnummark = stream_get_putp (s); stream_putc (s, 1); /* placeholder */ nhnum++; switch(nexthop->type) { case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: stream_put_in_addr (s, &nexthop->gate.ipv4); break; #ifdef HAVE_IPV6 case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: case NEXTHOP_TYPE_IPV6_IFNAME: stream_write (s, (u_char *) &nexthop->gate.ipv6, 16); break; #endif default: if (cmd == ZEBRA_IPV4_ROUTE_ADD || cmd == ZEBRA_IPV4_ROUTE_DELETE) { struct in_addr empty; memset (&empty, 0, sizeof (struct in_addr)); stream_write (s, (u_char *) &empty, IPV4_MAX_BYTELEN); } else { struct in6_addr empty; memset (&empty, 0, sizeof (struct in6_addr)); stream_write (s, (u_char *) &empty, IPV6_MAX_BYTELEN); } } /* Interface index. */ stream_putc (s, 1); stream_putl (s, nexthop->ifindex); break; } } /* Metric */ stream_putl (s, rib->metric); /* Write next-hop number */ if (nhnummark) stream_putc_at (s, nhnummark, nhnum); /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0; }
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); }
void bgp_dump_set_size (struct stream *s, int type) { stream_putl_at (s, 8, stream_get_putp (s) - BGP_DUMP_HEADER_SIZE); }
/* Fill in capability open option to the packet. */ void bgp_open_capability (struct stream *s, struct peer *peer) { u_char len; unsigned long cp; afi_t afi; safi_t safi; /* Remember current pointer for Opt Parm Len. */ cp = stream_get_putp (s); /* Opt Parm Len. */ stream_putc (s, 0); /* Do not send capability. */ if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN) || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY)) return; /* When the peer is IPv4 unicast only, do not send capability. */ if (! peer->afc[AFI_IP][SAFI_MULTICAST] && ! peer->afc[AFI_IP][SAFI_MPLS_VPN] && ! peer->afc[AFI_IP6][SAFI_UNICAST] && ! peer->afc[AFI_IP6][SAFI_MULTICAST] && CHECK_FLAG (peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP) && ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST], PEER_FLAG_ORF_PREFIX_SM) && ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST], PEER_FLAG_ORF_PREFIX_RM) && ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST], PEER_FLAG_ORF_PREFIX_SM) && ! CHECK_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST], PEER_FLAG_ORF_PREFIX_RM) && ! CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) return; /* IPv4 unicast. */ if (peer->afc[AFI_IP][SAFI_UNICAST]) { peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1; stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); stream_putc (s, CAPABILITY_CODE_MP); stream_putc (s, CAPABILITY_CODE_MP_LEN); stream_putw (s, AFI_IP); stream_putc (s, 0); stream_putc (s, SAFI_UNICAST); } /* IPv4 multicast. */ if (peer->afc[AFI_IP][SAFI_MULTICAST]) { peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1; stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); stream_putc (s, CAPABILITY_CODE_MP); stream_putc (s, CAPABILITY_CODE_MP_LEN); stream_putw (s, AFI_IP); stream_putc (s, 0); stream_putc (s, SAFI_MULTICAST); } /* IPv4 VPN */ if (peer->afc[AFI_IP][SAFI_MPLS_VPN]) { peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1; stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); stream_putc (s, CAPABILITY_CODE_MP); stream_putc (s, CAPABILITY_CODE_MP_LEN); stream_putw (s, AFI_IP); stream_putc (s, 0); stream_putc (s, BGP_SAFI_VPNV4); } #ifdef HAVE_IPV6 /* IPv6 unicast. */ if (peer->afc[AFI_IP6][SAFI_UNICAST]) { peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1; stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); stream_putc (s, CAPABILITY_CODE_MP); stream_putc (s, CAPABILITY_CODE_MP_LEN); stream_putw (s, AFI_IP6); stream_putc (s, 0); stream_putc (s, SAFI_UNICAST); } /* IPv6 multicast. */ if (peer->afc[AFI_IP6][SAFI_MULTICAST]) { peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1; stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); stream_putc (s, CAPABILITY_CODE_MP); stream_putc (s, CAPABILITY_CODE_MP_LEN); stream_putw (s, AFI_IP6); stream_putc (s, 0); stream_putc (s, SAFI_MULTICAST); } #endif /* HAVE_IPV6 */ /* Route refresh. */ if (! CHECK_FLAG (peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP)) { SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV); stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2); stream_putc (s, CAPABILITY_CODE_REFRESH_OLD); stream_putc (s, CAPABILITY_CODE_REFRESH_LEN); stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2); stream_putc (s, CAPABILITY_CODE_REFRESH); stream_putc (s, CAPABILITY_CODE_REFRESH_LEN); } /* ORF capability. */ for (afi = AFI_IP ; afi < AFI_MAX ; afi++) for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++) if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) { bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD); bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF); } /* Dynamic capability. */ if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) { SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV); stream_putc (s, BGP_OPEN_OPT_CAP); stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2); stream_putc (s, CAPABILITY_CODE_DYNAMIC); stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN); } /* Total Opt Parm Len. */ len = stream_get_putp (s) - cp - 1; stream_putc_at (s, cp, len); }
void bgp_open_capability_orf (struct stream *s, struct peer *peer, afi_t afi, safi_t safi, u_char code) { u_char cap_len; u_char orf_len; unsigned long capp; unsigned long orfp; unsigned long numberp; int number_of_orfs = 0; if (safi == SAFI_MPLS_VPN) safi = BGP_SAFI_VPNV4; stream_putc (s, BGP_OPEN_OPT_CAP); capp = stream_get_putp (s); /* Set Capability Len Pointer */ stream_putc (s, 0); /* Capability Length */ stream_putc (s, code); /* Capability Code */ orfp = stream_get_putp (s); /* Set ORF Len Pointer */ stream_putc (s, 0); /* ORF Length */ stream_putw (s, afi); stream_putc (s, 0); stream_putc (s, safi); numberp = stream_get_putp (s); /* Set Number Pointer */ stream_putc (s, 0); /* Number of ORFs */ /* Address Prefix ORF */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) { stream_putc (s, (code == CAPABILITY_CODE_ORF ? ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD)); if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM) && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) { SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV); SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV); stream_putc (s, ORF_MODE_BOTH); } else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)) { SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV); stream_putc (s, ORF_MODE_SEND); } else { SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV); stream_putc (s, ORF_MODE_RECEIVE); } number_of_orfs++; } /* Total Number of ORFs. */ stream_putc_at (s, numberp, number_of_orfs); /* Total ORF Len. */ orf_len = stream_get_putp (s) - orfp - 1; stream_putc_at (s, orfp, orf_len); /* Total Capability Len. */ cap_len = stream_get_putp (s) - capp - 1; stream_putc_at (s, capp, cap_len); }