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); }
/* write RIP-2 hash authentication data trailer */ static void rip_auth_write_trailer (struct stream *s, struct rip_interface *ri, char *auth_str) { unsigned char digest[RIP_AUTH_MAX_SIZE]; unsigned hash_error; if (IS_RIP_DEBUG_AUTH) zlog_debug ("writing authentication trailer after %zuB of main body", stream_get_endp (s)); assert (ri->auth_type == RIP_AUTH_HASH); /* Set authentication data. */ stream_putw (s, RIP_FAMILY_AUTH); stream_putw (s, RIP_AUTH_DATA); /* Generate a digest for the RIP packet and write it to the packet. */ switch (ri->hash_algo) { case HASH_KEYED_MD5: if (IS_RIP_DEBUG_AUTH) zlog_debug ("%s: %zuB of input buffer, %zuB of key", __func__, stream_get_endp (s), strlen (auth_str)); hash_error = hash_make_keyed_md5 ((caddr_t) STREAM_DATA (s), stream_get_endp (s), auth_str, strlen (auth_str), digest); stream_write (s, digest, HASH_SIZE_MD5); break; #ifdef HAVE_LIBGCRYPT case HASH_HMAC_SHA1: case HASH_HMAC_SHA256: case HASH_HMAC_SHA384: case HASH_HMAC_SHA512: { u_int8_t compr_auth_str[RIP_AUTH_MAX_SIZE]; size_t compr_authlen; /* RFC4822 2.5: Fill Apad, process whole packet with HMAC rounds. */ size_t saved_endp = stream_get_endp (s); hash_key_compress_rfc4822 (ri->hash_algo, auth_str, strlen (auth_str), compr_auth_str, &compr_authlen); stream_write (s, hash_apad_sha512, hash_digest_length[ri->hash_algo]); if (IS_RIP_DEBUG_AUTH) zlog_debug ("%s: %zuB of input buffer, %zuB of key (%zuB compressed)", __func__, stream_get_endp (s), strlen (auth_str), compr_authlen); hash_error = hash_make_hmac (ri->hash_algo, STREAM_DATA (s), stream_get_endp (s), compr_auth_str, compr_authlen, STREAM_DATA (s) + saved_endp); break; } #endif /* HAVE_LIBGCRYPT */ default: assert (0); } if (hash_error) if (IS_RIP_DEBUG_AUTH) zlog_debug ("hash function returned error %u", hash_error); }
/* 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); }
static int zebra_server_send_message(struct zserv *client) { if (client->t_suicide) return -1; switch (buffer_write(client->wb, client->sock, STREAM_DATA(client->obuf), stream_get_endp(client->obuf))) { case BUFFER_ERROR: zlog_warn("%s: buffer_write failed to zserv client fd %d, closing", __func__, client->sock); /* Schedule a delayed close since many of the functions that call this one do not check the return code. They do not allow for the possibility that an I/O error may have caused the client to be deleted. */ client->t_suicide = thread_add_event(zebrad.master, zserv_delayed_close, client, 0); return -1; case BUFFER_EMPTY: THREAD_OFF(client->t_write); break; case BUFFER_PENDING: THREAD_WRITE_ON(zebrad.master, client->t_write, zserv_flush_data, client, client->sock); break; } return 0; }
/* 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); }
int authenticate_pdu(struct isis_passwd *external,struct isis_passwd *local,struct stream *stream, uint32_t auth_tlv_offset) { unsigned char digest[ISIS_AUTH_MD5_SIZE]; if(local->type != external->type) return ISIS_ERROR; switch(local->type) { case ISIS_PASSWD_TYPE_UNUSED: //do the respective operation break; case ISIS_PASSWD_TYPE_CLEARTXT: //do the respective operation break; case ISIS_PASSWD_TYPE_HMAC_MD5: if(external->len != ISIS_AUTH_MD5_SIZE) return ISIS_ERROR; memset(STREAM_DATA (stream)+auth_tlv_offset+3, 0, ISIS_AUTH_MD5_SIZE); hmac_md5(STREAM_DATA(stream),stream_get_endp(stream), (unsigned char*)&(local->passwd), local->len, (caddr_t)&digest); memcpy(STREAM_DATA (stream)+auth_tlv_offset+3, external->passwd,ISIS_AUTH_MD5_SIZE); return memcmp(digest,external->passwd,ISIS_AUTH_MD5_SIZE); case ISIS_PASSWD_TYPE_PRIVATE: //do the operation break; default: zlog_err("Authentication type is unrecognized."); return ISIS_ERROR; } /*If authentication is not enabled pass the PDU*/ return ISIS_OK; }
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); }
int shim_sisis_write (struct stream * obuf, struct buffer * wb) { struct listnode * node, * nnode; struct sisis_listener * listener; printf("num of listeners %d\n", listcount(sm->listen_sockets)); for(ALL_LIST_ELEMENTS (sm->listen_sockets, node, nnode, listener)) { printf("listener fd: %d\n", listener->sisis_fd); buffer_write(wb, listener->sisis_fd, STREAM_DATA(obuf), stream_get_endp(obuf)); } return 0; }
int svz_tunnel_send_message (struct tclient * tclient) { if (tclient->sock < 0) return -1; switch(buffer_write(tclient->wb, tclient->sock, STREAM_DATA(tclient->obuf) + stream_get_getp(tclient->obuf), stream_get_endp(tclient->obuf) - stream_get_getp(tclient->obuf))) { case BUFFER_ERROR: zlog_warn("%s: buffer_write failed to tclient fd %d, closing", __func__, tclient->sock); return svz_tunnel_failed(tclient); case BUFFER_EMPTY: THREAD_OFF(tclient->t_write); break; case BUFFER_PENDING: THREAD_WRITE_ON(master, tclient->t_write, svz_tunnel_flush_data, tclient, tclient->sock); break; } return 0; }
int zclient_send_message(struct zclient *zclient) { if (zclient->sock < 0) return -1; switch (buffer_write(zclient->wb, zclient->sock, STREAM_DATA(zclient->obuf), stream_get_endp(zclient->obuf))) { case BUFFER_ERROR: zlog_warn("%s: buffer_write failed to zclient fd %d, closing", __func__, zclient->sock); return zclient_failed(zclient); break; case BUFFER_EMPTY: THREAD_OFF(zclient->t_write); break; case BUFFER_PENDING: THREAD_WRITE_ON(master, zclient->t_write, zclient_flush_data, zclient, zclient->sock); break; } return 0; }
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; }
/* 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); }
/* validate the given aspath */ static int validate (struct aspath *as, const struct test_spec *sp) { size_t bytes, bytes4; int fails = 0; const u_char *out; static struct stream *s; struct aspath *asinout, *asconfeddel, *asstr, *as4; out = aspath_snmp_pathseg (as, &bytes); asinout = make_aspath (out, bytes, 0); /* Excercise AS4 parsing a bit, with a dogfood test */ if (!s) s = stream_new (4096); bytes4 = aspath_put (s, as, 1); as4 = make_aspath (STREAM_DATA(s), bytes4, 1); asstr = aspath_str2aspath (sp->shouldbe); asconfeddel = aspath_delete_confed_seq (aspath_dup (asinout)); printf ("got: %s\n", aspath_print(as)); /* the parsed path should match the specified 'shouldbe' string. * We should pass the "eat our own dog food" test, be able to output * this path and then input it again. Ie the path resulting from: * * aspath_parse(aspath_put(as)) * * should: * * - also match the specified 'shouldbe' value * - hash to same value as original path * - have same hops and confed counts as original, and as the * the specified counts * * aspath_str2aspath() and shouldbe should match * * We do the same for: * * aspath_parse(aspath_put(as,USE32BIT)) * * Confederation related tests: * - aspath_delete_confed_seq(aspath) should match shouldbe_confed * - aspath_delete_confed_seq should be idempotent. */ if (strcmp(aspath_print (as), sp->shouldbe) /* hash validation */ || (aspath_key_make (as) != aspath_key_make (asinout)) /* by string */ || strcmp(aspath_print (asinout), sp->shouldbe) /* By 4-byte parsing */ || strcmp(aspath_print (as4), sp->shouldbe) /* by various path counts */ || (aspath_count_hops (as) != sp->hops) || (aspath_count_confeds (as) != sp->confeds) || (aspath_count_hops (asinout) != sp->hops) || (aspath_count_confeds (asinout) != sp->confeds)) { failed++; fails++; printf ("shouldbe:\n%s\n", sp->shouldbe); printf ("as4:\n%s\n", aspath_print (as4)); printf ("hash keys: in: %d out->in: %d\n", aspath_key_make (as), aspath_key_make (asinout)); printf ("hops: %d, counted %d %d\n", sp->hops, aspath_count_hops (as), aspath_count_hops (asinout) ); printf ("confeds: %d, counted %d %d\n", sp->confeds, aspath_count_confeds (as), aspath_count_confeds (asinout)); printf ("out->in:\n%s\nbytes: ", aspath_print(asinout)); printbytes (out, bytes); } /* basic confed related tests */ if ((aspath_print (asconfeddel) == NULL && sp->shouldbe_delete_confed != NULL) || (aspath_print (asconfeddel) != NULL && sp->shouldbe_delete_confed == NULL) || strcmp(aspath_print (asconfeddel), sp->shouldbe_delete_confed) /* delete_confed_seq should be idempotent */ || (aspath_key_make (asconfeddel) != aspath_key_make (aspath_delete_confed_seq (asconfeddel)))) { failed++; fails++; printf ("confed_del: %s\n", aspath_print (asconfeddel)); printf ("should be: %s\n", sp->shouldbe_delete_confed); } /* aspath_str2aspath test */ if ((aspath_print (asstr) == NULL && sp->shouldbe != NULL) || (aspath_print (asstr) != NULL && sp->shouldbe == NULL) || strcmp(aspath_print (asstr), sp->shouldbe)) { failed++; fails++; printf ("asstr: %s\n", aspath_print (asstr)); } /* loop, private and first as checks */ if ((sp->does_loop && aspath_loop_check (as, sp->does_loop) == 0) || (sp->doesnt_loop && aspath_loop_check (as, sp->doesnt_loop) != 0) || (aspath_private_as_check (as) != sp->private_as) || (aspath_firstas_check (as,sp->first) && sp->first == 0)) { failed++; fails++; printf ("firstas: %d, got %d\n", sp->first, aspath_firstas_check (as,sp->first)); printf ("loop does: %d %d, doesnt: %d %d\n", sp->does_loop, aspath_loop_check (as, sp->does_loop), sp->doesnt_loop, aspath_loop_check (as, sp->doesnt_loop)); printf ("private check: %d %d\n", sp->private_as, aspath_private_as_check (as)); } aspath_unintern (asinout); aspath_unintern (as4); aspath_free (asconfeddel); aspath_free (asstr); stream_reset (s); return fails; }
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); }
/* Take a sequence of payload (routing) RTE structures, decide on particular * authentication required for the given interface and build a complete RIP * packet in a stream structure. The packet will consist of header, optional * heading RTE, the payload RTEs and optional trailing data. Return the stream. */ int rip_auth_make_packet ( struct rip_interface * ri, struct stream * packet, struct stream * rtes, const u_int8_t version, const u_int8_t command ) { struct key *key = NULL; char *auth_str = NULL; if (IS_RIP_DEBUG_AUTH) zlog_debug ("interface auth type is '%s', inet RTEs payload size is %zuB", LOOKUP (rip_ffff_type_str, ri->auth_type), stream_get_endp (rtes)); /* packet header, unconditional */ stream_reset (packet); stream_putc (packet, command); stream_putc (packet, version); stream_putw (packet, 0); /* authentication leading RTE, conditional */ if (version == RIPv2 && ri->auth_type != RIP_NO_AUTH) { if (ri->key_chain) { struct keychain *keychain; keychain = keychain_lookup (ri->key_chain); if (keychain) { if (IS_RIP_DEBUG_AUTH) zlog_debug ("trying configured key chain '%s'", ri->key_chain); key = key_lookup_for_send (keychain); } else { if (IS_RIP_DEBUG_AUTH) zlog_debug ("key chain '%s' is configured, but does not exist", ri->key_chain); } } /* Pick correct auth string for sends, prepare auth_str buffer for use. * (left justified and padded). * * presumes one of ri or key is valid, and that the auth strings they point * to are nul terminated. If neither are present, auth_str will be fully * zero padded. * */ if (key && key->string) { if (IS_RIP_DEBUG_AUTH) zlog_debug ("using keychain '%s', key %u for sending", ri->key_chain, key->index); auth_str = key->string; } else if (ri->auth_str) { if (IS_RIP_DEBUG_AUTH) zlog_debug ("using interface authentication string"); auth_str = ri->auth_str; } if (auth_str == NULL) { if (IS_RIP_DEBUG_AUTH) zlog_debug ("authentication string lookup failed"); return -1; } rip_auth_write_leading_rte (packet, ri, key ? key->index % 256 : 1, auth_str, RIP_HEADER_SIZE + RIP_RTE_SIZE + stream_get_endp (rtes)); } /* RTEs payload, unconditional */ if (stream_get_endp (rtes) % RIP_RTE_SIZE) { zlog_err ("%s: malformed input RTE buffer", __func__); return -1; } stream_write (packet, STREAM_DATA (rtes), stream_get_endp (rtes)); stream_reset (rtes); /* authentication trailing data, even more conditional */ if (version == RIPv2 && ri->auth_type == RIP_AUTH_HASH) rip_auth_write_trailer (packet, ri, auth_str); return 0; }
void bgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp, safi_t safi) { int flags; u_char distance; struct peer *peer; struct bgp_info *mpinfo; size_t oldsize, newsize; if (zclient->sock < 0) return; if (! zclient->redist[ZEBRA_ROUTE_BGP]) return; flags = 0; peer = info->peer; if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) { SET_FLAG (flags, ZEBRA_FLAG_IBGP); SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); } if ((peer->sort == BGP_PEER_EBGP && peer->ttl != 1) || CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); /* resize nexthop buffer size if necessary */ if ((oldsize = stream_get_size (bgp_nexthop_buf)) < (sizeof (struct in_addr *) * (bgp_info_mpath_count (info) + 1))) { newsize = (sizeof (struct in_addr *) * (bgp_info_mpath_count (info) + 1)); newsize = stream_resize (bgp_nexthop_buf, newsize); if (newsize == oldsize) { zlog_err ("can't resize nexthop buffer"); return; } } stream_reset (bgp_nexthop_buf); if (p->family == AF_INET) { struct zapi_ipv4 api; struct in_addr *nexthop; api.flags = flags; nexthop = &info->attr->nexthop; stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); for (mpinfo = bgp_info_mpath_first (info); mpinfo; mpinfo = bgp_info_mpath_next (mpinfo)) { nexthop = &mpinfo->attr->nexthop; stream_put (bgp_nexthop_buf, &nexthop, sizeof (struct in_addr *)); } api.type = ZEBRA_ROUTE_BGP; api.message = 0; api.safi = safi; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1 + bgp_info_mpath_count (info); api.nexthop = (struct in_addr **)STREAM_DATA (bgp_nexthop_buf); api.ifindex_num = 0; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; distance = bgp_distance_apply (p, info, bgp); if (distance) { SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); api.distance = distance; } if (BGP_DEBUG(zebra, ZEBRA)) { int i; char buf[2][INET_ADDRSTRLEN]; zlog_debug("Zebra send: IPv4 route add %s/%d nexthop %s metric %u" " count %d", inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), p->prefixlen, inet_ntop(AF_INET, api.nexthop[0], buf[1], sizeof(buf[1])), api.metric, api.nexthop_num); for (i = 1; i < api.nexthop_num; i++) zlog_debug("Zebra send: IPv4 route add [nexthop %d] %s", i, inet_ntop(AF_INET, api.nexthop[i], buf[1], sizeof(buf[1]))); } zapi_ipv4_route (ZEBRA_IPV4_ROUTE_ADD, zclient, (struct prefix_ipv4 *) p, &api); } #ifdef HAVE_IPV6 /* We have to think about a IPv6 link-local address curse. */ if (p->family == AF_INET6) { unsigned int ifindex; struct in6_addr *nexthop; struct zapi_ipv6 api; ifindex = 0; nexthop = NULL; assert (info->attr->extra); /* Only global address nexthop exists. */ if (info->attr->extra->mp_nexthop_len == 16) nexthop = &info->attr->extra->mp_nexthop_global; /* If both global and link-local address present. */ if (info->attr->extra->mp_nexthop_len == 32) { /* Workaround for Cisco's nexthop bug. */ if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->extra->mp_nexthop_global) && peer->su_remote->sa.sa_family == AF_INET6) nexthop = &peer->su_remote->sin6.sin6_addr; else nexthop = &info->attr->extra->mp_nexthop_local; if (info->peer->nexthop.ifp) ifindex = info->peer->nexthop.ifp->ifindex; } if (nexthop == NULL) return; if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex) { if (info->peer->ifname) ifindex = if_nametoindex (info->peer->ifname); else if (info->peer->nexthop.ifp) ifindex = info->peer->nexthop.ifp->ifindex; } /* Make Zebra API structure. */ api.flags = flags; api.type = ZEBRA_ROUTE_BGP; api.message = 0; api.safi = safi; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; api.nexthop = &nexthop; SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); api.ifindex_num = 1; api.ifindex = &ifindex; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][INET6_ADDRSTRLEN]; zlog_debug("Zebra send: IPv6 route add %s/%d nexthop %s metric %u", inet_ntop(AF_INET6, &p->u.prefix6, buf[0], sizeof(buf[0])), p->prefixlen, inet_ntop(AF_INET6, nexthop, buf[1], sizeof(buf[1])), api.metric); } zapi_ipv6_route (ZEBRA_IPV6_ROUTE_ADD, zclient, (struct prefix_ipv6 *) p, &api); } #endif /* HAVE_IPV6 */ }