Ethereal-dev: [Ethereal-dev] BGP support for L2VPNs

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Hannes Gredler <hannes@xxxxxxxxxxx>
Date: Mon, 26 Aug 2002 23:52:54 +0200
hi ethereal developers,

pls find attached a patch

for more complete support for L2VPNs like described in 
  draft-kompella-ppvpn-l2vpn;

fixing a segfault in the extd_community decoder;

more consistent SAFI strings (tcpdump)

more robust V6 decoding (the assumption that v6 may come
  only in unlabeled form is wrong :-|)

/hannes

Index: packet-bgp.c
===================================================================
RCS file: /cvsroot/ethereal/packet-bgp.c,v
retrieving revision 1.64
diff -u -r1.64 packet-bgp.c
--- packet-bgp.c	2002/08/24 21:58:57	1.64
+++ packet-bgp.c	2002/08/26 21:46:06
@@ -203,9 +203,9 @@
     { SAFNUM_MULCAST, "Multicast" },
     { SAFNUM_UNIMULC, "Unicast+Multicast" },
     { SAFNUM_MPLS_LABEL, "MPLS Labeled Prefix"},
-    { SAFNUM_LAB_VPNUNICAST, "Labeled Unicast" },        /* draft-rosen-rfc2547bis-03 */
-    { SAFNUM_LAB_VPNMULCAST, "Labeled Multicast" },
-    { SAFNUM_LAB_VPNUNIMULC, "Labeled Unicast+Multicast" },
+    { SAFNUM_LAB_VPNUNICAST, "Labeled VPN Unicast" },        /* draft-rosen-rfc2547bis-03 */
+    { SAFNUM_LAB_VPNMULCAST, "Labeled VPN Multicast" },
+    { SAFNUM_LAB_VPNUNIMULC, "Labeled VPN Unicast+Multicast" },
     { 0, NULL },
 };
 
@@ -333,6 +333,8 @@
     return(1 + length);
 }
 
+
+
 /*
  * Decode an MPLS label stack
  */
@@ -415,7 +417,7 @@
                                         case FORMAT_IP_LOC:
                                                 length = 12;
                                                 tvb_memcpy(tvb, ip4addr, offset + 2, 4);   /* IP part of the RD            */
-                                                tvb_memcpy(tvb, ip4addr2, offset +6, 4);   /* IP address of the VPN-IPv4   */
+                                                tvb_memcpy(tvb, ip4addr2, offset +6, 4);   /* IP address of the VPN        */
                                                 snprintf(buf, buflen, "Empty Label Stack RD=%s:%u IP=%s",
                                                                 ip_to_str(ip4addr),
                                                                 tvb_get_ntohs(tvb, offset + 6),
@@ -423,21 +425,47 @@
                                                 break ;
                                         default:
                                                 length = 0 ;
-                                                snprintf(buf, buflen, "Unknown labeled VPN-IPv4 address format");
+                                                snprintf(buf, buflen, "Unknown (0x%04x)labeled VPN address format",rd_type);
                                                 break;
                                 }
                                 break;
                         default:
-                                length = 0 ;
-                                snprintf(buf, buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
-                                break;
+                            length = 0 ;
+                            snprintf(buf, buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
+                            break;
                 }
                 break;
         case AFNUM_INET6:
-                length = 16 ;
-                tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8,offset, sizeof(ip6addr));
-                snprintf(buf, buflen, "%s", ip6_to_str(&ip6addr));
+                switch (safi) {
+                        case SAFNUM_UNICAST: /* only decode unlabeled prefixes */
+                        case SAFNUM_MULCAST:
+                        case SAFNUM_UNIMULC:
+                            length = 16 ;
+                            tvb_memcpy(tvb, ip6addr.u6_addr.u6_addr8,offset, sizeof(ip6addr));
+                            snprintf(buf, buflen, "%s", ip6_to_str(&ip6addr));
+                            break;
+                        default:
+                            length = 0 ;
+                            snprintf(buf, buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
+                            break;
+                }
                 break;
+       case AFNUM_L2VPN:
+                switch (safi) {
+                        case SAFNUM_LAB_VPNUNICAST: /* only labeles prefixes do make sense */
+                        case SAFNUM_LAB_VPNMULCAST:
+                        case SAFNUM_LAB_VPNUNIMULC:
+                            length = 4; /* the next-hop is simply an ipv4 addr */
+                            tvb_memcpy(tvb, ip4addr, offset + 0, 4);
+                            snprintf(buf, buflen, "IP=%s",
+                                     ip_to_str(ip4addr));
+                            break;
+                        default:
+                            length = 0 ;
+                            snprintf(buf, buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
+                            break; 
+                }
+                break;
         default:
                 length = 0 ;
                 snprintf(buf, buflen, "Unknown AFI (%u) value", afi);
@@ -455,6 +483,7 @@
     int                 length;                         /* length of the prefix in byte */
     int                 plen;                           /* length of the prefix in bit  */
     int                 labnum;                         /* number of labels             */
+    int                 ce_id,labblk_off;
     guint8              ip4addr[4],ip4addr2[4];         /* IPv4 address                 */
     guint16             rd_type;                        /* Route Distinguisher type     */
     char                lab_stk[256];                   /* label stack                  */
@@ -551,7 +580,7 @@
                                                 break ;
                                         default:
                                                 length = 0 ;
-                                                snprintf(buf,buflen, "Unknown labeled VPN  address format");
+                                                snprintf(buf,buflen, "Unknown labeled VPN address format");
                                                 break;
                                 }
                                 break;
@@ -562,8 +591,62 @@
                 }
                 break;
         case AFNUM_INET6:
