[Bro] BRO with MPLS + 802.1 Q vlan

Robin Sommer robin at icir.org
Mon Feb 22 09:19:16 PST 2010


On Mon, Feb 22, 2010 at 08:09 -0500, Seth Hall wrote:

> Bro doesn't support MPLS packets currently.  Patches are welcome  
> however. :)

I have one for MPLS actually, it's attached. However, it is old and
hasn't seen much testing, which is why it never made it into the
distribution. It may also not apply cleanly anymore. 

The patch adds a new option "mpls_link" that needs to be redefed to
true.

Robin

-- 
Robin Sommer * Phone +1 (510) 666-2886 * robin at icir.org 
ICSI/LBNL    * Fax   +1 (510) 666-2956 *   www.icir.org
-------------- next part --------------
Index: NetVar.h
===================================================================
--- NetVar.h	(revision 4921)
+++ NetVar.h	(working copy)
@@ -53,6 +53,7 @@
 
 extern int encap_hdr_size;
 extern int udp_tunnel_port;
+extern int mpls_link;
 
 extern double frag_timeout;
 
Index: NetVar.cc
===================================================================
--- NetVar.cc	(revision 4921)
+++ NetVar.cc	(working copy)
@@ -50,6 +50,7 @@
 
 int encap_hdr_size;
 int udp_tunnel_port;
+int mpls_link;
 
 double frag_timeout;
 
@@ -337,6 +338,8 @@
 	encap_hdr_size = opt_internal_int("encap_hdr_size");
 
 	udp_tunnel_port = opt_internal_int("udp_tunnel_port") & ~UDP_PORT_MASK;
+        
+	mpls_link = opt_internal_int("mpls_link");
 
 	frag_timeout = opt_internal_double("frag_timeout");
 
Index: bro.bif
===================================================================
--- bro.bif	(revision 4921)
+++ bro.bif	(working copy)
@@ -716,6 +716,11 @@
 	return map_conn_type(p->PortType());
 	%}
 
+function get_port_number%(p: port%): count
+	%{
+	return new Val(p->Port(), TYPE_COUNT);
+	%}
+
 function current_time%(%): time
 	%{
 	return new Val(current_time(), TYPE_TIME);
Index: PktSrc.cc
===================================================================
--- PktSrc.cc	(revision 4921)
+++ PktSrc.cc	(working copy)
@@ -204,16 +204,73 @@
 
 	current_timestamp = next_timestamp;
 
+	int pkt_hdr_size = hdr_size;
+        
+	// MPLS decapsulation.
+	if ( mpls_link )
+		{
+		// Unfortunately some packets on the link might have MPLS labels
+		// while others don't. That means we need to ask the link-layer if
+		// labels are in place. 
+		// 
+		// We only support MPLS over DLT_PPP_SERIAL links currently.
+		// DLT_PPP_SERIAL is "HDLC-like framing for PPP encapsulated packets"
+		// (RFC 1662). 
+		bool have_mpls = false;
+		switch ( datalink ) {
+			case 0x32:	// PPP_SERIAL
+				{
+				// Skip "HDLC-like" frame (per RFC 1662, 3.1. Note that the
+				// flags don't show up in our input.)
+				data += 2;
+				
+				// Get PPP protocol.
+				int protocol = (data[0] << 8) + data[1];
+				
+				if ( protocol == 0x0281 ) 
+					// MPLS Unicast
+					have_mpls = true;
+				else if ( protocol != 0x0021 && protocol != 0x0057 )
+					{
+					// Neither IPv4 nor IPv6.
+					sessions->Weird("non_ip_packet_in_ppp_encapsulation", &hdr, data);
+					data = 0;
+					return;
+					}
+				
+                // Skip protocol field.
+				data += 2;
+                break;   
+				}
+		
+			default:
+				error(fmt("link-layer %d not supported for MPLS traffic", datalink));
+		}
+		
+		if ( have_mpls )
+			{
+			// Skip the MPLS label stack.
+			bool end_of_stack = false;
+			while ( ! end_of_stack )
+				{
+				end_of_stack = *(data + 2) & 0x01;
+				data += 4;
+				}
+			}
+		
+		pkt_hdr_size = 0;
+		}
+	
 	if ( pseudo_realtime )
 		{
 		current_pseudo = CheckPseudoTime();
-		net_packet_arrival(current_pseudo, &hdr, data, hdr_size, this);
+		net_packet_arrival(current_pseudo, &hdr, data, pkt_hdr_size, this);
 		if ( ! first_wallclock )
 			first_wallclock = current_time(true);
 		}
 
 	else
-		net_packet_arrival(current_timestamp, &hdr, data, hdr_size, this);
+		net_packet_arrival(current_timestamp, &hdr, data, pkt_hdr_size, this);
 
 	data = 0;
 	}
@@ -437,6 +494,11 @@
 	if ( PrecompileFilter(0, filter) && SetFilter(0) )
 		{
 		SetHdrSize();
+		
+		if ( closed )
+			// Couldn't get header size.
+			return;
+		
 		fprintf(stderr, "listening on %s\n", interface);
 		}
 	else
@@ -458,6 +520,10 @@
 		{
 		SetHdrSize();
 
+		if ( closed )
+			// Couldn't get header size.
+			return;
+		
 #ifdef USE_SELECT_LOOP
 		// We don't put file sources into non-blocking mode as
 		// otherwise we would not be able to identify the EOF
@@ -683,6 +749,9 @@
 		return 16;
 #endif
 
+	case 0x32:	// PPP_SERIAL
+		return 4;
+        
 	case DLT_RAW:
 		return 0;
 	}


More information about the Bro mailing list