Date: Thu, 10 Jul 2003 04:22:46 +0400 (MSD) From: Gleb Smirnoff <glebius@cell.sick.ru> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/54295: [PATCH] ng_rfc1490(4) does not support Cisco encapsulation Message-ID: <200307100022.h6A0MkcM074121@cell.sick.ru> Resent-Message-ID: <200307100030.h6A0UKWF071028@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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@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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200307100022.h6A0MkcM074121>