Add support for SNA-over-X.25. Add QLLC dissector. I still need to
[obnox/wireshark/wip.git] / packet-bgp.c
index feb2fcfa552f3a3b4438cb6fd56cb62721d19324..49e11db89a1ae7e47499aad0b6adbd49a11ff08f 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for BGP packet dissection.
  * Copyright 1999, Jun-ichiro itojun Hagino <itojun@itojun.org>
  *
- * $Id: packet-bgp.c,v 1.44 2001/07/08 22:59:50 guy Exp $
+ * $Id: packet-bgp.c,v 1.48 2001/11/03 21:25:12 guy Exp $
  *
  * Supports:
  * RFC1771 A Border Gateway Protocol 4 (BGP-4)
@@ -66,6 +66,7 @@
 #include "packet.h"
 #include "packet-bgp.h"
 #include "packet-ipv6.h"
+#include "afn.h"
 
 static const value_string bgptypevals[] = {
     { BGP_OPEN, "OPEN Message" },
@@ -181,33 +182,10 @@ static const value_string bgpext_ospf_rtype[] = {
   { 0, NULL },
 };
 
-static const value_string bgpext_osptf_rtype_metric[] = {
-};
 
 /* MUST be resized if a longer named extended community is added */
 #define MAX_SIZE_OF_EXT_COM_NAMES       20
 
-static const value_string afnumber[] = {
-    { 0, "Reserved" },
-    { AFNUM_INET, "IPv4" },
-    { AFNUM_INET6, "IPv6" },
-    { AFNUM_NSAP, "NSAP" },
-    { AFNUM_HDLC, "HDLC" },
-    { AFNUM_BBN1822, "BBN 1822" },
-    { AFNUM_802, "802" },
-    { AFNUM_E163, "E.163" },
-    { AFNUM_E164, "E.164" },
-    { AFNUM_F69, "F.69" },
-    { AFNUM_X121, "X.121" },
-    { AFNUM_IPX, "IPX" },
-    { AFNUM_ATALK, "Appletalk" },
-    { AFNUM_DECNET, "Decnet IV" },
-    { AFNUM_BANYAN, "Banyan Vines" },
-    { AFNUM_E164NSAP, "E.164 with NSAP subaddress" },
-    { 65535, "Reserved" },
-    { 0, NULL },
-};
-
 /* Subsequent address family identifier, RFC2858 */
 static const value_string bgpattr_nlri_safi[] = {
     { 0, "Reserved" },
@@ -219,6 +197,21 @@ static const value_string bgpattr_nlri_safi[] = {
     { 0, NULL },
 };
 
+/* ORF Type, draft-ietf-idr-route-filter-04.txt */
+static const value_string orf_type_vals[] = {
+    { 2,       "Communities ORF-Type" },
+    { 3,       "Extended Communities ORF-Type" },
+    { 0,       NULL },
+};
+
+/* ORF Send/Receive, draft-ietf-idr-route-filter-04.txt */
+static const value_string orf_send_recv_vals[] = {
+    { 1,       "Receive" },
+    { 2,       "Send" },
+    { 3,       "Both" },
+    { 0,       NULL },
+};
+
 /* Maximal size of an IP address string */
 #define MAX_SIZE_OF_IP_ADDR_STRING      16
 
@@ -504,13 +497,18 @@ dissect_bgp_open(tvbuff_t *tvb, int offset, proto_tree *tree)
     int             plen;      /* parameter length      */
     int             ctype;     /* capability type       */
     int             clen;      /* capability length     */
+    int             cend;      /* capabilities end      */
     int             ostart;    /* options start         */
     int             oend;      /* options end           */
     int             p;         /* tvb offset counter    */
     proto_item      *ti;       /* tree item             */
     proto_tree      *subtree;  /* subtree for options   */
+    proto_tree      *subtree1; /* subtree for an option */
     proto_tree      *subtree2; /* subtree for an option */
     proto_tree      *subtree3; /* subtree for an option */
+    guint8          orfnum;    /* number of ORFs */
+    guint8          orftype;        /* ORF Type */
+    guint8          orfsendrecv;    /* ORF Send/Receive */
 
     /* snarf OPEN message */
     tvb_memcpy(tvb, bgpo.bgpo_marker, offset, BGP_MIN_OPEN_MSG_SIZE);
@@ -559,127 +557,178 @@ dissect_bgp_open(tvbuff_t *tvb, int offset, proto_tree *tree)
                 break;
             case BGP_OPTION_CAPABILITY:
                 /* grab the capability code */
+               cend = p - 1 + plen;
                 ctype = tvb_get_guint8(tvb, p++);
                 clen = tvb_get_guint8(tvb, p++);
-
-                /* check the capability type */
-                switch (ctype) {
-                case BGP_CAPABILITY_RESERVED:
-                    ti = proto_tree_add_text(subtree, tvb, p - 4,
-                         2 + plen, "Reserved capability (%u %s)", 2 + plen,
-                         (plen == 1) ? "byte" : "bytes");
-                    subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
-                    proto_tree_add_text(subtree2, tvb, p - 4,
-                         1, "Parameter type: Capabilities (2)");
-                    proto_tree_add_text(subtree2, tvb, p - 3,
-                         1, "Parameter length: %u %s", plen,
-                         (plen == 1) ? "byte" : "bytes");
-                    proto_tree_add_text(subtree2, tvb, p - 2,
-                         1, "Capability code: Reserved (0)");
-                    proto_tree_add_text(subtree2, tvb, p - 1,
-                         1, "Capability length: %u %s", clen,
-                         (clen == 1) ? "byte" : "bytes");
-                    if (clen != 0) {
-                        proto_tree_add_text(subtree2, tvb, p,
-                             clen, "Capability value: Unknown");
-                    }
-                    p += clen;
-                    break;
-                case BGP_CAPABILITY_MULTIPROTOCOL:
-                    ti = proto_tree_add_text(subtree, tvb, p - 4,
-                         2 + plen,
-                         "Multiprotocol extensions capability (%u %s)",
-                         2 + plen, (plen == 1) ? "byte" : "bytes");
-                    subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
-                    proto_tree_add_text(subtree2, tvb, p - 4,
-                         1, "Parameter type: Capabilities (2)");
-                    proto_tree_add_text(subtree2, tvb, p - 3,
-                         1, "Parameter length: %u %s", plen,
-                         (plen == 1) ? "byte" : "bytes");
-                    proto_tree_add_text(subtree2, tvb, p - 2,
-                         1, "Capability code: Multiprotocol extensions (%d)",
-                         ctype);
-                    if (clen != 4) {
-                        proto_tree_add_text(subtree2, tvb, p - 1,
-                             1, "Capability length: Invalid");
-                        proto_tree_add_text(subtree2, tvb, p,
-                             clen, "Capability value: Unknown");
-                    }
-                    else {
-                        proto_tree_add_text(subtree2, tvb, p - 1,
+               ti = proto_tree_add_text(subtree, tvb, p - 4,
+                     2 + plen, "Capabilities Advertisement (%u bytes)",
+                    2 + plen);
+               subtree1 = proto_item_add_subtree(ti, ett_bgp_option);
+               proto_tree_add_text(subtree1, tvb, p - 4,
+                     1, "Parameter type: Capabilities (2)");
+               proto_tree_add_text(subtree1, tvb, p - 3,
+                     1, "Parameter length: %u %s", plen,
+                     (plen == 1) ? "byte" : "bytes");
+               p -= 2;
+
+               /* step through all of the capabilities */
+               while (p < cend) {
+                   ctype = tvb_get_guint8(tvb, p++);
+                   clen = tvb_get_guint8(tvb, p++);
+
+                   /* check the capability type */
+                   switch (ctype) {
+                   case BGP_CAPABILITY_RESERVED:
+                       ti = proto_tree_add_text(subtree1, tvb, p - 2,
+                             2 + clen, "Reserved capability (%u %s)", 2 + clen,
+                             (clen == 1) ? "byte" : "bytes");
+                       subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
+                       proto_tree_add_text(subtree2, tvb, p - 2,
+                             1, "Capability code: Reserved (0)");
+                       proto_tree_add_text(subtree2, tvb, p - 1,
                              1, "Capability length: %u %s", clen,
                              (clen == 1) ? "byte" : "bytes");
-                        ti = proto_tree_add_text(subtree2, tvb, p,
+                       if (clen != 0) {
+                           proto_tree_add_text(subtree2, tvb, p,
+                                 clen, "Capability value: Unknown");
+                       }
+                       p += clen;
+                       break;
+                   case BGP_CAPABILITY_MULTIPROTOCOL:
+                       ti = proto_tree_add_text(subtree1, tvb, p - 2,
+                             2 + clen,
+                             "Multiprotocol extensions capability (%u %s)",
+                             2 + clen, (clen == 1) ? "byte" : "bytes");
+                       subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
+                       proto_tree_add_text(subtree2, tvb, p - 2,
+                             1, "Capability code: Multiprotocol extensions (%d)",
+                             ctype);
+                       if (clen != 4) {
+                           proto_tree_add_text(subtree2, tvb, p - 1,
+                                 1, "Capability length: Invalid");
+                           proto_tree_add_text(subtree2, tvb, p,
+                                 clen, "Capability value: Unknown");
+                       }
+                       else {
+                           proto_tree_add_text(subtree2, tvb, p - 1,
+                                 1, "Capability length: %u %s", clen,
+                                 (clen == 1) ? "byte" : "bytes");
+                           ti = proto_tree_add_text(subtree2, tvb, p,
+                                 clen, "Capability value");
+                           subtree3 = proto_item_add_subtree(ti,
+                                       ett_bgp_option);
+                           /* AFI */
+                           i = tvb_get_ntohs(tvb, p);
+                           proto_tree_add_text(subtree3, tvb, p,
+                                 2, "Address family identifier: %s (%u)",
+                                 val_to_str(i, afn_vals, "Unknown"), i);
+                           p += 2;
+                           /* Reserved */
+                           proto_tree_add_text(subtree3, tvb, p,
+                                 1, "Reserved: 1 byte");
+                           p++;
+                           /* SAFI */
+                           i = tvb_get_guint8(tvb, p);
+                           proto_tree_add_text(subtree3, tvb, p,
+                                 1, "Subsequent address family identifier: %s (%u)",
+                                 val_to_str(i, bgpattr_nlri_safi,
+                                    i >= 128 ? "Vendor specific" : "Unknown"), i);
+                           p++;
+                       }
+                       break;
+                   case BGP_CAPABILITY_ROUTE_REFRESH_CISCO:
+                   case BGP_CAPABILITY_ROUTE_REFRESH:
+                       ti = proto_tree_add_text(subtree1, tvb, p - 2,
+                             2 + clen, "Route refresh capability (%u %s)", 2 + clen,
+                             (clen == 1) ? "byte" : "bytes");
+                       subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
+                       proto_tree_add_text(subtree2, tvb, p - 2,
+                             1, "Capability code: Route refresh (%d)", ctype);
+                       if (clen != 0) {
+                           proto_tree_add_text(subtree2, tvb, p,
+                                 clen, "Capability value: Invalid");
+                       }
+                       else {
+                           proto_tree_add_text(subtree2, tvb, p - 1,
+                                 1, "Capability length: %u %s", clen,
+                                 (clen == 1) ? "byte" : "bytes");
+                       }
+                       p += clen;
+                       break;
+                   case BGP_CAPABILITY_COOPERATIVE_ROUTE_FILTERING:
+                       ti = proto_tree_add_text(subtree1, tvb, p - 2,
+                             2 + clen,
+                             "Cooperative route filtering capability (%u %s)",
+                             2 + clen, (clen == 1) ? "byte" : "bytes");
+                       subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
+                       proto_tree_add_text(subtree2, tvb, p - 2,
+                             1, "Capability code: Cooperative route filtering (%d)",
+                             ctype);
+                       proto_tree_add_text(subtree2, tvb, p - 1,
+                            1, "Capability length: %u %s", clen,
+                            (clen == 1) ? "byte" : "bytes");
+                       ti = proto_tree_add_text(subtree2, tvb, p,
                              clen, "Capability value");
-                             subtree3 = proto_item_add_subtree(ti,
-                                        ett_bgp_option);
-                        /* AFI */
-                        i = tvb_get_ntohs(tvb, p);
-                        proto_tree_add_text(subtree3, tvb, p,
-                             2, "Address family identifier: %s (%u)",
-                             val_to_str(i, afnumber, "Unknown"), i);
-                        p += 2;
-                        /* Reserved */
-                        proto_tree_add_text(subtree3, tvb, p,
-                             1, "Reserved: 1 byte");
-                        p++;
-                        /* SAFI */
-                        i = tvb_get_guint8(tvb, p);
-                        proto_tree_add_text(subtree3, tvb, p,
-                             1, "Subsequent address family identifier: %s (%u)",
-                             val_to_str(i, bgpattr_nlri_safi,
-                                i >= 128 ? "Vendor specific" : "Unknown"), i);
-                        p++;
-                    }
-                    break;
-                case BGP_CAPABILITY_ROUTE_REFRESH_CISCO:
-                case BGP_CAPABILITY_ROUTE_REFRESH:
-                    ti = proto_tree_add_text(subtree, tvb, p - 4,
-                         2 + plen, "Route refresh capability (%u %s)", 2 + plen,
-                         (plen == 1) ? "byte" : "bytes");
-                    subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
-                    proto_tree_add_text(subtree2, tvb, p - 4,
-                         1, "Parameter type: Capabilities (2)");
-                    proto_tree_add_text(subtree2, tvb, p - 3,
-                         1, "Parameter length: %u %s", plen,
-                         (plen == 1) ? "byte" : "bytes");
-                    proto_tree_add_text(subtree2, tvb, p - 2,
-                         1, "Capability code: Route refresh (%d)", ctype);
-                    if (clen != 0) {
-                        proto_tree_add_text(subtree2, tvb, p,
-                             clen, "Capability value: Invalid");
-                    }
-                    else {
-                        proto_tree_add_text(subtree2, tvb, p - 1,
+                       subtree3 = proto_item_add_subtree(ti, ett_bgp_option);
+                       /* AFI */
+                       i = tvb_get_ntohs(tvb, p);
+                       proto_tree_add_text(subtree3, tvb, p,
+                            2, "Address family identifier: %s (%u)",
+                             val_to_str(i, afn_vals, "Unknown"), i);
+                       p += 2;
+                       /* Reserved */
+                       proto_tree_add_text(subtree3, tvb, p, 
+                            1, "Reserved: 1 byte");
+                       p++;
+                       /* SAFI */
+                       i = tvb_get_guint8(tvb, p);
+                       proto_tree_add_text(subtree3, tvb, p,
+                            1, "Subsequent address family identifier: %s (%u)",
+                            val_to_str(i, bgpattr_nlri_safi,
+                            i >= 128 ? "Vendor specific" : "Unknown"), i);
+                       p++;
+                       /* Number of ORFs */
+                       orfnum = tvb_get_guint8(tvb, p);
+                       proto_tree_add_text(subtree3, tvb, p,
+                                           1, "Number of ORFs: %u", orfnum);
+                       p++;
+                       for (i=0; i<orfnum; i++) {
+                           /* ORF Type */
+                           orftype = tvb_get_guint8(tvb, p);
+                           proto_tree_add_text(subtree3, tvb, p,
+                               1, "ORF Type: %s (%u)",
+                               val_to_str(orftype, orf_type_vals,"Unknown"),
+                               orftype);
+                           p++;
+                           /* Send/Receive */
+                           orfsendrecv = tvb_get_guint8(tvb, p);
+                           proto_tree_add_text(subtree3, tvb, p,
+                               1, "Send/Receive: %s (%u)",
+                               val_to_str(orfsendrecv, orf_send_recv_vals, 
+                               "Uknown"), orfsendrecv);
+                           p++;
+                       }
+                       break;
+                   /* unknown capability */
+                   default:
+                       ti = proto_tree_add_text(subtree, tvb, p - 2,
+                             2 + clen, "Unknown capability (%u %s)", 2 + clen,
+                             (clen == 1) ? "byte" : "bytes");
+                       subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
+                       proto_tree_add_text(subtree2, tvb, p - 2,
+                             1, "Capability code: %s (%d)",
+                             ctype >= 128 ? "Private use" : "Unknown", ctype);
+                       proto_tree_add_text(subtree2, tvb, p - 1,
                              1, "Capability length: %u %s", clen,
                              (clen == 1) ? "byte" : "bytes");
-                    }
-                    p += clen;
-                    break;
-                /* unknown capability */
-                default:
-                    ti = proto_tree_add_text(subtree, tvb, p - 4,
-                         2 + plen, "Unknown capability (%u %s)", 2 + plen,
-                         (plen == 1) ? "byte" : "bytes");
-                    subtree2 = proto_item_add_subtree(ti, ett_bgp_option);
-                    proto_tree_add_text(subtree2, tvb, p - 4,
-                         1, "Parameter type: Capabilities (2)");
-                    proto_tree_add_text(subtree2, tvb, p - 3,
-                         1, "Parameter length: %u %s", plen,
-                         (plen == 1) ? "byte" : "bytes");
-                    proto_tree_add_text(subtree2, tvb, p - 2,
-                         1, "Capability code: %s (%d)",
-                         ctype >= 128 ? "Private use" : "Unknown", ctype);
-                    proto_tree_add_text(subtree2, tvb, p - 1,
-                         1, "Capability length: %u %s", clen,
-                         (clen == 1) ? "byte" : "bytes");
-                    if (clen != 0) {
-                        proto_tree_add_text(subtree2, tvb, p,
-                             clen, "Capability value: Unknown");
-                    }
-                    p += clen;
-                    break;
-                }
+                       if (clen != 0) {
+                           proto_tree_add_text(subtree2, tvb, p,
+                                 clen, "Capability value: Unknown");
+                       }
+                       p += clen;
+                       break;
+                   }
+               }
                 break;
             default:
                 proto_tree_add_text(subtree, tvb, p - 2, 2 + plen,
@@ -1318,7 +1367,7 @@ dissect_bgp_update(tvbuff_t *tvb, int offset, proto_tree *tree)
                af = tvb_get_ntohs(tvb, o + i + aoff);
                proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
                    "Address family: %s (%u)",
-                   val_to_str(af, afnumber, "Unknown"), af);
+                   val_to_str(af, afn_vals, "Unknown"), af);
                 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
                proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
                    "Subsequent address family identifier: %s (%u)",
@@ -1381,7 +1430,7 @@ dissect_bgp_update(tvbuff_t *tvb, int offset, proto_tree *tree)
                af = tvb_get_ntohs(tvb, o + i + aoff);
                proto_tree_add_text(subtree2, tvb, o + i + aoff, 2,
                    "Address family: %s (%u)",
-                   val_to_str(af, afnumber, "Unknown"), af);
+                   val_to_str(af, afn_vals, "Unknown"), af);
                 saf = tvb_get_guint8(tvb, o + i + aoff + 2) ;
                proto_tree_add_text(subtree2, tvb, o + i + aoff + 2, 1,
                    "Subsequent address family identifier: %s (%u)",
@@ -1578,15 +1627,15 @@ dissect_bgp_route_refresh(tvbuff_t *tvb, int offset, proto_tree *tree)
     i = tvb_get_ntohs(tvb, offset + BGP_HEADER_SIZE);
     proto_tree_add_text(tree, tvb, offset + BGP_HEADER_SIZE, 2, 
                         "Address family identifier: %s (%u)",
-                        val_to_str(i, afnumber, "Unknown"), i);
+                        val_to_str(i, afn_vals, "Unknown"), i);
     offset += 2;
     /* Reserved */
-    proto_tree_add_text(tree, tvb, offset + BGP_HEADER_SIZE + 2, 1, 
+    proto_tree_add_text(tree, tvb, offset + BGP_HEADER_SIZE, 1, 
                         "Reserved: 1 byte");
     offset++;
     /* SAFI */
-    i = tvb_get_guint8(tvb, offset);
-    proto_tree_add_text(tree, tvb, offset + BGP_HEADER_SIZE + 3, 1, 
+    i = tvb_get_guint8(tvb, offset + BGP_HEADER_SIZE);
+    proto_tree_add_text(tree, tvb, offset + BGP_HEADER_SIZE, 1, 
                         "Subsequent address family identifier: %s (%u)",
                         val_to_str(i, bgpattr_nlri_safi,
                         i >= 128 ? "Vendor specific" : "Unknown"),