+static int
+bgp_mp_af_print(netdissect_options *ndo,
+ const u_char *tptr, u_int tlen,
+ uint16_t *afp, uint8_t *safip)
+{
+ uint16_t af;
+ uint8_t safi;
+
+ af = GET_BE_U_2(tptr);
+ *afp = af;
+ safi = GET_U_1(tptr + 2);
+ *safip = safi;
+
+ ND_PRINT("\n\t AFI: %s (%u), %sSAFI: %s (%u)",
+ tok2str(af_values, "Unknown AFI", af),
+ af,
+ (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
+ tok2str(bgp_safi_values, "Unknown SAFI", safi),
+ safi);
+
+ switch(af<<8 | safi) {
+ case (AFNUM_IP<<8 | SAFNUM_UNICAST):
+ case (AFNUM_IP<<8 | SAFNUM_MULTICAST):
+ case (AFNUM_IP<<8 | SAFNUM_UNIMULTICAST):
+ case (AFNUM_IP<<8 | SAFNUM_LABUNICAST):
+ case (AFNUM_IP<<8 | SAFNUM_RT_ROUTING_INFO):
+ case (AFNUM_IP<<8 | SAFNUM_VPNUNICAST):
+ case (AFNUM_IP<<8 | SAFNUM_VPNMULTICAST):
+ case (AFNUM_IP<<8 | SAFNUM_VPNUNIMULTICAST):
+ case (AFNUM_IP<<8 | SAFNUM_MULTICAST_VPN):
+ case (AFNUM_IP<<8 | SAFNUM_MDT):
+ case (AFNUM_IP6<<8 | SAFNUM_UNICAST):
+ case (AFNUM_IP6<<8 | SAFNUM_MULTICAST):
+ case (AFNUM_IP6<<8 | SAFNUM_UNIMULTICAST):
+ case (AFNUM_IP6<<8 | SAFNUM_LABUNICAST):
+ case (AFNUM_IP6<<8 | SAFNUM_VPNUNICAST):
+ case (AFNUM_IP6<<8 | SAFNUM_VPNMULTICAST):
+ case (AFNUM_IP6<<8 | SAFNUM_VPNUNIMULTICAST):
+ case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
+ case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
+ case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
+ case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
+ case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
+ case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
+ case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
+ case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
+ case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
+ case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
+ break;
+ default:
+ ND_TCHECK_LEN(tptr, tlen);
+ ND_PRINT("\n\t no AFI %u / SAFI %u decoder", af, safi);
+ if (ndo->ndo_vflag <= 1)
+ print_unknown_data(ndo, tptr, "\n\t ", tlen);
+ return -1;
+ }
+ return 0;
+trunc:
+ return -2;
+}
+
+static int
+bgp_nlri_print(netdissect_options *ndo, uint16_t af, uint8_t safi,
+ const u_char *tptr, u_int len,
+ int add_path4, int add_path6)
+{
+ int advance;
+ u_int path_id = 0;
+ char buf[512];
+
+ switch (af<<8 | safi) {
+ case (AFNUM_IP<<8 | SAFNUM_UNICAST):
+ case (AFNUM_IP<<8 | SAFNUM_MULTICAST):
+ case (AFNUM_IP<<8 | SAFNUM_UNIMULTICAST):
+ if (add_path4) {
+ path_id = GET_BE_U_4(tptr);
+ tptr += 4;
+ }
+ advance = decode_prefix4(ndo, tptr, len, buf, sizeof(buf));
+ if (advance == -1)
+ ND_PRINT("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ break; /* bytes left, but not enough */
+ else
+ ND_PRINT("\n\t %s", buf);
+ if (add_path4) {
+ ND_PRINT(" Path Id: %u", path_id);
+ advance += 4;
+ }
+ break;
+ case (AFNUM_IP<<8 | SAFNUM_LABUNICAST):
+ advance = print_labeled_prefix4(ndo, tptr, len);
+ if (advance == -2)
+ goto trunc;
+ break;
+ case (AFNUM_IP<<8 | SAFNUM_VPNUNICAST):
+ case (AFNUM_IP<<8 | SAFNUM_VPNMULTICAST):
+ case (AFNUM_IP<<8 | SAFNUM_VPNUNIMULTICAST):
+ advance = print_labeled_vpn_prefix4(ndo, tptr);
+ break;
+ case (AFNUM_IP<<8 | SAFNUM_RT_ROUTING_INFO):
+ advance = print_rt_routing_info(ndo, tptr);
+ break;
+ case (AFNUM_IP<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
+ case (AFNUM_IP6<<8 | SAFNUM_MULTICAST_VPN):
+ advance = print_multicast_vpn(ndo, tptr);
+ if (advance == -2)
+ goto trunc;
+ break;
+
+ case (AFNUM_IP<<8 | SAFNUM_MDT):
+ advance = print_mdt_vpn_nlri(ndo, tptr);
+ if (advance == -2)
+ goto trunc;
+ break;
+ case (AFNUM_IP6<<8 | SAFNUM_UNICAST):
+ case (AFNUM_IP6<<8 | SAFNUM_MULTICAST):
+ case (AFNUM_IP6<<8 | SAFNUM_UNIMULTICAST):
+ if (add_path6) {
+ path_id = GET_BE_U_4(tptr);
+ tptr += 4;
+ }
+ advance = decode_prefix6(ndo, tptr, len, buf, sizeof(buf));
+ if (advance == -1)
+ ND_PRINT("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ break; /* bytes left, but not enough */
+ else
+ ND_PRINT("\n\t %s", buf);
+ if (add_path6) {
+ ND_PRINT(" Path Id: %u", path_id);
+ advance += 4;
+ }
+ break;
+ case (AFNUM_IP6<<8 | SAFNUM_LABUNICAST):
+ advance = print_labeled_prefix6(ndo, tptr, len);
+ if (advance == -2)
+ goto trunc;
+ break;
+ case (AFNUM_IP6<<8 | SAFNUM_VPNUNICAST):
+ case (AFNUM_IP6<<8 | SAFNUM_VPNMULTICAST):
+ case (AFNUM_IP6<<8 | SAFNUM_VPNUNIMULTICAST):
+ advance = print_labeled_vpn_prefix6(ndo, tptr);
+ break;
+ case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
+ case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
+ case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
+ case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
+ advance = print_labeled_vpn_l2(ndo, tptr);
+ if (advance == -2)
+ goto trunc;
+ break;
+ case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
+ case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
+ case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
+ advance = print_clnp_prefix(ndo, tptr);
+ break;
+ case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
+ case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
+ case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
+ advance = print_labeled_vpn_clnp_prefix(ndo, tptr);
+ break;
+ default:
+ /*
+ * This should not happen, we should have been protected
+ * by bgp_mp_af_print()'s return value.
+ */
+ ND_PRINT("\n\t ERROR: no AFI %u / SAFI %u decoder", af, safi);
+ advance = -4;
+ break;
+ }
+ return advance;
+trunc: /* we rely on the caller to recognize -2 return value */
+ return -2;
+}
+
+static const struct tok bgp_flags[] = {
+ { 0x80, "O"},
+ { 0x40, "T"},
+ { 0x20, "P"},
+ { 0x10, "E"},
+ { 0, NULL }
+};
+