static int mcp_ppp_all_config_syn_parse_update(struct stream *data_s) { int type; int len; struct stream* tmp_s; tmp_s = stream_new(10240); while(STREAM_READABLE(data_s) >= 4) { type = stream_getw(data_s); len = stream_getw(data_s); //zlog_debug("<%s,%d> type:%d len:%d", __FUNCTION__, __LINE__, type, len); if(len == 0) continue; switch(type) { case MCP_PPPD_CONFIG_SYN_REMOT_USERINFO: stream_put(tmp_s, data_s->data + stream_get_getp(data_s), len); mcp_recv_pppd_remote_userinfo_ack(tmp_s); stream_forward_getp(data_s, len); stream_reset(tmp_s); break; case MCP_PPPD_CONFIG_SYN_MULTILINK_INFO: stream_put(tmp_s, data_s->data + stream_get_getp(data_s), len); mcp_recv_pppd_multilink_info_ack(tmp_s); stream_forward_getp(data_s, len); stream_reset(tmp_s); break; case MCP_PPPD_CONFIG_SYN_INTERFACE_INFO: stream_put(tmp_s, data_s->data + stream_get_getp(data_s), len); mcp_recv_pppd_interface_info_ack(tmp_s, 1); stream_forward_getp(data_s, len); stream_reset(tmp_s); break; default: zlog_err("mcp<%s:%d> wrong type:%u",__FUNCTION__,__LINE__,type); goto error; } } stream_free(tmp_s); return 0; error: stream_free(tmp_s); return -1; }
/* Interface address is added/deleted. Send ZEBRA_INTERFACE_ADDRESS_ADD or * ZEBRA_INTERFACE_ADDRESS_DELETE to the client. * * A ZEBRA_INTERFACE_ADDRESS_ADD is sent in the following situations: * - in response to a 3-byte ZEBRA_INTERFACE_ADD request * from the client, after the ZEBRA_INTERFACE_ADD has been * sent from zebra to the client * - redistribute new address info to all clients in the following situations * - at startup, when zebra figures out the available interfaces * - when an interface is added (where support for * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is * received) * - for the vty commands "ip address A.B.C.D/M [<secondary>|<label LINE>]" * and "no bandwidth <1-10000000>", "ipv6 address X:X::X:X/M" * - when an RTM_NEWADDR message is received from the kernel, * * The call tree that triggers ZEBRA_INTERFACE_ADDRESS_DELETE: * * zsend_interface_address(DELETE) * ^ * | * zebra_interface_address_delete_update * ^ ^ ^ * | | if_delete_update (not called on * | | Solaris) * ip_address_uninstall connected_delete_ipv4 * [ipv6_addresss_uninstall] [connected_delete_ipv6] * ^ ^ * | | * | RTM_NEWADDR on routing/netlink socket * | * vty commands: * "no ip address A.B.C.D/M [label LINE]" * "no ip address A.B.C.D/M secondary" * ["no ipv6 address X:X::X:X/M"] * */ int zsend_interface_address (int cmd, struct zserv *client, struct interface *ifp, struct connected *ifc) { int blen; struct stream *s; struct prefix *p; /* Check this client need interface information. */ if (! client->ifinfo) return -1; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); stream_putc (s, cmd); stream_putl (s, ifp->ifindex); /* Interface address flag. */ stream_putc (s, ifc->flags); /* Prefix information. */ p = ifc->address; stream_putc (s, p->family); blen = prefix_blen (p); stream_put (s, &p->u.prefix, blen); /* * XXX gnu version does not send prefixlen for ZEBRA_INTERFACE_ADDRESS_DELETE * but zebra_interface_address_delete_read() in the gnu version * expects to find it */ stream_putc (s, p->prefixlen); /* Destination. */ p = ifc->destination; if (p) stream_put (s, &p->u.prefix, blen); else stream_put (s, NULL, blen); /* 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 token_print(stream_t *s, tok_state_t *state) { char buf[17]; switch(state->type) { case TOK_SYM: stream_put(s, "TOK_SYM(", state->u.sym, ")\n", NULL); break; case TOK_LIT: stream_put(s, "TOK_LIT(0x", fmt_u64(buf, state->u.lit), ")\n", NULL); break; default: stream_put(s, token_type_names[state->type], "\n", NULL); break; } }
/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */ int zsend_router_id_update (struct zserv *client, struct prefix *p) { struct stream *s; int blen; /* Check this client need interface information. */ if (!client->ridinfo) return 0; s = client->obuf; stream_reset (s); /* Message type. */ zserv_create_header (s, ZEBRA_ROUTER_ID_UPDATE); /* Prefix information. */ stream_putc (s, p->family); blen = prefix_blen (p); stream_put (s, &p->u.prefix, blen); stream_putc (s, p->prefixlen); /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); return zebra_server_send_message(client); }
/* * The cmd passed to zsend_interface_update may be ZEBRA_INTERFACE_UP or * ZEBRA_INTERFACE_DOWN. * * The ZEBRA_INTERFACE_UP message is sent from the zebra server to * the clients in one of 2 situations: * - an if_up is detected e.g., as a result of an RTM_IFINFO message * - a vty command modifying the bandwidth of an interface is received. * The ZEBRA_INTERFACE_DOWN message is sent when an if_down is detected. */ int zsend_interface_update (int cmd, struct zserv *client, struct interface_FOO *ifp) { struct stream *s; /* Check this client need interface information. */ if (! client->ifinfo) return 0; s = client->obuf; stream_reset (s); zserv_create_header (s, cmd); /* Interface information. */ stream_put (s, ifp->name, INTERFACE_NAMSIZ); stream_putl (s, ifp->ifindex); stream_putc (s, ifp->status); stream_putq (s, ifp->flags); stream_putl (s, ifp->metric); stream_putl (s, ifp->mtu); stream_putl (s, ifp->mtu6); stream_putl (s, ifp->bandwidth); /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); return zebra_server_send_message(client); }
/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */ int zsend_router_id_update (struct zserv *client, struct prefix *p) { struct stream *s; int blen; /* Check this client need interface information. */ if (!client->ridinfo) return -1; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); /* Message type. */ stream_putc (s, ZEBRA_ROUTER_ID_UPDATE); /* Prefix information. */ stream_putc (s, p->family); blen = prefix_blen (p); stream_put (s, &p->u.prefix, blen); stream_putc (s, p->prefixlen); /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); return writen (client->sock, s->data, stream_get_endp (s)); }
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); }
struct bgp_nexthop_cache * zlookup_query_ipv6 (struct in6_addr *addr) { int ret; struct stream *s; /* Check socket. */ if (zlookup->sock < 0) return NULL; s = zlookup->obuf; stream_reset (s); zclient_create_header (s, ZEBRA_IPV6_NEXTHOP_LOOKUP); stream_put (s, addr, 16); stream_putw_at (s, 0, stream_get_endp (s)); ret = writen (zlookup->sock, s->data, stream_get_endp (s)); if (ret < 0) { zlog_err ("can't write to zlookup->sock"); close (zlookup->sock); zlookup->sock = -1; return NULL; } if (ret == 0) { zlog_err ("zlookup->sock connection closed"); close (zlookup->sock); zlookup->sock = -1; return NULL; } return zlookup_read_ipv6 (); }
/* * The cmd passed to zsend_interface_update may be ZEBRA_INTERFACE_UP or * ZEBRA_INTERFACE_DOWN. * * The ZEBRA_INTERFACE_UP message is sent from the zebra server to * the clients in one of 2 situations: * - an if_up is detected e.g., as a result of an RTM_IFINFO message * - a vty command modifying the bandwidth of an interface is received. * The ZEBRA_INTERFACE_DOWN message is sent when an if_down is detected. */ int zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp) { struct stream *s; /* Check this client need interface information. */ if (! client->ifinfo) return -1; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); /* Zebra command. */ stream_putc (s, cmd); /* Interface information. */ stream_put (s, ifp->name, INTERFACE_NAMSIZ); stream_putl (s, ifp->ifindex); stream_putc (s, ifp->status); stream_putl (s, ifp->flags); stream_putl (s, ifp->metric); stream_putl (s, ifp->mtu); stream_putl (s, ifp->mtu6); stream_putl (s, ifp->bandwidth); /* 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; }
int zsend_interface_delete (struct zserv *client, struct interface *ifp) { struct stream *s; /* Check this client need interface information. */ if (! client->ifinfo) return -1; s = client->obuf; stream_reset (s); /* Packet length placeholder. */ stream_putw (s, 0); /* Interface information. */ stream_putc (s, ZEBRA_INTERFACE_DELETE); stream_put (s, ifp->name, INTERFACE_NAMSIZ); stream_putl (s, ifp->ifindex); stream_putc (s, ifp->status); stream_putl (s, ifp->flags); stream_putl (s, ifp->metric); stream_putl (s, ifp->mtu); stream_putl (s, ifp->mtu6); stream_putl (s, ifp->bandwidth); /* Write packet length. */ stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0; }
static void rip_auth_write_leading_rte ( struct stream *s, struct rip_interface *ri, const u_int8_t key_id, char *auth_str, u_int16_t main_body_len ) { u_int8_t dlen; if (IS_RIP_DEBUG_AUTH) zlog_debug ("writing authentication header for %uB of main body", main_body_len); stream_putw (s, RIP_FAMILY_AUTH); switch (ri->auth_type) { case RIP_AUTH_SIMPLE_PASSWORD: { u_int8_t padded_simple_password[RIP_AUTH_SIMPLE_SIZE] = { 0 }; memcpy (padded_simple_password, auth_str, MIN (RIP_AUTH_SIMPLE_SIZE, strlen (auth_str))); stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD); stream_put (s, padded_simple_password, RIP_AUTH_SIMPLE_SIZE); break; } case RIP_AUTH_HASH: if (IS_RIP_DEBUG_AUTH) zlog_debug ("hash algorithm is '%s'", LOOKUP (hash_algo_str, ri->hash_algo)); stream_putw (s, RIP_AUTH_HASH); stream_putw (s, main_body_len); stream_putc (s, key_id); switch (ri->hash_algo) { case HASH_KEYED_MD5: /* Auth Data Len. Set 16 for MD5 authentication data. Older ripds * however expect RIP_HEADER_SIZE + HASH_SIZE_MD5 so we allow for this * to be configurable. */ dlen = ri->md5_auth_len; break; case HASH_HMAC_SHA1: case HASH_HMAC_SHA256: case HASH_HMAC_SHA384: case HASH_HMAC_SHA512: dlen = hash_digest_length[ri->hash_algo]; break; default: assert (0); } if (IS_RIP_DEBUG_AUTH) zlog_debug ("declared auth data length is %uB", dlen); stream_putc (s, dlen); stream_putl (s, time (NULL)); /* Sequence Number (non-decreasing). */ stream_putl (s, 0); /* reserved, MBZ */ stream_putl (s, 0); /* reserved, MBZ */ break; default: assert (0); } }
/* * This function is called in the following situations: * - in response to a 3-byte ZEBRA_INTERFACE_ADD request * from the client. * - at startup, when zebra figures out the available interfaces * - when an interface is added (where support for * RTM_IFANNOUNCE or AF_NETLINK sockets is available), or when * an interface is marked IFF_UP (i.e., an RTM_IFINFO message is * received) */ int zsend_interface_add (struct zserv *client, struct interface *ifp) { struct stream *s; /* Check this client need interface information. */ if (! client->ifinfo) return -1; s = client->obuf; stream_reset (s); /* Place holder for size. */ stream_putw (s, 0); /* Message type. */ stream_putc (s, ZEBRA_INTERFACE_ADD); /* Interface information. */ stream_put (s, ifp->name, INTERFACE_NAMSIZ); stream_putl (s, ifp->ifindex); stream_putc (s, ifp->status); stream_putl (s, ifp->flags); stream_putl (s, ifp->metric); stream_putl (s, ifp->mtu); stream_putl (s, ifp->mtu6); stream_putl (s, ifp->bandwidth); #ifdef HAVE_SOCKADDR_DL stream_put (s, &ifp->sdl, sizeof (ifp->sdl)); #else stream_putl (s, ifp->hw_addr_len); if (ifp->hw_addr_len) stream_put (s, ifp->hw_addr, ifp->hw_addr_len); #endif /* HAVE_SOCKADDR_DL */ /* 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; }
PUBLIC sw_t cmd_read_binary_b0__from_current_EF(const CmdAPDU *apdu) { u8 i; if (apdu->Lc) return 0x0001; if (!apdu->Le) return 0x0001; /* ACK */ stream_put(current->response, apdu->header->INS); /* for each block */ for (i = 1; i <= apdu->Le; i++) { stream_put(current->response, i); } return SW__OK; }
/* basic parsing test */ static void parse_test (struct peer *peer, struct test_segment *t, int type) { int ret; int oldfailed = failed; struct attr attr; struct bgp_nlri nlri; #define RANDOM_FUZZ 35 stream_reset (peer->ibuf); stream_put (peer->ibuf, NULL, RANDOM_FUZZ); stream_set_getp (peer->ibuf, RANDOM_FUZZ); stream_write (peer->ibuf, t->data, t->len); printf ("%s: %s\n", t->name, t->desc); if (type == BGP_ATTR_MP_REACH_NLRI) ret = bgp_mp_reach_parse (peer, t->len, &attr, BGP_ATTR_FLAG_OPTIONAL, BGP_INPUT_PNT (peer), &nlri); else ret = bgp_mp_unreach_parse (peer, t->len, BGP_ATTR_FLAG_OPTIONAL, BGP_INPUT_PNT (peer), &nlri); if (!ret) { safi_t safi = t->safi; if (bgp_afi_safi_valid_indices (t->afi, &safi) != t->afi_valid) failed++; printf ("MP: %u/%u (%u): recv %u, nego %u\n", t->afi, t->safi, safi, peer->afc_recv[t->afi][safi], peer->afc_nego[t->afi][safi]); } printf ("parsed?: %s\n", ret ? "no" : "yes"); if (ret != t->parses) failed++; if (tty) printf ("%s", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET : VT100_GREEN "OK" VT100_RESET); else printf ("%s", (failed > oldfailed) ? "failed!" : "OK" ); if (failed) printf (" (%u)", failed); printf ("\n\n"); }
static void zserv_encode_interface (struct stream *s, struct interface *ifp) { /* Interface information. */ stream_put (s, ifp->name, INTERFACE_NAMSIZ); stream_putl (s, ifp->ifindex); stream_putc (s, ifp->status); stream_putq (s, ifp->flags); stream_putl (s, ifp->metric); stream_putl (s, ifp->mtu); stream_putl (s, ifp->mtu6); stream_putl (s, ifp->bandwidth); #ifdef HAVE_STRUCT_SOCKADDR_DL stream_put (s, &ifp->sdl, sizeof (ifp->sdl_storage)); #else stream_putl (s, ifp->hw_addr_len); if (ifp->hw_addr_len) stream_put (s, ifp->hw_addr, ifp->hw_addr_len); #endif /* HAVE_STRUCT_SOCKADDR_DL */ /* Write packet size. */ stream_putw_at (s, 0, stream_get_endp (s)); }
void logon () { int len; char *sn = PARAM_SCREEN_NAME; char *pass; char login[11]; stream_t stream; u_int16_t streamid = htons(0x16); log (LOG_NOTICE, _("Loging into provider as '%s'\n"), sn); get_password (sn, &pass); len = strlen (sn); if (len < 10) { strncpy (login, sn, len); memset (&login[len], ' ', 10 - len); sn = login; sn[10]=0; } stream_init(&stream); stream_put(&stream, sizeof(streamid), &streamid); add_atom(&stream, UNI_PID, UNI_START_STREAM, 0); add_atom(&stream, MAN_PID, MAN_SET_CONTEXT_RELATIVE, 1); add_atom(&stream, MAN_PID, MAN_SET_CONTEXT_INDEX, 5); add_atom(&stream, DE_PID , DE_DATA, sn); add_atom(&stream, MAN_PID, MAN_END_CONTEXT, 0); add_atom(&stream, MAN_PID, MAN_END_CONTEXT, 0); add_atom(&stream, MAN_PID, MAN_SET_CONTEXT_RELATIVE, 2); add_atom(&stream, DE_PID , DE_DATA, pass); add_atom(&stream, MAN_PID, MAN_END_CONTEXT, 0); add_atom(&stream, MAN_PID, MAN_SET_CONTEXT_RELATIVE, 16); add_atom(&stream, MAN_PID, MAN_SET_CONTEXT_INDEX, 1); add_atom(&stream, MAN_PID, MAN_END_CONTEXT, 0); add_atom(&stream, MAN_PID, MAN_END_CONTEXT, 0); add_atom(&stream, UNI_PID, UNI_END_STREAM, 0); fdo_send (TOKEN ("Dd"), stream.data, stream.used); stream_destroy(&stream); fdo_unregister (TOKEN ("SD")); fdo_register (TOKEN ("At"), login_confirm); fdo_register (TOKEN ("AT"), atom_handler); fdo_register (TOKEN ("at"), atom_handler); }
/* Main thread */ void usb_thread (void) { for (;;) { bcond_wait(&usb_active); t_yield(); int16_t c; while ((c = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface)) > 0) stream_put(&cdc_instr, c); t_yield(); while ( ! stream_empty(&cdc_outstr)) CDC_Device_SendByte(&VirtualSerial_CDC_Interface, stream_get(&cdc_outstr)); CDC_Device_USBTask(&VirtualSerial_CDC_Interface); USB_USBTask(); } }
/* make an aspath from a data stream */ static struct aspath * make_aspath (const u_char *data, size_t len, int use32bit) { struct stream *s = NULL; struct aspath *as; if (len) { s = stream_new (len); stream_put (s, data, len); } as = aspath_parse (s, len, use32bit); if (s) stream_free (s); return as; }
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); }
/* Dump common information. */ static void bgp_dump_common (struct stream *obuf, struct peer *peer, int forceas4) { char empty[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Source AS number and Destination AS number. */ if (forceas4 || CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) ) { stream_putl (obuf, peer->as); stream_putl (obuf, peer->local_as); } else { stream_putw (obuf, peer->as); stream_putw (obuf, peer->local_as); } if (peer->su.sa.sa_family == AF_INET) { stream_putw (obuf, peer->ifindex); stream_putw (obuf, AFI_IP); stream_put (obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN); if (peer->su_local) stream_put (obuf, &peer->su_local->sin.sin_addr, IPV4_MAX_BYTELEN); else stream_put (obuf, empty, IPV4_MAX_BYTELEN); } #ifdef HAVE_IPV6 else if (peer->su.sa.sa_family == AF_INET6) { /* Interface Index and Address family. */ stream_putw (obuf, peer->ifindex); stream_putw (obuf, AFI_IP6); /* Source IP Address and Destination IP Address. */ stream_put (obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN); if (peer->su_local) stream_put (obuf, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN); else stream_put (obuf, empty, IPV6_MAX_BYTELEN); } #endif /* HAVE_IPV6 */ }
void remark_bundle_notify_mcp(unsigned int ifnum, unsigned int ifunit) { struct remark_bundle bundleinfo; struct ppp_mcp_sock *peer; struct stream* s_new; return; peer = g_ppp_mcp_sock; bundleinfo.master = ifnum; bundleinfo.slave = ifunit; s_new = stream_new(1024); stream_putl(s_new, 4 + sizeof(struct remark_bundle)); ppp_put_control_to_stream(s_new, REMARK_BUDLE_CMD); stream_put(s_new, (unsigned char*)(&bundleinfo), sizeof(struct remark_bundle)); stream_fifo_push (peer->obuf, s_new); MCP_WRITE_ON (peer->t_write, ppp_tcp_write, peer, peer->fd); // MCP_TIMER_ON (peer->t_wait_bundle_ack, ppp_tcp_wait_notify_ack_timer, peer, CLIENT_WAIT_IPINFO_ACK_TIMER); return; }
void zebra_ipmr_route_stats(ZAPI_HANDLER_ARGS) { struct mcast_route_data mroute; struct stream *s; int suc = -1; memset(&mroute, 0, sizeof(mroute)); STREAM_GET(&mroute.sg.src, msg, 4); STREAM_GET(&mroute.sg.grp, msg, 4); STREAM_GETL(msg, mroute.ifindex); if (IS_ZEBRA_DEBUG_KERNEL) { char sbuf[40]; char gbuf[40]; strlcpy(sbuf, inet_ntoa(mroute.sg.src), sizeof(sbuf)); strlcpy(gbuf, inet_ntoa(mroute.sg.grp), sizeof(gbuf)); zlog_debug("Asking for (%s,%s) mroute information", sbuf, gbuf); } suc = kernel_get_ipmr_sg_stats(zvrf, &mroute); stream_failure: s = stream_new(ZEBRA_MAX_PACKET_SIZ); stream_reset(s); zclient_create_header(s, ZEBRA_IPMR_ROUTE_STATS, zvrf_id(zvrf)); stream_put_in_addr(s, &mroute.sg.src); stream_put_in_addr(s, &mroute.sg.grp); stream_put(s, &mroute.lastused, sizeof(mroute.lastused)); stream_putl(s, suc); stream_putw_at(s, 0, stream_get_endp(s)); zserv_send_message(client, s); }
/* Dump common information. */ void bgp_dump_common (struct stream *obuf, struct peer *peer) { char empty[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* Source AS number and Destination AS number. */ stream_putw (obuf, peer->as); stream_putw (obuf, peer->local_as); if (peer->afc[AFI_IP][SAFI_UNICAST]) { stream_putw (obuf, peer->ifindex); stream_putw (obuf, AFI_IP); stream_put (obuf, &peer->su.sin.sin_addr, IPV4_MAX_BYTELEN); if (peer->su_local) stream_put (obuf, &peer->su_local->sin.sin_addr, IPV4_MAX_BYTELEN); else stream_put (obuf, empty, IPV4_MAX_BYTELEN); } #ifdef HAVE_IPV6 else if (peer->afc[AFI_IP6][SAFI_UNICAST]) { /* Interface Index and Address family. */ stream_putw (obuf, peer->ifindex); stream_putw (obuf, AFI_IP6); /* Source IP Address and Destination IP Address. */ stream_put (obuf, &peer->su.sin6.sin6_addr, IPV6_MAX_BYTELEN); if (peer->su_local) stream_put (obuf, &peer->su_local->sin6.sin6_addr, IPV6_MAX_BYTELEN); else stream_put (obuf, empty, IPV6_MAX_BYTELEN); } #endif /* HAVE_IPV6 */ }
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); }
/* basic parsing test */ static void parse_test (struct peer *peer, struct test_segment *t, int type) { int parse_ret = 0, nlri_ret = 0; struct attr attr = { }; struct bgp_nlri nlri = { }; struct bgp_attr_parser_args attr_args = { .peer = peer, .length = t->len, .total = 1, .attr = &attr, .type = type, .flags = BGP_ATTR_FLAG_OPTIONAL, .startp = BGP_INPUT_PNT (peer), }; #define RANDOM_FUZZ 35 stream_reset (peer->ibuf); stream_put (peer->ibuf, NULL, RANDOM_FUZZ); stream_set_getp (peer->ibuf, RANDOM_FUZZ); stream_write (peer->ibuf, t->data, t->len); printf ("%s: %s\n", t->name, t->desc); if (type == BGP_ATTR_MP_REACH_NLRI) parse_ret = bgp_mp_reach_parse (&attr_args, &nlri); else parse_ret = bgp_mp_unreach_parse (&attr_args, &nlri); if (parse_ret == 0 && t->afi_valid == VALID_AFI) assert (nlri.afi == t->afi && nlri.safi == t->safi); if (!parse_ret) { if (type == BGP_ATTR_MP_REACH_NLRI) nlri_ret = bgp_nlri_parse (peer, &attr, &nlri); else nlri_ret = bgp_nlri_parse (peer, NULL, &nlri); } handle_result (peer, t, parse_ret, nlri_ret); } static struct bgp *bgp; static as_t asn = 100; int main (void) { struct peer *peer; int i, j; conf_bgp_debug_fsm = -1UL; conf_bgp_debug_events = -1UL; conf_bgp_debug_packet = -1UL; conf_bgp_debug_normal = -1UL; conf_bgp_debug_as4 = -1UL; term_bgp_debug_fsm = -1UL; term_bgp_debug_events = -1UL; term_bgp_debug_packet = -1UL; term_bgp_debug_normal = -1UL; term_bgp_debug_as4 = -1UL; master = thread_master_create (); bgp_master_init (); bgp_option_set (BGP_OPT_NO_LISTEN); bgp_attr_init (); bgp_address_init (); if (fileno (stdout) >= 0) tty = isatty (fileno (stdout)); if (bgp_get (&bgp, &asn, NULL)) return -1; peer = peer_create_accept (bgp); peer->host = (char *)"foo"; peer->status = Established; for (i = AFI_IP; i < AFI_MAX; i++) for (j = SAFI_UNICAST; j < SAFI_MAX; j++) { peer->afc[i][j] = 1; peer->afc_adv[i][j] = 1; } i = 0; while (mp_reach_segments[i].name) parse_test (peer, &mp_reach_segments[i++], BGP_ATTR_MP_REACH_NLRI); i = 0; while (mp_unreach_segments[i].name) parse_test (peer, &mp_unreach_segments[i++], BGP_ATTR_MP_UNREACH_NLRI); printf ("failures: %d\n", failed); return failed; }
int zsend_ipv6_nexthop_lookup (struct zserv *client, struct in6_addr *addr) { struct stream *s; struct rib *rib; unsigned long nump; u_char num; struct nexthop *nexthop; /* Lookup nexthop. */ rib = rib_match_ipv6 (addr); /* Get output stream. */ s = client->obuf; stream_reset (s); /* Fill in result. */ stream_putw (s, 0); stream_putc (s, ZEBRA_IPV6_NEXTHOP_LOOKUP); stream_put (s, &addr, 16); if (rib) { stream_putl (s, rib->metric); num = 0; nump = s->putp; stream_putc (s, 0); for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next) if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)) { stream_putc (s, nexthop->type); switch (nexthop->type) { case ZEBRA_NEXTHOP_IPV6: stream_put (s, &nexthop->gate.ipv6, 16); break; case ZEBRA_NEXTHOP_IPV6_IFINDEX: case ZEBRA_NEXTHOP_IPV6_IFNAME: stream_put (s, &nexthop->gate.ipv6, 16); stream_putl (s, nexthop->ifindex); break; case ZEBRA_NEXTHOP_IFINDEX: case ZEBRA_NEXTHOP_IFNAME: stream_putl (s, nexthop->ifindex); break; default: /* do nothing */ break; } num++; } stream_putc_at (s, nump, num); } else { stream_putl (s, 0); stream_putc (s, 0); } stream_putw_at (s, 0, stream_get_endp (s)); zebra_server_send_message (client->sock, s->data, stream_get_endp (s)); return 0; }
int stream_abort(ObjectStream* os) { /// // TBD: this should be a per-repo config-option /// static const time_t timeout_sec = 5; // fuse may call fuse-flush multiple times (one for every open stream). // but will not call flush after calling close(). if (! (os->flags & OSF_OPEN)) { LOG(LOG_ERR, "%s isn't open\n", os->url); errno = EINVAL; /* ?? */ return -1; } else if (! (os->flags & OSF_WRITING)) { LOG(LOG_ERR, "%s aborting a read-stream is not supported\n", os->url); errno = ENOSYS; return -1; } // See NOTE, above, regarding the difference between reads and writes. void* retval; if (! pthread_tryjoin_np(os->op, &retval)) { LOG(LOG_INFO, "op-thread joined\n"); os->flags |= OSF_JOINED; } else { if (os->flags & OSF_WRITING) { // signal ABORT to readfunc LOG(LOG_INFO, "(wr) sending (char*)1 (flags=0x%04x)\n", os->flags); os->flags |= OSF_ABORT; if (stream_put(os, (const char*)1, 1) != 1) { LOG(LOG_ERR, "stream_put((char*)1) failed\n"); pthread_kill(os->op, SIGKILL); LOG(LOG_INFO, "killed thread\n"); } } // check whether thread has returned. Could mean a curl // error, an S3 protocol error, or server flaking out. LOG(LOG_INFO, "waiting for op-thread\n"); if (stream_wait(os)) { LOG(LOG_ERR, "err joining op-thread\n"); return -1; } } // thread has completed os->flags |= OSF_JOINED; LOG(LOG_INFO, "op-thread returned %d\n", os->op_rc); if ((os->op_rc == CURLE_ABORTED_BY_CALLBACK) && (os->iob.read_pos == (char*)1)) { LOG(LOG_INFO, "op-thread return is as expected for ABORT\n"); return 0; } else { errno = (os->op_rc ? EINVAL : 0); return os->op_rc; } }
// wait for the S3 GET/PUT to complete int stream_sync(ObjectStream* os) { /// // TBD: this should be a per-repo config-option /// static const time_t timeout_sec = 5; void* retval; // fuse may call fuse-flush multiple times (one for every open stream). // but will not call flush after calling close(). if (! (os->flags & OSF_OPEN)) { LOG(LOG_ERR, "%s isn't open\n", os->url); errno = EINVAL; /* ?? */ return -1; } // See NOTE, above, regarding the difference between reads and writes. if (! pthread_tryjoin_np(os->op, &retval)) { LOG(LOG_INFO, "op-thread joined\n"); os->flags |= OSF_JOINED; } else { // If a stream_get/put timed-out waiting for their // writefunc/readfunc, then the locks are likely in an inconsistent // state. [Either (a) the readfunc never posted iob_empty for // stream__put(), or (b) the writefunc never posted iob_full for // stream_get().] In either case, the operation started by // stream_open() is declared a failure, and we shouldn't do any of // the normal cleanup stuff, like trying to write recovery-info, etc. // But we do need to the thread to stop before we return, because if // the writefunc/readfunc gets another callback, it will access parts // of the ObjectStream that are about to be deallocated. if (os->flags & OSF_TIMEOUT) { LOG(LOG_INFO, "cancelling timed-out thread\n"); int rc = pthread_cancel(os->op); if (rc) { LOG(LOG_ERR, "cancellation failed (%s), killing thread\n", strerror(errno)); pthread_kill(os->op, SIGKILL); LOG(LOG_INFO, "killed thread\n"); } LOG(LOG_INFO, "waiting for terminated op-thread\n"); if (stream_wait(os)) { LOG(LOG_ERR, "err joining op-thread ('%s')\n", strerror(errno)); return -1; } } // In this case, the get/put timed-out, but it did so inside SAFE_WAIT_KILL(), // rather than SAFE_WAIT(), so the thread has already been cancelled // and joined. else if (os->flags & OSF_TIMEOUT_K) { LOG(LOG_INFO, "timed-out thread already killed\n"); LOG(LOG_INFO, "op-thread returned %d\n", os->op_rc); errno = (os->op_rc ? EIO : 0); return os->op_rc; } #if (LIBCURL_VERSION_MAJOR > 7) || ((LIBCURL_VERSION_MAJOR == 7) && (LIBCURL_VERSION_MINOR >= 45)) // Our installed version of libcurl is 7.19.7. We are experimenting // with a custom-built libcurl based on 7.45.0. We notice that the // latter does not call streaming_readfunc() again, if stream_open() // provided a content-length (i.e. the request had a content-length // header, rather than being chunked-transfer-encoded), and the full // number of chars matching the content-length header has been sent. // In such a case, stream_sync() shouldn't use "stream_put(..0)" to // get the readfunc to quit, because the readfunc isn't running. // // NOTE: This behavior may actually be present in earlier versions of // libcurl, in which case, the VERSION_MINOR here should be // adjusted downwards, toward 19. else if ((os->flags & OSF_WRITING) && os->content_len && (os->content_len == os->written)) { LOG(LOG_INFO, "(wr) wrote content-len, no action needed (flags=0x%04x)\n", os->flags); } #endif // signal EOF to readfunc else if (os->flags & OSF_WRITING) { LOG(LOG_INFO, "(wr) sending empty buffer (flags=0x%04x)\n", os->flags); if (stream_put(os, NULL, 0)) { LOG(LOG_ERR, "stream_put(0) failed\n"); pthread_kill(os->op, SIGKILL); LOG(LOG_INFO, "killed thread\n"); } } // signal QUIT to writefunc else { LOG(LOG_INFO, "(rd) sending empty buffer (flags=0x%04x)\n", os->flags); if (stream_get(os, NULL, 0)) { LOG(LOG_ERR, "stream_get(0) failed\n"); pthread_kill(os->op, SIGKILL); LOG(LOG_INFO, "killed thread\n"); } } // check whether thread has returned. Could mean a curl // error, an S3 protocol error, or server flaking out. LOG(LOG_INFO, "waiting for op-thread\n"); if (stream_wait(os)) { LOG(LOG_ERR, "err joining op-thread ('%s')\n", strerror(errno)); return -1; } } // thread has completed os->flags |= OSF_JOINED; if (( os->flags & OSF_READING) && (os->op_rc == CURLE_WRITE_ERROR)) { // when we signalled writefunc to quit, it provoked this LOG(LOG_INFO, "op-thread returned CURLE_WRITE_ERROR as expected\n"); return 0; } else { LOG(LOG_INFO, "op-thread returned %d\n", os->op_rc); errno = (os->op_rc ? EIO : 0); return os->op_rc; } }
/* basic parsing test */ static void parse_test (struct peer *peer, struct test_segment *t, int type) { int ret; int capability = 0; as_t as4 = 0; int oldfailed = failed; int len = t->len; #define RANDOM_FUZZ 35 stream_reset (peer->ibuf); stream_put (peer->ibuf, NULL, RANDOM_FUZZ); stream_set_getp (peer->ibuf, RANDOM_FUZZ); switch (type) { case CAPABILITY: stream_putc (peer->ibuf, BGP_OPEN_OPT_CAP); stream_putc (peer->ibuf, t->len); break; case DYNCAP: /* for (i = 0; i < BGP_MARKER_SIZE; i++) stream_putc (peer->, 0xff); stream_putw (s, 0); stream_putc (s, BGP_MSG_CAPABILITY);*/ break; } stream_write (peer->ibuf, t->data, t->len); printf ("%s: %s\n", t->name, t->desc); switch (type) { case CAPABILITY: len += 2; /* to cover the OPT-Param header */ case OPT_PARAM: printf ("len: %u\n", len); /* peek_for_as4 wants getp at capibility*/ as4 = peek_for_as4_capability (peer, len); printf ("peek_for_as4: as4 is %u\n", as4); /* and it should leave getp as it found it */ assert (stream_get_getp (peer->ibuf) == RANDOM_FUZZ); ret = bgp_open_option_parse (peer, len, &capability); break; case DYNCAP: ret = bgp_capability_receive (peer, t->len); break; default: printf ("unknown type %u\n", type); exit(1); } if (!ret && t->validate_afi) { safi_t safi = t->safi; if (bgp_afi_safi_valid_indices (t->afi, &safi) != t->afi_valid) failed++; printf ("MP: %u/%u (%u): recv %u, nego %u\n", t->afi, t->safi, safi, peer->afc_recv[t->afi][safi], peer->afc_nego[t->afi][safi]); if (t->afi_valid == VALID_AFI) { if (!peer->afc_recv[t->afi][safi]) failed++; if (!peer->afc_nego[t->afi][safi]) failed++; } } if (as4 != t->peek_for) { printf ("as4 %u != %u\n", as4, t->peek_for); failed++; } printf ("parsed?: %s\n", ret ? "no" : "yes"); if (ret != t->parses) failed++; if (tty) printf ("%s", (failed > oldfailed) ? VT100_RED "failed!" VT100_RESET : VT100_GREEN "OK" VT100_RESET); else printf ("%s", (failed > oldfailed) ? "failed!" : "OK" ); if (failed) printf (" (%u)", failed); printf ("\n\n"); }
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); }