kern/54295: [PATCH] ng_rfc1490(4) does not support Cisco encapsulation

Gleb Smirnoff glebius at cell.sick.ru
Wed Jul 9 17:30:22 PDT 2003


>Number:         54295
>Category:       kern
>Synopsis:       [PATCH] ng_rfc1490(4) does not support Cisco encapsulation
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul 09 17:30:20 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator:     Gleb Smirnoff
>Release:        FreeBSD 4.8-PRERELEASE i386
>Organization:
Bestcom JSC
>Environment:
System: FreeBSD cell.sick.ru 4.8-PRERELEASE FreeBSD 4.8-PRERELEASE #10: Fri Feb 21 22:03:32 MSK 2003 root at cell.sick.ru:/usr/obj/usr/src/sys/NUCLEUS i386

>Description:
	ng_rfc1490(4) is usually put on top of ng_frame_relay(4).
	In some situations remote link of frame relay channel may
	use Cisco encapsulation, instead of IETF RFC1490/2427.

	Of course, Cisco standards are nothing to do with RFC1490/2427,
	but I suppose it'll be better to implement cisco encapsulation in
	ng_rfc1490(4) rather than create a separate node, because
	both encapsulations are used on top of frame relay, and thus
	ng_rfc1490 is connected to ng_frame_relay.

>How-To-Repeat:
	If the remote side of frame relay connection is Cisco with
	configuration line

	encapsulation frame-relay cisco

	, then ng_rfc1490 drops all frames coming on its downstream hook.
>Fix:

	The following patch adds support for cisco encapsulation to
	ng_rfc1490(4). The node can be switched to 3 different 
	methods: 

	1) NLPID value indicating IP
		see RFC2427, chapter 7, fig.1
	2) NLPID value indicating SNAP, SNAP indicating IP
		see RFC2427, chapter 7, fig.2
	3) Cisco encapsulation
		see http://www.cisco.com/warp/public/121/frf8modes.pdf

	Switching is done by sending NGM_RFC1490_SETENCAP control message
	to the node with one argument - number of the method. Current
	method is returned by NGM_RFC1490_GETENCAP control message.

	Looking at ng_rfc1490's code I have noticed, that it can understand
	encapsulations 1 and 2, but _always_ sends data to downstream
	using encapsulation 1. I suppose this is a bug. The following patch
	fixes this: node can be switched to mode 2, in which it will send
	data using SNAP field abd ethertype. Moreover if node recevies SNAP
	frame it switches itself to method 2.
	Autoswitching to Cisco mode is not implemented, cause it can not
	be autodetected easily.

	Also patch corrects some errors (typos?) in table where implemented
	protocols are marked with "*". I removed "*" from SNAP frames carrying
	ARP, and inserted IP there.

	Here is the patch:

--- ng_rfc1490.c.orig	Thu Jul 10 00:37:20 2003
+++ ng_rfc1490.c	Thu Jul 10 03:21:30 2003
@@ -61,6 +61,7 @@
 
 #include <netgraph/ng_message.h>
 #include <netgraph/netgraph.h>
+#include <netgraph/ng_parse.h>
 #include <netgraph/ng_rfc1490.h>
 
 /*
@@ -83,6 +84,7 @@
 	hook_p  downlink;
 	hook_p  ppp;
 	hook_p  inet;
+	u_int8_t encapsulation;
 };
 typedef struct ng_rfc1490_private *priv_p;
 
@@ -94,6 +96,25 @@
 static ng_rcvdata_t	ng_rfc1490_rcvdata;
 static ng_disconnect_t	ng_rfc1490_disconnect;
 
+/* List of commands and how to convert arguments to/from ASCII */
+static const struct ng_cmdlist ng_rfc1490_cmds[] = {
+	{
+	  NGM_RFC1490_COOKIE,
+	  NGM_RFC1490_SET_ENCAP,
+	  "setencap",
+	  &ng_parse_int8_type,
+	  NULL
+	},
+	{
+	  NGM_RFC1490_COOKIE,
+	  NGM_RFC1490_GET_ENCAP,
+	  "getencap",
+	  NULL,
+	  &ng_parse_int8_type
+	},
+	{ 0 }
+};
+
 /* Node type descriptor */
 static struct ng_type typestruct = {
 	NG_VERSION,
@@ -108,7 +129,7 @@
 	ng_rfc1490_rcvdata,
 	ng_rfc1490_rcvdata,
 	ng_rfc1490_disconnect,
-	NULL
+	ng_rfc1490_cmds
 };
 NETGRAPH_INIT(rfc1490, &typestruct);
 
