static void ospf_router_lsa_dump(struct stream *s, uint16_t length) { char buf[BUFSIZ]; struct router_lsa *rl; int i, len; rl = (struct router_lsa *)stream_pnt(s); zlog_debug(" Router-LSA"); zlog_debug(" flags %s", ospf_router_lsa_flags_dump(rl->flags, buf, BUFSIZ)); zlog_debug(" # links %d", ntohs(rl->links)); len = ntohs(rl->header.length) - OSPF_LSA_HEADER_SIZE - 4; for (i = 0; len > 0; i++) { zlog_debug(" Link ID %s", inet_ntoa(rl->link[i].link_id)); zlog_debug(" Link Data %s", inet_ntoa(rl->link[i].link_data)); zlog_debug(" Type %d", (uint8_t)rl->link[i].type); zlog_debug(" TOS %d", (uint8_t)rl->link[i].tos); zlog_debug(" metric %d", ntohs(rl->link[i].metric)); len -= 12; } }
static void ospf_packet_db_desc_dump(struct stream *s, uint16_t length) { struct ospf_db_desc *dd; char dd_flags[8]; uint32_t gp; gp = stream_get_getp(s); dd = (struct ospf_db_desc *)stream_pnt(s); zlog_debug("Database Description"); zlog_debug(" Interface MTU %d", ntohs(dd->mtu)); zlog_debug(" Options %d (%s)", dd->options, ospf_options_dump(dd->options)); zlog_debug(" Flags %d (%s)", dd->flags, ospf_dd_flags_dump(dd->flags, dd_flags, sizeof dd_flags)); zlog_debug(" Sequence Number 0x%08lx", (unsigned long)ntohl(dd->dd_seqnum)); length -= OSPF_HEADER_SIZE + OSPF_DB_DESC_MIN_SIZE; stream_forward_getp(s, OSPF_DB_DESC_MIN_SIZE); ospf_lsa_header_list_dump(s, length); stream_set_getp(s, gp); }
void zebra_read_ipv6 (int command, struct zserv *client, u_short length) { u_char type; u_char flags; struct in6_addr nexthop, *gate; u_char *lim; u_char *pnt; unsigned int ifindex; pnt = stream_pnt (client->ibuf); lim = pnt + length; type = stream_getc (client->ibuf); flags = stream_getc (client->ibuf); stream_get (&nexthop, client->ibuf, sizeof (struct in6_addr)); while (stream_pnt (client->ibuf) < lim) { int size; struct prefix_ipv6 p; ifindex = stream_getl (client->ibuf); memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; p.prefixlen = stream_getc (client->ibuf); size = PSIZE(p.prefixlen); stream_get (&p.prefix, client->ibuf, size); if (IN6_IS_ADDR_UNSPECIFIED (&nexthop)) gate = NULL; else gate = &nexthop; if (command == ZEBRA_IPV6_ROUTE_ADD) rib_add_ipv6 (type, flags, &p, gate, ifindex, 0, 0, 0); else rib_delete_ipv6 (type, flags, &p, gate, ifindex, 0); } }
static void ospf_lsa_header_list_dump(struct stream *s, uint16_t length) { struct lsa_header *lsa; zlog_debug(" # LSA Headers %d", length / OSPF_LSA_HEADER_SIZE); /* LSA Headers. */ while (length > 0) { lsa = (struct lsa_header *)stream_pnt(s); ospf_lsa_header_dump(lsa); stream_forward_getp(s, OSPF_LSA_HEADER_SIZE); length -= OSPF_LSA_HEADER_SIZE; } }
static void ospf_summary_lsa_dump(struct stream *s, uint16_t length) { struct summary_lsa *sl; int size; int i; sl = (struct summary_lsa *)stream_pnt(s); zlog_debug(" Summary-LSA"); zlog_debug(" Network Mask %s", inet_ntoa(sl->mask)); size = ntohs(sl->header.length) - OSPF_LSA_HEADER_SIZE - 4; for (i = 0; size > 0; size -= 4, i++) zlog_debug(" TOS=%d metric %d", sl->tos, GET_METRIC(sl->metric)); }
static void ospf_network_lsa_dump(struct stream *s, uint16_t length) { struct network_lsa *nl; int i, cnt; nl = (struct network_lsa *)stream_pnt(s); cnt = (ntohs(nl->header.length) - (OSPF_LSA_HEADER_SIZE + 4)) / 4; zlog_debug(" Network-LSA"); /* zlog_debug ("LSA total size %d", ntohs (nl->header.length)); zlog_debug ("Network-LSA size %d", ntohs (nl->header.length) - OSPF_LSA_HEADER_SIZE); */ zlog_debug(" Network Mask %s", inet_ntoa(nl->mask)); zlog_debug(" # Attached Routers %d", cnt); for (i = 0; i < cnt; i++) zlog_debug(" Attached Router %s", inet_ntoa(nl->routers[i])); }
void ospf_packet_dump(struct stream *s) { struct ospf_header *ospfh; unsigned long gp; /* Preserve pointer. */ gp = stream_get_getp(s); /* OSPF Header dump. */ ospfh = (struct ospf_header *)stream_pnt(s); /* Until detail flag is set, return. */ if (!(term_debug_ospf_packet[ospfh->type - 1] & OSPF_DEBUG_DETAIL)) return; /* Show OSPF header detail. */ ospf_header_dump(ospfh); stream_forward_getp(s, OSPF_HEADER_SIZE); switch (ospfh->type) { case OSPF_MSG_HELLO: ospf_packet_hello_dump(s, ntohs(ospfh->length)); break; case OSPF_MSG_DB_DESC: ospf_packet_db_desc_dump(s, ntohs(ospfh->length)); break; case OSPF_MSG_LS_REQ: ospf_packet_ls_req_dump(s, ntohs(ospfh->length)); break; case OSPF_MSG_LS_UPD: ospf_packet_ls_upd_dump(s, ntohs(ospfh->length)); break; case OSPF_MSG_LS_ACK: ospf_packet_ls_ack_dump(s, ntohs(ospfh->length)); break; default: break; } stream_set_getp(s, gp); }
static void ospf_as_external_lsa_dump(struct stream *s, uint16_t length) { struct as_external_lsa *al; int size; int i; al = (struct as_external_lsa *)stream_pnt(s); zlog_debug(" %s", ospf_lsa_type_msg[al->header.type].str); zlog_debug(" Network Mask %s", inet_ntoa(al->mask)); size = ntohs(al->header.length) - OSPF_LSA_HEADER_SIZE - 4; for (i = 0; size > 0; size -= 12, i++) { zlog_debug(" bit %s TOS=%d metric %d", IS_EXTERNAL_METRIC(al->e[i].tos) ? "E" : "-", al->e[i].tos & 0x7f, GET_METRIC(al->e[i].metric)); zlog_debug(" Forwarding address %s", inet_ntoa(al->e[i].fwd_addr)); zlog_debug(" External Route Tag %" ROUTE_TAG_PRI, al->e[i].route_tag); } }
static void print_stream (struct stream *s) { size_t getp = stream_get_getp (s); printf ("endp: %zu, readable: %zu, writeable: %zu\n", stream_get_endp (s), STREAM_READABLE (s), STREAM_WRITEABLE (s)); while (STREAM_READABLE (s)) { printf ("0x%x ", *stream_pnt (s)); stream_forward_getp (s, 1); } printf ("\n"); /* put getp back to where it was */ stream_set_getp (s, getp); }
static void ospf_packet_hello_dump(struct stream *s, uint16_t length) { struct ospf_hello *hello; int i; hello = (struct ospf_hello *)stream_pnt(s); zlog_debug("Hello"); zlog_debug(" NetworkMask %s", inet_ntoa(hello->network_mask)); zlog_debug(" HelloInterval %d", ntohs(hello->hello_interval)); zlog_debug(" Options %d (%s)", hello->options, ospf_options_dump(hello->options)); zlog_debug(" RtrPriority %d", hello->priority); zlog_debug(" RtrDeadInterval %ld", (unsigned long)ntohl(hello->dead_interval)); zlog_debug(" DRouter %s", inet_ntoa(hello->d_router)); zlog_debug(" BDRouter %s", inet_ntoa(hello->bd_router)); length -= OSPF_HEADER_SIZE + OSPF_HELLO_MIN_SIZE; zlog_debug(" # Neighbors %d", length / 4); for (i = 0; length > 0; i++, length -= sizeof(struct in_addr)) zlog_debug(" Neighbor %s", inet_ntoa(hello->neighbors[i])); }
static void ospf_packet_ls_upd_dump(struct stream *s, uint16_t length) { uint32_t sp; struct lsa_header *lsa; int lsa_len; uint32_t count; length -= OSPF_HEADER_SIZE; sp = stream_get_getp(s); count = stream_getl(s); length -= 4; zlog_debug("Link State Update"); zlog_debug(" # LSAs %d", count); while (length > 0 && count > 0) { if (length < OSPF_HEADER_SIZE || length % 4 != 0) { zlog_debug(" Remaining %d bytes; Incorrect length.", length); break; } lsa = (struct lsa_header *)stream_pnt(s); lsa_len = ntohs(lsa->length); ospf_lsa_header_dump(lsa); switch (lsa->type) { case OSPF_ROUTER_LSA: ospf_router_lsa_dump(s, length); break; case OSPF_NETWORK_LSA: ospf_network_lsa_dump(s, length); break; case OSPF_SUMMARY_LSA: case OSPF_ASBR_SUMMARY_LSA: ospf_summary_lsa_dump(s, length); break; case OSPF_AS_EXTERNAL_LSA: ospf_as_external_lsa_dump(s, length); break; case OSPF_AS_NSSA_LSA: ospf_as_external_lsa_dump(s, length); break; case OSPF_OPAQUE_LINK_LSA: case OSPF_OPAQUE_AREA_LSA: case OSPF_OPAQUE_AS_LSA: ospf_opaque_lsa_dump(s, length); break; default: break; } stream_forward_getp(s, lsa_len); length -= lsa_len; count--; } stream_set_getp(s, sp); }
/** * Parse given capability. * XXX: This is reading into a stream, but not using stream API * * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol * capabilities were encountered. */ static int bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability, u_char **error) { int ret; struct stream *s = BGP_INPUT (peer); size_t end = stream_get_getp (s) + length; assert (STREAM_READABLE (s) >= length); while (stream_get_getp (s) < end) { size_t start; u_char *sp = stream_pnt (s); struct capability_header caphdr; /* We need at least capability code and capability length. */ if (stream_get_getp(s) + 2 > end) { zlog_info ("%s Capability length error (< header)", peer->host); bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); return -1; } caphdr.code = stream_getc (s); caphdr.length = stream_getc (s); start = stream_get_getp (s); /* Capability length check sanity check. */ if (start + caphdr.length > end) { zlog_info ("%s Capability length error (< length)", peer->host); bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); return -1; } if (BGP_DEBUG (normal, NORMAL)) zlog_debug ("%s OPEN has %s capability (%u), length %u", peer->host, LOOKUP (capcode_str, caphdr.code), caphdr.code, caphdr.length); /* Length sanity check, type-specific, for known capabilities */ switch (caphdr.code) { case CAPABILITY_CODE_MP: case CAPABILITY_CODE_REFRESH: case CAPABILITY_CODE_REFRESH_OLD: case CAPABILITY_CODE_ORF: case CAPABILITY_CODE_ORF_OLD: case CAPABILITY_CODE_RESTART: case CAPABILITY_CODE_AS4: case CAPABILITY_CODE_DYNAMIC: /* Check length. */ if (caphdr.length < cap_minsizes[caphdr.code]) { zlog_info ("%s %s Capability length error: got %u," " expected at least %u", peer->host, LOOKUP (capcode_str, caphdr.code), caphdr.length, (unsigned) cap_minsizes[caphdr.code]); bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); return -1; } /* we deliberately ignore unknown codes, see below */ default: break; } switch (caphdr.code) { case CAPABILITY_CODE_MP: { *mp_capability = 1; /* Ignore capability when override-capability is set. */ if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) { /* Set negotiated value. */ ret = bgp_capability_mp (peer, &caphdr); /* Unsupported Capability. */ if (ret < 0) { /* Store return data. */ memcpy (*error, sp, caphdr.length + 2); *error += caphdr.length + 2; } } } break; case CAPABILITY_CODE_REFRESH: case CAPABILITY_CODE_REFRESH_OLD: { /* BGP refresh capability */ if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD) SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV); else SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV); } break; case CAPABILITY_CODE_ORF: case CAPABILITY_CODE_ORF_OLD: if (bgp_capability_orf (peer, &caphdr)) return -1; break; case CAPABILITY_CODE_RESTART: if (bgp_capability_restart (peer, &caphdr)) return -1; break; case CAPABILITY_CODE_DYNAMIC: SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV); break; case CAPABILITY_CODE_AS4: /* Already handled as a special-case parsing of the capabilities * at the beginning of OPEN processing. So we care not a jot * for the value really, only error case. */ if (!bgp_capability_as4 (peer, &caphdr)) return -1; break; default: if (caphdr.code > 128) { /* We don't send Notification for unknown vendor specific capabilities. It seems reasonable for now... */ zlog_warn ("%s Vendor specific capability %d", peer->host, caphdr.code); } else { zlog_warn ("%s unrecognized capability code: %d - ignored", peer->host, caphdr.code); memcpy (*error, sp, caphdr.length + 2); *error += caphdr.length + 2; } } if (stream_get_getp(s) != (start + caphdr.length)) { if (stream_get_getp(s) > (start + caphdr.length)) zlog_warn ("%s Cap-parser for %s read past cap-length, %u!", peer->host, LOOKUP (capcode_str, caphdr.code), caphdr.length); stream_set_getp (s, start + caphdr.length); } } return 0; }
/* Parse open option */ int bgp_open_option_parse (struct peer *peer, u_char length, int *capability) { int ret; u_char *end; u_char opt_type; u_char opt_length; u_char *pnt; u_char *error; u_char error_data[BGP_MAX_PACKET_SIZE]; /* Fetch pointer. */ pnt = stream_pnt (peer->ibuf); ret = 0; opt_type = 0; opt_length = 0; end = pnt + length; error = error_data; if (BGP_DEBUG (normal, NORMAL)) zlog_info ("%s rcv OPEN w/ OPTION parameter len: %u", peer->host, length); while (pnt < end) { /* Check the length. */ if (pnt + 2 > end) { zlog_info ("%s Option length error", peer->host); bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); return -1; } /* Fetch option type and length. */ opt_type = *pnt++; opt_length = *pnt++; /* Option length check. */ if (pnt + opt_length > end) { zlog_info ("%s Option length error", peer->host); bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0); return -1; } if (BGP_DEBUG (normal, NORMAL)) zlog_info ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u", peer->host, opt_type, opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" : opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown", opt_length); switch (opt_type) { case BGP_OPEN_OPT_AUTH: ret = bgp_auth_parse (peer, pnt, opt_length); break; case BGP_OPEN_OPT_CAP: ret = bgp_capability_parse (peer, pnt, opt_length, &error); *capability = 1; break; default: bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_PARAM); ret = -1; break; } /* Parse error. To accumulate all unsupported capability codes, bgp_capability_parse does not return -1 when encounter unsupported capability code. To detect that, please check error and erro_data pointer, like below. */ if (ret < 0) return -1; /* Forward pointer. */ pnt += opt_length; } /* All OPEN option is parsed. Check capability when strict compare flag is enabled.*/ if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) { /* If Unsupported Capability exists. */ if (error != error_data) { bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_CAPBL, error_data, error - error_data); return -1; } /* Check local capability does not negotiated with remote peer. */ if (! strict_capability_same (peer)) { bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_CAPBL); return -1; } } /* Check there is no common capability send Unsupported Capability error. */ if (*capability && ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) { if (! peer->afc_nego[AFI_IP][SAFI_UNICAST] && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST] && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST] && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST]) { plog_err (peer->log, "%s [Error] No common capability", peer->host); if (error != error_data) bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_CAPBL, error_data, error - error_data); else bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSUP_CAPBL); return -1; } } return 0; }