-                 length = decode_prefix6(tvb, offset, buf, buflen) - 1 ;
-                 break;
+                switch (safi) {
+                        case SAFNUM_UNICAST:
+                        case SAFNUM_MULCAST:
+                        case SAFNUM_UNIMULC:
+                            length = decode_prefix6(tvb, offset, buf, buflen) - 1 ;
+                            break;
+                default:
+                        length = 0 ;
+                        snprintf(buf,buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
+                        break;
+                }
+                break;
+       case AFNUM_L2VPN:
+                switch (safi) {
+                        case SAFNUM_LAB_VPNUNICAST:
+                        case SAFNUM_LAB_VPNMULCAST:
+                        case SAFNUM_LAB_VPNUNIMULC:
+                                plen =  tvb_get_ntohs(tvb,offset);
+                                rd_type=tvb_get_ntohs(tvb,offset+2);
+                                ce_id=tvb_get_ntohs(tvb,offset+10);
+                                labblk_off=tvb_get_ntohs(tvb,offset+12);
+                                labnum = decode_MPLS_stack(tvb, offset + 14, lab_stk, sizeof(lab_stk));
+ 
+                                switch (rd_type) {
+                                        case FORMAT_AS2_LOC:
+                                                tvb_memcpy(tvb, ip4addr, offset + 6, 4);
+                                                snprintf(buf,buflen, "RD: %u:%s, CE-ID: %u, Label-Block Offset: %u, Label Base %s",
+                                                         tvb_get_ntohs(tvb, offset + 4),
+                                                         ip_to_str(ip4addr),
+                                                         ce_id,
+                                                         labblk_off,
+                                                         lab_stk);
+                                                break ;
+                                        case FORMAT_IP_LOC:
+                                                tvb_memcpy(tvb, ip4addr, offset + 4, 4);
+                                                snprintf(buf,buflen, "RD: %s:%u, CE-ID: %u, Label-Block Offset: %u, Label Base %s",
+                                                         ip_to_str(ip4addr),
+                                                         tvb_get_ntohs(tvb, offset + 8),
+                                                         ce_id,
+                                                         labblk_off,
+                                                         lab_stk);
+                                                break ;
+                                        default:
+                                                length = 0 ;
+                                                snprintf(buf,buflen, "Unknown labeled VPN address format");
+                                                break;
+                                }
+                            /* FIXME there are subTLVs left to decode ... for now lets omit them */
+                            length=plen+1; /* should be 2 but length+1 is returned at the end */
+                            break;
+                default:
+                        length = 0 ;
+                        snprintf(buf, buflen, "Unknown SAFI (%u) for AFI %u", safi, afi);
+                        break;
+                }
+                break;
         default:
                 length = 0 ;
                 snprintf(buf,buflen, "Unknown AFI (%u) value", afi);
@@ -864,8 +947,8 @@
     char            *as_path_str = NULL;        /* AS_PATH string           */
     char            *communities_str = NULL;    /* COMMUNITIES string       */
     char            *cluster_list_str = NULL;   /* CLUSTER_LIST string      */
-    char            *ext_com_str = NULL;        /* EXTENDED COMMUNITY list  */
     char            junk_buf[256];              /* tmp                      */
+    int             junk_buf_len;               /* tmp len                  */
     guint8          ipaddr[4];                  /* IPv4 address             */
 
     hlen = tvb_get_ntohs(tvb, offset + BGP_MARKER_SIZE);
@@ -1138,22 +1221,20 @@
                    (o + current attribute + aoff bytes to first tuple) */
                 q = o + i + aoff;
                 end = q + tlen;
-                ext_com_str = malloc((tlen / 8)*MAX_SIZE_OF_EXT_COM_NAMES);
-                if (ext_com_str == NULL) break;
-                ext_com_str[0] = '\0';
+                junk_buf_len=0;
                 while (q < end) {
                         ext_com = tvb_get_ntohs(tvb, q);
-                        snprintf(junk_buf, sizeof(junk_buf), "%s", val_to_str(ext_com,bgpext_com_type,"Unknown"));
-                        strncat(ext_com_str, junk_buf, sizeof(junk_buf));
+                        junk_buf_len=snprintf(junk_buf+junk_buf_len,sizeof(junk_buf),"%s",
+                                              val_to_str(ext_com,bgpext_com_type,"Unknown"));
                         q = q + 8;
-                        if (q < end) strncat(ext_com_str, ",", 1);
+                        if (q < end) junk_buf_len=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ", ");
                 }