@@ -168,14 +189,55 @@
 }
 
 /*
- * Receive a control message. We don't support any special ones.
+ * Receive a control message.
  */
 static int
 ng_rfc1490_rcvmsg(node_p node, struct ng_mesg *msg,
 		  const char *raddr, struct ng_mesg **rp)
 {
+	const priv_p priv = node->private;
+	struct ng_mesg *resp = NULL;
+	int error = 0;
+
+	if (msg->header.typecookie == NGM_RFC1490_COOKIE) {
+		switch (msg->header.cmd) {
+		case NGM_RFC1490_SET_ENCAP:
+		  {
+			u_int8_t encap = (u_int8_t )*(msg->data);
+
+			/* Sanity check */
+			if (msg->header.arglen != sizeof(u_int8_t) ||
+			    encap > NG_RFC1490_ENCAP_CISCO ) {
+				error = EINVAL;
+				goto done;
+			}
+			priv->encapsulation = encap;
+			break;
+		  }
+		 case NGM_RFC1490_GET_ENCAP:
+		  {
+			NG_MKRESPONSE(resp, msg, sizeof(u_int8_t), M_NOWAIT);
+			if (resp == NULL) {
+				error = ENOMEM;
+				goto done;
+			}
+			*(resp->data) = priv->encapsulation;
+			break;
+		  }
+		default:
+			error = EINVAL;
+			break;
+		}
+	} else
+		error = EINVAL;
+
+done:	if (rp)
+		*rp = resp;
+	else if (resp)
+		FREE(resp, M_NETGRAPH);
+
 	FREE(msg, M_NETGRAPH);
-	return (EINVAL);
+	return (error);
 }
 
 /*
@@ -185,15 +247,15 @@
  *                            Q.922 control
  *                                 |
  *                                 |
- *            --------------------------------------------
- *            | 0x03                                     |
- *           UI                                       I Frame
- *            |                                          |
- *      ---------------------------------         --------------
- *      | 0x08  | 0x81  |0xCC   |0xCF   | 0x00    |..01....    |..10....
- *      |       |       |       |       | 0x80    |            |
- *     Q.933   CLNP    IP(*)   PPP(*)  SNAP     ISO 8208    ISO 8208
- *      |                    (rfc1973)  |       Modulo 8    Modulo 128
+ *            ---------------------------------------------------------------------
+ *            | 0x03                                     |                        |
+ *           UI                                       I Frame                   Cisco
+ *            |                                          |                  Encapsulation
+ *      ---------------------------------         --------------                  |
+ *      | 0x08  | 0x81  |0xCC   |0xCF   | 0x00    |..01....    |..10....   --------------
+ *      |       |       |       |       | 0x80    |            |           |0x800       |
+ *     Q.933   CLNP    IP(*)   PPP(*)  SNAP     ISO 8208    ISO 8208       |            |
+ *      |                    (rfc1973)  |       Modulo 8    Modulo 128     IP(*)     Others
  *      |                               |
  *      --------------------           OUI
  *      |                  |            |
@@ -203,9 +265,9 @@
  *      |               0x70        PID                     Ethertype
  *      |                            |                       |
  *      -------------------        --------------...        ----------
- *      |0x51 |0x4E |     |0x4C    |0x1   |0xB  |           |0x806   |
+ *      |0x51 |0x4E |     |0x4C    |0x1   |0xB  |           |0x800   |
  *      |     |     |     |        |      |     |           |        |
- *     7776  Q.922 Others 802.2   802.3  802.6 Others       ARP(*)  Others
+ *     7776  Q.922 Others 802.2   802.3  802.6 Others       IP(*)  Others
  *
  *
  */
@@ -230,6 +292,9 @@
 			ERROUT(ENOBUFS);
 		ptr = start = mtod(m, const u_char *);
 
+		if (priv->encapsulation == NG_RFC1490_ENCAP_CISCO)
+			goto switch_on_etype;
+
 		/* Must be UI frame */
 		if (*ptr++ != HDLC_UI)
 			ERROUT(0);
