1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-13 10:02:38 +00:00

Add the capacity for the rfc1490 node to handle cisco style encasulation

which is often used alongside rfc1490 in frame relay links.

Submitted by:	Gleb Smirnoff <glebius@cell.sick.ru>
This commit is contained in:
Julian Elischer 2004-06-13 15:44:00 +00:00
parent 04fa3b29f5
commit a974ba0b70
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=130413
3 changed files with 177 additions and 25 deletions

View File

@ -62,7 +62,7 @@ hooks are used to transmit and receive raw IP frames and PPP frames,
respectively. PPP frames are transmitted and received according to
RFC 1973; in particular, frames appearing on the
.Dv ppp
hook begin with the PPP protocol number. The
hook begin with the PPP protocol number. The
.Dv ethernet
hook can be used to transmit and receive Ethernet frames (without a
checksum) in RFC 1490's bridging format.
@ -88,7 +88,25 @@ Transmits and receives raw IP frames.
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 for the node.
The desired method must be passed as a string message argument,
and must be one of the following supported encapsulation modes:
.Bl -tag
.It Qq ietf-ip
IP packets are sent using simple RFC1490/2427 encapsulation.
.It Qq ietf-snap
IP packets are sent inside SNAP frames.
Also conforms to RFC1490/2427.
.It Qq cisco
IP packets are sent and received using proprietary Cisco encapsulation
method.
.El
.It Dv NGM_RFC1490_GETENCAP
This command returns current encapsulation method on the node.
.El
.Sh SHUTDOWN
This node shuts down upon receipt of a
.Dv NGM_SHUTDOWN
@ -111,6 +129,9 @@ Not all of RFC 1490 is implemented.
.%T "PPP in Frame Relay"
.%O RFC 1973
.Re
.Rs
http://www.cisco.com/warp/public/121/frf8modes.pdf
.Re
.Sh HISTORY
The
.Nm

View File

