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:
parent
04fa3b29f5
commit
a974ba0b70
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=130413
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user