Move handling of the address and control fields into the PPP node;
they belong there because they are device independent. Also some other misc. fixes.
This commit is contained in:
parent
e6ce529511
commit
d690a6e798
@ -69,6 +69,7 @@
|
||||
#define PROT_CRYPTD 0x0053
|
||||
#define PROT_IP 0x0021
|
||||
#define PROT_IPX 0x002b
|
||||
#define PROT_LCP 0xc021
|
||||
#define PROT_MP 0x003d
|
||||
#define PROT_VJCOMP 0x002d
|
||||
#define PROT_VJUNCOMP 0x002f
|
||||
@ -92,7 +93,7 @@
|
||||
#define MP_LONG_FIRST_FLAG 0x80000000 /* first fragment in frame */
|
||||
#define MP_LONG_LAST_FLAG 0x40000000 /* last fragment in frame */
|
||||
|
||||
#define MP_SEQ_MASK (priv->conf.recvShortSeq ? \
|
||||
#define MP_SEQ_MASK(priv) ((priv)->conf.recvShortSeq ? \
|
||||
MP_SHORT_SEQ_MASK : MP_LONG_SEQ_MASK)
|
||||
|
||||
/* Sign extension of MP sequence numbers */
|
||||
@ -105,7 +106,7 @@
|
||||
#define MP_SHORT_SEQ_DIFF(x,y) (MP_SHORT_EXTEND(x) - MP_SHORT_EXTEND(y))
|
||||
#define MP_LONG_SEQ_DIFF(x,y) (MP_LONG_EXTEND(x) - MP_LONG_EXTEND(y))
|
||||
|
||||
#define MP_SEQ_DIFF(x,y) (priv->conf.recvShortSeq ? \
|
||||
#define MP_SEQ_DIFF(priv,x,y) ((priv)->conf.recvShortSeq ? \
|
||||
MP_SHORT_SEQ_DIFF((x), (y)) : \
|
||||
MP_LONG_SEQ_DIFF((x), (y)))
|
||||
|
||||
@ -190,7 +191,7 @@ static ng_disconnect_t ng_ppp_disconnect;
|
||||
/* Helper functions */
|
||||
static int ng_ppp_input(node_p node, int bypass,
|
||||
int linkNum, struct mbuf *m, meta_p meta);
|
||||
static int ng_ppp_output(node_p node, int bypass,
|
||||
static int ng_ppp_output(node_p node, int bypass, int proto,
|
||||
int linkNum, struct mbuf *m, meta_p meta);
|
||||
static int ng_ppp_mp_input(node_p node, int linkNum,
|
||||
struct mbuf *m, meta_p meta);
|
||||
@ -198,6 +199,7 @@ static int ng_ppp_mp_output(node_p node, struct mbuf *m, meta_p meta);
|
||||
static void ng_ppp_mp_strategy(node_p node, int len, int *distrib);
|
||||
static int ng_ppp_intcmp(const void *v1, const void *v2);
|
||||
static struct mbuf *ng_ppp_addproto(struct mbuf *m, int proto, int compOK);
|
||||
static struct mbuf *ng_ppp_prepend(struct mbuf *m, const void *buf, int len);
|
||||
static int ng_ppp_config_valid(node_p node,
|
||||
const struct ng_ppp_node_config *newConf);
|
||||
static void ng_ppp_update(node_p node, int newConf);
|
||||
@ -222,6 +224,9 @@ NETGRAPH_INIT(ppp, &ng_ppp_typestruct);
|
||||
|
||||
static int *compareLatencies; /* hack for ng_ppp_intcmp() */
|
||||
|
||||
/* Address and control field header */
|
||||
static const u_char ng_ppp_acf[2] = { 0xff, 0x03 };
|
||||
|
||||
#define ERROUT(x) do { error = (x); goto done; } while (0)
|
||||
|
||||
/************************************************************************
|
||||
@ -427,6 +432,16 @@ ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
|
||||
priv->linkStats[linkNum].recvFrames++;
|
||||
priv->linkStats[linkNum].recvOctets += m->m_pkthdr.len;
|
||||
|
||||
/* Strip address and control fields, if present */
|
||||
if (m->m_pkthdr.len >= 2) {
|
||||
if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) {
|
||||
NG_FREE_DATA(m, meta);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
if (bcmp(mtod(m, u_char *), &ng_ppp_acf, 2) == 0)
|
||||
m_adj(m, 2);
|
||||
}
|
||||
|
||||
/* Dispatch incoming frame (if not enabled, to bypass) */
|
||||
return ng_ppp_input(node,
|
||||
!priv->conf.links[linkNum].enableLink, linkNum, m, meta);
|
||||
@ -564,14 +579,8 @@ ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
|
||||
/* FALLTHROUGH */
|
||||
case HOOK_INDEX_ENCRYPT:
|
||||
case HOOK_INDEX_BYPASS:
|
||||
if ((m = ng_ppp_addproto(m, proto,
|
||||
linkNum == NG_PPP_BUNDLE_LINKNUM
|
||||
|| priv->conf.links[linkNum].enableProtoComp)) == NULL) {
|
||||
NG_FREE_META(meta);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
return ng_ppp_output(node,
|
||||
index == HOOK_INDEX_BYPASS, NG_PPP_BUNDLE_LINKNUM, m, meta);
|
||||
return ng_ppp_output(node, index == HOOK_INDEX_BYPASS,
|
||||
proto, NG_PPP_BUNDLE_LINKNUM, m, meta);
|
||||
|
||||
/* Incoming data */
|
||||
case HOOK_INDEX_DECRYPT:
|
||||
@ -697,11 +706,12 @@ ng_ppp_input(node_p node, int bypass, int linkNum, struct mbuf *m, meta_p meta)
|
||||
/* For unknown/inactive protocols, forward out the bypass hook */
|
||||
bypass:
|
||||
if (outHook == NULL) {
|
||||
M_PREPEND(m, 4, M_NOWAIT);
|
||||
if (m == NULL || (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL))
|
||||
u_int16_t hdr[2];
|
||||
|
||||
hdr[0] = htons(linkNum);
|
||||
hdr[1] = htons((u_int16_t)proto);
|
||||
if ((m = ng_ppp_prepend(m, &hdr, 4)) == NULL)
|
||||
return (ENOBUFS);
|
||||
mtod(m, u_int16_t *)[0] = htons(linkNum);
|
||||
mtod(m, u_int16_t *)[1] = htons(proto);
|
||||
outHook = priv->hooks[HOOK_INDEX_BYPASS];
|
||||
}
|
||||
|
||||
@ -714,26 +724,45 @@ ng_ppp_input(node_p node, int bypass, int linkNum, struct mbuf *m, meta_p meta)
|
||||
* Deliver a frame out a link, either a real one or NG_PPP_BUNDLE_LINKNUM
|
||||
*/
|
||||
static int
|
||||
ng_ppp_output(node_p node, int bypass, int linkNum, struct mbuf *m, meta_p meta)
|
||||
ng_ppp_output(node_p node, int bypass,
|
||||
int proto, int linkNum, struct mbuf *m, meta_p meta)
|
||||
{
|
||||
const priv_p priv = node->private;
|
||||
int len, error;
|
||||
|
||||
/* Check for bundle virtual link */
|
||||
if (linkNum == NG_PPP_BUNDLE_LINKNUM) {
|
||||
if (priv->conf.enableMultilink)
|
||||
return ng_ppp_mp_output(node, m, meta);
|
||||
/* If not doing MP, map bundle virtual link to (the only) link */
|
||||
if (linkNum == NG_PPP_BUNDLE_LINKNUM && !priv->conf.enableMultilink)
|
||||
linkNum = priv->activeLinks[0];
|
||||
}
|
||||
|
||||
/* Check link status */
|
||||
if (!bypass && !priv->conf.links[linkNum].enableLink)
|
||||
/* Check link status (if real) */
|
||||
if (linkNum != NG_PPP_BUNDLE_LINKNUM
|
||||
&& !bypass && !priv->conf.links[linkNum].enableLink)
|
||||
return (ENXIO);
|
||||
if (priv->links[linkNum] == NULL) {
|
||||
NG_FREE_DATA(m, meta);
|
||||
return (ENETDOWN);
|
||||
}
|
||||
|
||||
/* Prepend protocol number, possibly compressed */
|
||||
if ((m = ng_ppp_addproto(m, proto,
|
||||
linkNum == NG_PPP_BUNDLE_LINKNUM
|
||||
|| priv->conf.links[linkNum].enableProtoComp)) == NULL) {
|
||||
NG_FREE_META(meta);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
|
||||
/* Special handling for the MP virtual link */
|
||||
if (linkNum == NG_PPP_BUNDLE_LINKNUM)
|
||||
return ng_ppp_mp_output(node, m, meta);
|
||||
|
||||
/* Prepend address and control field (unless compressed) */
|
||||
if (proto == PROT_LCP || !priv->conf.links[linkNum].enableACFComp) {
|
||||
if ((m = ng_ppp_prepend(m, &ng_ppp_acf, 2)) == NULL) {
|
||||
NG_FREE_META(meta);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
}
|
||||
|
||||
/* Deliver frame */
|
||||
len = m->m_pkthdr.len;
|
||||
NG_SEND_DATA(error, priv->links[linkNum], m, meta);
|
||||
@ -824,7 +853,7 @@ ng_ppp_mp_input(node_p node, int linkNum, struct mbuf *m, meta_p meta)
|
||||
|
||||
/* Add fragment to queue, which is reverse sorted by sequence number */
|
||||
CIRCLEQ_FOREACH(qent, &priv->frags, f_qent) {
|
||||
diff = MP_SEQ_DIFF(frag->seq, qent->seq);
|
||||
diff = MP_SEQ_DIFF(priv, frag->seq, qent->seq);
|
||||
if (diff > 0) {
|
||||
CIRCLEQ_INSERT_BEFORE(&priv->frags, qent, frag, f_qent);
|
||||
break;
|
||||
@ -852,7 +881,7 @@ ng_ppp_mp_input(node_p node, int linkNum, struct mbuf *m, meta_p meta)
|
||||
first = qent;
|
||||
break;
|
||||
}
|
||||
nextSeq = (nextSeq + 1) & MP_SEQ_MASK;
|
||||
nextSeq = (nextSeq - 1) & MP_SEQ_MASK(priv);
|
||||
}
|
||||
|
||||
/* Find the last fragment in the possibly newly completed frame */
|
||||
@ -865,7 +894,7 @@ ng_ppp_mp_input(node_p node, int linkNum, struct mbuf *m, meta_p meta)
|
||||
last = qent;
|
||||
break;
|
||||
}
|
||||
nextSeq = (nextSeq - 1) & MP_SEQ_MASK;
|
||||
nextSeq = (nextSeq + 1) & MP_SEQ_MASK(priv);
|
||||
}
|
||||
|
||||
/* We have a complete frame, extract it from the queue */
|
||||
@ -878,7 +907,7 @@ ng_ppp_mp_input(node_p node, int linkNum, struct mbuf *m, meta_p meta)
|
||||
} else {
|
||||
m->m_pkthdr.len += qent->data->m_pkthdr.len;
|
||||
tail->m_next = qent->data;
|
||||
NG_FREE_META(qent->meta); /* drop other frag's metas */
|
||||
NG_FREE_META(qent->meta); /* drop other frags' metas */
|
||||
}
|
||||
while (tail->m_next != NULL)
|
||||
tail = tail->m_next;
|
||||
@ -891,7 +920,7 @@ ng_ppp_mp_input(node_p node, int linkNum, struct mbuf *m, meta_p meta)
|
||||
/* Prune out stale entries in the queue */
|
||||
for (qent = CIRCLEQ_LAST(&priv->frags);
|
||||
qent != (void *) &priv->frags; qent = qnext) {
|
||||
if (MP_SEQ_DIFF(highSeq, qent->seq) <= MP_MAX_SEQ_LINGER)
|
||||
if (MP_SEQ_DIFF(priv, highSeq, qent->seq) <= MP_MAX_SEQ_LINGER)
|
||||
break;
|
||||
qnext = CIRCLEQ_PREV(qent, f_qent);
|
||||
CIRCLEQ_REMOVE(&priv->frags, qent, f_qent);
|
||||
@ -987,15 +1016,6 @@ ng_ppp_mp_output(node_p node, struct mbuf *m, meta_p meta)
|
||||
if (priv->conf.xmitShortSeq) {
|
||||
u_int16_t shdr;
|
||||
|
||||
M_PREPEND(m2, 2, M_NOWAIT);
|
||||
if (m2 == NULL
|
||||
|| (m2->m_len < 2
|
||||
&& (m2 = m_pullup(m2, 2)) == NULL)) {
|
||||
if (!lastFragment)
|
||||
m_freem(m);
|
||||
NG_FREE_META(meta);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
shdr = priv->mpSeqOut;
|
||||
priv->mpSeqOut =
|
||||
(priv->mpSeqOut + 1) % MP_SHORT_SEQ_MASK;
|
||||
@ -1003,19 +1023,11 @@ ng_ppp_mp_output(node_p node, struct mbuf *m, meta_p meta)
|
||||
shdr |= MP_SHORT_FIRST_FLAG;
|
||||
if (lastFragment)
|
||||
shdr |= MP_SHORT_LAST_FLAG;
|
||||
*mtod(m2, u_int16_t *) = htons(shdr);
|
||||
shdr = htons(shdr);
|
||||
m2 = ng_ppp_prepend(m2, &shdr, 2);
|
||||
} else {
|
||||
u_int32_t lhdr;
|
||||
|
||||
M_PREPEND(m2, 4, M_NOWAIT);
|
||||
if (m2 == NULL
|
||||
|| (m2->m_len < 4
|
||||
&& (m2 = m_pullup(m2, 4)) == NULL)) {
|
||||
if (!lastFragment)
|
||||
m_freem(m);
|
||||
NG_FREE_META(meta);
|
||||
return (ENOBUFS);
|
||||
}
|
||||
lhdr = priv->mpSeqOut;
|
||||
priv->mpSeqOut =
|
||||
(priv->mpSeqOut + 1) % MP_LONG_SEQ_MASK;
|
||||
@ -1023,12 +1035,9 @@ ng_ppp_mp_output(node_p node, struct mbuf *m, meta_p meta)
|
||||
lhdr |= MP_LONG_FIRST_FLAG;
|
||||
if (lastFragment)
|
||||
lhdr |= MP_LONG_LAST_FLAG;
|
||||
*mtod(m2, u_int32_t *) = htonl(lhdr);
|
||||
lhdr = htonl(lhdr);
|
||||
m2 = ng_ppp_prepend(m2, &lhdr, 4);
|
||||
}
|
||||
|
||||
/* Add MP protocol number */
|
||||
m2 = ng_ppp_addproto(m, PROT_MP,
|
||||
priv->conf.links[linkNum].enableProtoComp);
|
||||
if (m2 == NULL) {
|
||||
if (!lastFragment)
|
||||
m_freem(m);
|
||||
@ -1051,9 +1060,7 @@ ng_ppp_mp_output(node_p node, struct mbuf *m, meta_p meta)
|
||||
meta2 = meta;
|
||||
|
||||
/* Send fragment */
|
||||
error = ng_ppp_output(node, 0, linkNum, m2, meta2);
|
||||
|
||||
/* Abort for error */
|
||||
error = ng_ppp_output(node, 0, PROT_MP, linkNum, m2, meta2);
|
||||
if (error != 0) {
|
||||
if (!lastFragment)
|
||||
NG_FREE_DATA(m, meta);
|
||||
@ -1299,16 +1306,27 @@ ng_ppp_intcmp(const void *v1, const void *v2)
|
||||
static struct mbuf *
|
||||
ng_ppp_addproto(struct mbuf *m, int proto, int compOK)
|
||||
{
|
||||
int psize = (PROT_COMPRESSABLE(proto) && compOK) ? 1 : 2;
|
||||
if (compOK && PROT_COMPRESSABLE(proto)) {
|
||||
u_char pbyte = (u_char)proto;
|
||||
|
||||
/* Add protocol number */
|
||||
M_PREPEND(m, psize, M_NOWAIT);
|
||||
if (m == NULL || (m->m_len < psize && (m = m_pullup(m, psize)) == NULL))
|
||||
return ng_ppp_prepend(m, &pbyte, 1);
|
||||
} else {
|
||||
u_int16_t pword = htons((u_int16_t)proto);
|
||||
|
||||
return ng_ppp_prepend(m, &pword, 2);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepend some bytes to an mbuf
|
||||
*/
|
||||
static struct mbuf *
|
||||
ng_ppp_prepend(struct mbuf *m, const void *buf, int len)
|
||||
{
|
||||
M_PREPEND(m, len, M_NOWAIT);
|
||||
if (m == NULL || (m->m_len < len && (m = m_pullup(m, len)) == NULL))
|
||||
return (NULL);
|
||||
if (psize == 1)
|
||||
*mtod(m, u_char *) = (u_char)proto;
|
||||
else
|
||||
*mtod(m, u_int16_t *) = htons((u_int16_t)proto);
|
||||
bcopy(buf, mtod(m, u_char *), len);
|
||||
return (m);
|
||||
}
|
||||
|
||||
@ -1332,7 +1350,8 @@ ng_ppp_update(node_p node, int newConf)
|
||||
for (i = 0; i < NG_PPP_MAX_LINKS; i++) {
|
||||
int hdrBytes;
|
||||
|
||||
hdrBytes = (priv->conf.links[i].enableProtoComp ? 1 : 2)
|
||||
hdrBytes = (priv->conf.links[i].enableACFComp ? 0 : 2)
|
||||
+ (priv->conf.links[i].enableProtoComp ? 1 : 2)
|
||||
+ (priv->conf.xmitShortSeq ? 2 : 4);
|
||||
priv->conf.links[i].latency +=
|
||||
((hdrBytes * priv->conf.links[i].bandwidth) + 50)
|
||||
|
@ -45,7 +45,7 @@
|
||||
|
||||
/* Node type name and magic cookie */
|
||||
#define NG_PPP_NODE_TYPE "ppp"
|
||||
#define NGM_PPP_COOKIE 940897792
|
||||
#define NGM_PPP_COOKIE 940897793
|
||||
|
||||
/* Maximum number of supported links */
|
||||
#define NG_PPP_MAX_LINKS 16
|
||||
@ -86,6 +86,7 @@ enum {
|
||||
struct ng_ppp_link_config {
|
||||
u_char enableLink; /* enable this link */
|
||||
u_char enableProtoComp;/* enable protocol field compression */
|
||||
u_char enableACFComp; /* enable addr/ctrl field compression */
|
||||
u_int16_t mru; /* peer MRU */
|
||||
u_int32_t latency; /* link latency (in milliseconds) */
|
||||
u_int32_t bandwidth; /* link bandwidth (in bytes/second) */
|
||||
|
Loading…
Reference in New Issue
Block a user