@ -61,6 +61,7 @@
#include <netgraph/ng_message.h>
#include <netgraph/netgraph.h>
#include <netgraph/ng_parse.h>
#include <netgraph/ng_rfc1490.h>
/*
@ -78,12 +79,34 @@
#define NLPID_ESIS 0x82
#define NLPID_ISIS 0x83
#define ERROUT(x) do { error = (x); goto done; } while (0)
/* Encapsulation methods we understand */
enum {
NG_RFC1490_ENCAP_IETF_IP = 1, /* see RFC2427, chapter 7, table 1 */
NG_RFC1490_ENCAP_IETF_SNAP, /* see RFC2427, chapter 7, table 2 */
NG_RFC1490_ENCAP_CISCO, /* Cisco's proprietary encapsulation */
};
struct ng_rfc1490_encap_t {
u_int8_t method;
const char *name;
};
static const struct ng_rfc1490_encap_t ng_rfc1490_encaps[] = {
{ NG_RFC1490_ENCAP_IETF_IP, "ietf-ip" },
{ NG_RFC1490_ENCAP_IETF_SNAP, "ietf-snap" },
{ NG_RFC1490_ENCAP_CISCO, "cisco" },
{ 0, NULL},
};
/* Node private data */
struct ng_rfc1490_private {
hook_p downlink;
hook_p ppp;
hook_p inet;
hook_p ethernet;
const struct ng_rfc1490_encap_t *enc;
};
typedef struct ng_rfc1490_private *priv_p;
@ -95,6 +118,25 @@ static ng_newhook_t ng_rfc1490_newhook;
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_string_type,
NULL
},
{
NGM_RFC1490_COOKIE,
NGM_RFC1490_GET_ENCAP,
"getencap",
NULL,
&ng_parse_string_type
},
{ 0 }
};
/* Node type descriptor */
static struct ng_type typestruct = {
.version = NG_ABI_VERSION,
@ -105,6 +147,7 @@ static struct ng_type typestruct = {
.newhook = ng_rfc1490_newhook,
.rcvdata = ng_rfc1490_rcvdata,
.disconnect = ng_rfc1490_disconnect,
.cmdlist = ng_rfc1490_cmds,
};
NETGRAPH_INIT(rfc1490, &typestruct);
@ -125,6 +168,9 @@ ng_rfc1490_constructor(node_p node)
if (priv == NULL)
return (ENOMEM);
/* Initialize to default encapsulation method - ietf-ip */
priv->enc = ng_rfc1490_encaps;
NG_NODE_SET_PRIVATE(node, priv);
/* Done */
@ -161,13 +207,65 @@ ng_rfc1490_newhook(node_p node, hook_p hook, const char *name)
}
/*
* Receive a control message. We don't support any special ones.
* Receive a control message.
*/
static int
ng_rfc1490_rcvmsg(node_p node, item_p item, hook_p lasthook)
{
NG_FREE_ITEM(item);
return (EINVAL);
const priv_p priv = NG_NODE_PRIVATE(node);
struct ng_mesg *msg;
struct ng_mesg *resp = NULL;
int error = 0;
NGI_GET_MSG(item, msg);
if (msg->header.typecookie == NGM_RFC1490_COOKIE) {
switch (msg->header.cmd) {
case NGM_RFC1490_SET_ENCAP:
{
const struct ng_rfc1490_encap_t *enc;
char *s;
size_t len;
if (msg->header.arglen == 0)
ERROUT(EINVAL);
s = (char *)msg->data;
len = msg->header.arglen - 1;
/* Search for matching encapsulation method */
for (enc = ng_rfc1490_encaps; enc->method != 0; enc++ )
if ((strlen(enc->name) == len) &&
!strncmp(enc->name, s, len))
break; /* found */
if (enc->method != 0)
priv->enc = enc;
else
error = EINVAL;
break;
}
case NGM_RFC1490_GET_ENCAP:
NG_MKRESPONSE(resp, msg, strlen(priv->enc->name) + 1, M_NOWAIT);
if (resp == NULL)
ERROUT(ENOMEM);
strlcpy((char *)resp->data, priv->enc->name,
strlen(priv->enc->name) + 1);
break;
default:
error = EINVAL;
break;
}
} else
error = EINVAL;
done:
NG_RESPOND_MSG(error, node, item, resp);
NG_FREE_MSG(msg);
return (error);
}
/*
@ -177,15 +275,15 @@ ng_rfc1490_rcvmsg(node_p node, item_p item, hook_p lasthook)
* 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
* | | |
@ -197,13 +295,12 @@ ng_rfc1490_rcvmsg(node_p node, item_p item, hook_p lasthook)
* ------------------- -----------------... ----------
* |0x51 |0x4E | |0x4C |0x7 |0xB | |0x806 |
* | | | | | | | | |
* 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
*
*
*/
#define MAX_ENCAPS_HDR 8
#define ERROUT(x) do { error = (x); goto done; } while (0)
#define OUICMP(P,A,B,C) ((P)[0]==(A) && (P)[1]==(B) && (P)[2]==(C))
static int
@ -224,6 +321,9 @@ ng_rfc1490_rcvdata(hook_p hook, item_p item)
ERROUT(ENOBUFS);
ptr = start = mtod(m, const u_char *);
if (priv->enc->method == NG_RFC1490_ENCAP_CISCO)
goto switch_on_etype;
/* Must be UI frame */
if (*ptr++ != HDLC_UI)
ERROUT(0);
@ -239,7 +339,7 @@ ng_rfc1490_rcvdata(hook_p hook, item_p item)
u_int16_t etype;
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) {
@ -256,7 +356,7 @@ ng_rfc1490_rcvdata(hook_p hook, item_p item)
/* 802.1 bridging */
ptr += 3;
if (*ptr++ != 0x00)
ERROUT(0); /* unknown PID octet 0 */
ERROUT(0); /* unknown PID octet 0 */
if (*ptr++ != 0x07)
ERROUT(0); /* not FCS-less 802.3 */
m_adj(m, ptr - start);
@ -293,11 +393,37 @@ ng_rfc1490_rcvdata(hook_p hook, item_p item)
mtod(m, u_char *)[1] = NLPID_PPP;
NG_FWD_NEW_DATA(error, item, priv->downlink, m);
} 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->enc->method) {
case NG_RFC1490_ENCAP_IETF_IP:
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_IETF_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;
}
NG_FWD_NEW_DATA(error, item, priv->downlink, m);
} else if (hook == priv->ethernet) {
M_PREPEND(m, 8, M_DONTWAIT); /* Prepend NLPID, OUI, PID */

View File

@ -1,4 +1,3 @@
/*
* ng_rfc1490.h
*
@ -45,7 +44,7 @@
/* Node type name */
#define NG_RFC1490_NODE_TYPE "rfc1490"
#define NGM_RFC1490_COOKIE 861060632
#define NGM_RFC1490_COOKIE 1086947474
/* Hook names */
#define NG_RFC1490_HOOK_DOWNSTREAM "downstream"
@ -53,4 +52,10 @@
#define NG_RFC1490_HOOK_PPP "ppp"
#define NG_RFC1490_HOOK_ETHERNET "ethernet"
/* Netgraph commands */
enum {
NGM_RFC1490_SET_ENCAP, /* sets encapsulation method */
NGM_RFC1490_GET_ENCAP, /* gets current encapsulation method */
};
#endif /* _NETGRAPH_NG_RFC1490_H_ */