@@ -244,8 +309,12 @@
 			if (OUICMP(ptr, 0, 0, 0)) {	/* It's an ethertype */
 				u_int16_t etype;
 
+				/* We have just received a SNAP frame, so
+				   we will switch to SNAP mode */
+				priv->encapsulation = NG_RFC1490_ENCAP_SNAP;
+
 				ptr += 3;
-				etype = ntohs(*((const u_int16_t *)ptr));
+switch_on_etype:		etype = ntohs(*((const u_int16_t *)ptr));
 				ptr += 2;
 				m_adj(m, ptr - start);
 				switch (etype) {
@@ -292,11 +361,38 @@
 		mtod(m, u_char *)[1] = NLPID_PPP;
 		NG_SEND_DATA(error, priv->downlink, m, meta);
 	} else if (hook == priv->inet) {
-		M_PREPEND(m, 2, M_DONTWAIT);	/* Prepend IP NLPID */
-		if (!m)
-			ERROUT(ENOBUFS);
-		mtod(m, u_char *)[0] = HDLC_UI;
-		mtod(m, u_char *)[1] = NLPID_IP;
+		switch (priv->encapsulation) {
+		  case NG_RFC1490_ENCAP_IETF:
+			M_PREPEND(m, 2, M_DONTWAIT);	/* Prepend IP NLPID */
+			if (!m)
+				ERROUT(ENOBUFS);
+		  	mtod(m, u_char *)[0] = HDLC_UI;
+		  	mtod(m, u_char *)[1] = NLPID_IP;
+			break;
+		  case NG_RFC1490_ENCAP_SNAP:
+			/*
+			 *  According to RFC2427 frame should begin with
+			 *  HDLC_UI  PAD  NLIPID  OUI	   PID
+			 *  03 	    00   80      00 00 00  08 00
+			 */
+			M_PREPEND(m, 8, M_DONTWAIT);
+			if (!m)
+				ERROUT(ENOBUFS);
+		  	mtod(m, u_char *)[0] = HDLC_UI;
+		  	mtod(m, u_char *)[1] = 0x00;			/* PAD */
+		  	mtod(m, u_char *)[2] = NLPID_SNAP;
+			bzero((char *)(mtod(m, u_char *) + 3), 3);	/* OUI 0-0-0 */
+		  	*((u_int16_t *)mtod(m, u_int16_t *) + 6/sizeof(u_int16_t))
+						= htons(ETHERTYPE_IP);	/* PID */
+			break;
+		  case NG_RFC1490_ENCAP_CISCO:
+			M_PREPEND(m, 2, M_DONTWAIT);	/* Prepend IP ethertype */
+			if (!m)
+				ERROUT(ENOBUFS);
+		  	*((u_int16_t *)mtod(m, u_int16_t *)) = htons(ETHERTYPE_IP);
+			break;
+		  default:
+		}
 		NG_SEND_DATA(error, priv->downlink, m, meta);
 	} else
 		panic(__FUNCTION__);
--- ng_rfc1490.h.orig	Thu Jul 10 00:42:52 2003
+++ ng_rfc1490.h	Thu Jul 10 02:14:20 2003
@@ -52,4 +52,15 @@
 #define NG_RFC1490_HOOK_INET		"inet"
 #define NG_RFC1490_HOOK_PPP		"ppp"
 
+/* Netgraph commands */
+enum {
+        NGM_RFC1490_SET_ENCAP = 1,         /* sets encapsulation method */
+        NGM_RFC1490_GET_ENCAP,             /* gets current encapsulation method */
+};
+
+/* Encapsulation types */
+#define NG_RFC1490_ENCAP_IETF		0  /* see RFC2427, chapter 7, table 1 */
+#define NG_RFC1490_ENCAP_SNAP		1  /* see RFC2427, chapter 7, table 2 */
+#define NG_RFC1490_ENCAP_CISCO		2  /* Cisco's encapsulation */
+
 #endif /* _NETGRAPH_RFC1490_H_ */
--- ng_rfc1490.4.orig	Thu Jul 10 03:12:39 2003
+++ ng_rfc1490.4	Thu Jul 10 03:19:55 2003
@@ -83,7 +83,14 @@
 Transmits and receives PPP frames.
 .El
 .Sh CONTROL MESSAGES
-This node type only supports the generic control messages.
+This node type supports the generic control messages, plus the following:
+.Bl -tag -width foo
+.It Dv NGM_RFC1490_SETENCAP
+This command sets encapsulation method on the node. Currently 3 methods are supported:
+two desribed in RFC1490/2427, and Cisco encapsulation. This command takes u_int8_t as
+an argument. Methods are numbered from 0 to 2, respectivly.
+.It Dv NGM_RFC1490_GETENCAP
+This command returns current encapsulation method on the node as u_int8_t.
 .Sh SHUTDOWN
 This node shuts down upon receipt of a
 .Dv NGM_SHUTDOWN
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list