+                junk_buf[junk_buf_len]='\0';
                 ti = proto_tree_add_text(subtree,tvb,o+i,tlen+aoff,
                         "%s: %s (%u %s)",
                         val_to_str(bgpa.bgpa_type,bgpattr_type,"Unknown"),
-                        ext_com_str, tlen + aoff,
+                        junk_buf, tlen + aoff,
                         (tlen + aoff == 1) ? "byte" : "bytes");
-                free(ext_com_str);
                 break;
 
 	    default:
@@ -1460,7 +1541,7 @@
 		    "Subsequent address family identifier: %s (%u)",
 		    val_to_str(saf, bgpattr_nlri_safi, saf >= 128 ? "Vendor specific" : "Unknown"),
 		    saf);
-                if (af != AFNUM_INET && af != AFNUM_INET6) {
+                if (af != AFNUM_INET && af != AFNUM_INET6 && af != AFNUM_L2VPN) {
                     /*
                      * The addresses don't contain lengths, so if we
                      * don't understand the address family type, we
@@ -1512,7 +1593,7 @@
                 }
                 tlen -= off;
 		aoff += off;
-
+                
 		ti = proto_tree_add_text(subtree2, tvb, o + i + aoff, tlen,
 			"Network layer reachability information (%u %s)",
 			tlen, (tlen == 1) ? "byte" : "bytes");
@@ -1549,10 +1630,10 @@
                         while (tlen > 0) {
                                 advance = decode_prefix_MP(af, saf, tvb, o + i + aoff , junk_buf, sizeof(junk_buf)) ;
                                 proto_tree_add_text(subtree3, tvb, o + i + aoff, advance, "%s", junk_buf) ;
-                                if (advance==1)  /* catch if this is a unknown AFI type*/
-                                        break;
 		                tlen -= advance;
 		                aoff += advance;
+                                if (advance==1)  /* catch if this is a unknown AFI type*/
+                                        break;
                         }
                 }
                 break;
@@ -1594,63 +1675,64 @@
                 } else {
                         q = o + i + aoff ;
                         end = o + i + aoff + tlen ;
-                        ext_com_str = malloc(MAX_SIZE_OF_EXT_COM_NAMES+MAX_SIZE_OF_IP_ADDR_STRING*2+1) ;
-                        if (ext_com_str == NULL) break ;
                         ti = proto_tree_add_text(subtree2,tvb,q,tlen, "Carried Extended communities");
                         subtree3 = proto_item_add_subtree(ti,ett_bgp_extended_communities) ;
 
+                        junk_buf_len=0;
                         while (q < end) {
-                            ext_com_str[0] = '\0' ;
                             ext_com = tvb_get_ntohs(tvb,q) ;
-                            snprintf(junk_buf, sizeof(junk_buf), "%s", val_to_str(ext_com,bgpext_com_type,"Unknown"));
-                            strncat(ext_com_str,junk_buf,sizeof(junk_buf));
+                            junk_buf_len=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf), "%s",
+                                                  val_to_str(ext_com,bgpext_com_type,"Unknown"));
                             switch (ext_com) {
                             case BGP_EXT_COM_RT_0:
                             case BGP_EXT_COM_RO_0:
-                                snprintf(junk_buf, sizeof(junk_buf), ": %u%s%d",tvb_get_ntohs(tvb,q+2),":",tvb_get_ntohl(tvb,q+4));
+                                junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": %u%s%d",
+                                                       tvb_get_ntohs(tvb,q+2),":",tvb_get_ntohl(tvb,q+4));
                                 break ;
                             case BGP_EXT_COM_RT_1:
                             case BGP_EXT_COM_RO_1:
                                 tvb_memcpy(tvb,ipaddr,q+2,4);
-                                snprintf(junk_buf, sizeof(junk_buf), ": %s%s%u",ip_to_str(ipaddr),":",tvb_get_ntohs(tvb,q+6));
+                                junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": %s%s%u",
+                                                       ip_to_str(ipaddr),":",tvb_get_ntohs(tvb,q+6));
                                 break;
                             case BGP_EXT_COM_VPN_ORIGIN:
                             case BGP_EXT_COM_OSPF_RID:
                                 tvb_memcpy(tvb,ipaddr,q+2,4);
-                                snprintf(junk_buf, sizeof(junk_buf), ": %s",ip_to_str(ipaddr));
+                                junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": %s",
+                                                       ip_to_str(ipaddr));
                                 break;
                             case BGP_EXT_COM_OSPF_RTYPE: 
                                 tvb_memcpy(tvb,ipaddr,q+2,4);
-                                snprintf(junk_buf, sizeof(junk_buf), ": Area:%s %s",
+                                junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": Area:%s %s",
                                          ip_to_str(ipaddr),
                                          val_to_str(tvb_get_guint8(tvb,q+6),bgpext_ospf_rtype,"Unknown"));
 				/* print OSPF Metric type if selected */
 				/* always print E2 even if not external route -- receiving router should ignore */
                                 if ( (tvb_get_guint8(tvb,q+7)) & BGP_OSPF_RTYPE_METRIC_TYPE ) { 
-                                    strcat(junk_buf," E2");
+                                    junk_buf_len+=snprintf(junk_buf+junk_buf_len,sizeof(junk_buf)-junk_buf_len," E2");
                                 } else if (tvb_get_guint8(tvb,q+6)==(BGP_OSPF_RTYPE_EXT ||BGP_OSPF_RTYPE_NSSA ) ) {
-                                    strcat(junk_buf, " E1");
+                                    junk_buf_len+=snprintf(junk_buf+junk_buf_len,sizeof(junk_buf)-junk_buf_len," E1");
                                 }
                                 break;
                             case BGP_EXT_COM_LINKBAND:
                                 tvb_memcpy(tvb,ipaddr,q+2,4); /* need to check on IEEE format on all platforms */
-                                snprintf(junk_buf, sizeof(junk_buf), ": %f bytes per second",(double)*ipaddr);
+                                junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": %.3f Mbps",
+                                                       ((double)*ipaddr)*8/1000000);
                                 break;
                             case BGP_EXT_COM_L2INFO:
-                                snprintf(junk_buf, sizeof(junk_buf), ": %s:Control Flags [0x%02x]:MTU %u",
+                                junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, ": %s:Control Flags [0x%02x]:MTU %u",
                                          val_to_str(tvb_get_guint8(tvb,q+2),bgp_l2vpn_encaps,"Unknown"),
                                          tvb_get_guint8(tvb,q+3),
                                          tvb_get_ntohs(tvb,q+4));
                               break;
                             default:
-                                snprintf(junk_buf, sizeof(junk_buf), " ");
+                                junk_buf_len+=snprintf(junk_buf+junk_buf_len, sizeof(junk_buf)-junk_buf_len, " ");
                                 break ;
-			  }
-			  strncat(ext_com_str,junk_buf,sizeof(junk_buf));
-			  proto_tree_add_text(subtree3,tvb,q,8, "%s",ext_com_str);
-			  q = q + 8 ;
+                            }
+                            junk_buf[junk_buf_len]='\0';
+                            proto_tree_add_text(subtree3,tvb,q,8, "%s",junk_buf);
+                            q = q + 8 ;
                         }
-                        free(ext_com_str) ;
                 }
                 break;
 	    default: