More bug fixes for the VJ Compression node. Seems to work now (really).

This commit is contained in:
Archie Cobbs 1999-11-15 20:02:58 +00:00
parent e870e9b278
commit 309c48c65b
2 changed files with 70 additions and 56 deletions
sys/netgraph

@ -72,7 +72,8 @@
#error NG_VJC_MAX_CHANNELS must be the same as MAX_STATES #error NG_VJC_MAX_CHANNELS must be the same as MAX_STATES
#endif #endif
#define MAX_VJHEADER 16 /* Maximum length of a compressed TCP VJ header */
#define MAX_VJHEADER 19
/* Node private data */ /* Node private data */
struct private { struct private {
@ -96,7 +97,7 @@ static ng_rcvdata_t ng_vjc_rcvdata;
static ng_disconnect_t ng_vjc_disconnect; static ng_disconnect_t ng_vjc_disconnect;
/* Helper stuff */ /* Helper stuff */
static struct mbuf *ng_vjc_pulluphdrs(struct mbuf *m); static struct mbuf *ng_vjc_pulluphdrs(struct mbuf *m, int knownTCP);
/* Node type descriptor */ /* Node type descriptor */
static struct ng_type typestruct = { static struct ng_type typestruct = {
@ -204,9 +205,8 @@ ng_vjc_rcvmsg(node_p node, struct ng_mesg *msg,
if (c->maxChannel > NG_VJC_MAX_CHANNELS - 1 if (c->maxChannel > NG_VJC_MAX_CHANNELS - 1
|| c->maxChannel < NG_VJC_MIN_CHANNELS - 1) || c->maxChannel < NG_VJC_MIN_CHANNELS - 1)
ERROUT(EINVAL); ERROUT(EINVAL);
} else { } else
c->maxChannel = NG_VJC_MAX_CHANNELS; c->maxChannel = NG_VJC_MAX_CHANNELS - 1;
}
if (c->enableComp != 0 || c->enableDecomp != 0) { if (c->enableComp != 0 || c->enableDecomp != 0) {
bzero(&priv->slc, sizeof(priv->slc)); bzero(&priv->slc, sizeof(priv->slc));
sl_compress_init(&priv->slc, c->maxChannel); sl_compress_init(&priv->slc, c->maxChannel);
@ -263,20 +263,27 @@ ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
int error = 0; int error = 0;
if (hook == priv->ip) { /* outgoing packet */ if (hook == priv->ip) { /* outgoing packet */
u_int type; u_int type = TYPE_IP;
if (!priv->conf.enableComp) /* compression not enabled */ /* Compress packet if enabled and proto is TCP */
type = TYPE_IP; if (priv->conf.enableComp) {
else {
struct ip *ip; struct ip *ip;
if ((m = ng_vjc_pulluphdrs(m)) == NULL) if ((m = ng_vjc_pulluphdrs(m, 0)) == NULL) {
ERROUT(ENOBUFS); NG_FREE_META(meta);
return (ENOBUFS);
}
ip = mtod(m, struct ip *); ip = mtod(m, struct ip *);
type = (ip->ip_p == IPPROTO_TCP) ? if (ip->ip_p == IPPROTO_TCP) {
sl_compress_tcp(m, ip, const int origLen = m->m_len;
&priv->slc, priv->conf.compressCID) : TYPE_IP;
type = sl_compress_tcp(m, ip,
&priv->slc, priv->conf.compressCID);
m->m_pkthdr.len += m->m_len - origLen;
}
} }
/* Dispatch to the appropriate outgoing hook */
switch (type) { switch (type) {
case TYPE_IP: case TYPE_IP:
hook = priv->vjip; hook = priv->vjip;
@ -291,56 +298,62 @@ ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
panic("%s: type=%d", __FUNCTION__, type); panic("%s: type=%d", __FUNCTION__, type);
} }
} else if (hook == priv->vjcomp) { /* incoming compressed packet */ } else if (hook == priv->vjcomp) { /* incoming compressed packet */
int vjlen; int vjlen, need2pullup;
u_int hlen; struct mbuf *hm;
u_char *hdr; u_char *hdr;
struct mbuf *mp; u_int hlen;
/* Are we decompressing? */ /* Are we decompressing? */
if (!priv->conf.enableDecomp) { if (!priv->conf.enableDecomp) {
NG_FREE_DATA(m, meta); NG_FREE_DATA(m, meta);
ERROUT(ENETDOWN); return (ENXIO);
}
/* Pull up the necessary amount from the mbuf */
need2pullup = MAX_VJHEADER;
if (need2pullup > m->m_pkthdr.len)
need2pullup = m->m_pkthdr.len;
if (m->m_len < need2pullup
&& (m = m_pullup(m, need2pullup)) == NULL) {
priv->slc.sls_errorin++;
NG_FREE_META(meta);
return (ENOBUFS);
} }
/* Uncompress packet to reconstruct TCP/IP header */ /* Uncompress packet to reconstruct TCP/IP header */
if (m->m_len < MAX_VJHEADER
&& (m = m_pullup(m, MAX_VJHEADER)) == NULL) {
priv->slc.sls_tossed++;
NG_FREE_META(meta);
ERROUT(ENOBUFS);
}
vjlen = sl_uncompress_tcp_core(mtod(m, u_char *), vjlen = sl_uncompress_tcp_core(mtod(m, u_char *),
m->m_len, m->m_pkthdr.len, TYPE_COMPRESSED_TCP, m->m_len, m->m_pkthdr.len, TYPE_COMPRESSED_TCP,
&priv->slc, &hdr, &hlen); &priv->slc, &hdr, &hlen);
if (vjlen <= 0) { if (vjlen <= 0) {
NG_FREE_DATA(m, meta); NG_FREE_DATA(m, meta);
ERROUT(EINVAL); return (EINVAL);
} }
m_adj(m, vjlen); m_adj(m, vjlen);
/* Copy the reconstructed TCP/IP headers into a new mbuf */ /* Copy the reconstructed TCP/IP headers into a new mbuf */
MGETHDR(mp, M_DONTWAIT, MT_DATA); MGETHDR(hm, M_DONTWAIT, MT_DATA);
if (mp == NULL) if (hm == NULL) {
goto compfailmem; priv->slc.sls_errorin++;
mp->m_len = 0; NG_FREE_DATA(m, meta);
mp->m_next = NULL; return (ENOBUFS);
if (hlen > MHLEN) { }
MCLGET(mp, M_DONTWAIT); hm->m_len = 0;
if (M_TRAILINGSPACE(mp) < hlen) { if (hlen > MHLEN) { /* unlikely, but can happen */
m_freem(mp); /* can't get a cluster, drop */ MCLGET(hm, M_DONTWAIT);
compfailmem: if ((hm->m_flags & M_EXT) == 0) {
priv->slc.sls_tossed++; m_freem(hm);
priv->slc.sls_errorin++;
NG_FREE_DATA(m, meta); NG_FREE_DATA(m, meta);
ERROUT(ENOBUFS); return (ENOBUFS);
} }
} }
bcopy(hdr, mtod(mp, u_char *), hlen); bcopy(hdr, mtod(hm, u_char *), hlen);
mp->m_len = hlen; hm->m_len = hlen;
/* Stick header and rest of packet together */ /* Glue TCP/IP headers and rest of packet together */
mp->m_next = m; hm->m_next = m;
mp->m_pkthdr.len = hlen + m->m_pkthdr.len; hm->m_pkthdr.len = hlen + m->m_pkthdr.len;
m = mp; m = hm;
hook = priv->ip; hook = priv->ip;
} else if (hook == priv->vjuncomp) { /* incoming uncompressed pkt */ } else if (hook == priv->vjuncomp) { /* incoming uncompressed pkt */
u_char *hdr; u_char *hdr;
@ -349,17 +362,21 @@ compfailmem:
/* Are we decompressing? */ /* Are we decompressing? */
if (!priv->conf.enableDecomp) { if (!priv->conf.enableDecomp) {
NG_FREE_DATA(m, meta); NG_FREE_DATA(m, meta);
ERROUT(ENETDOWN); return (ENXIO);
}
/* Pull up IP+TCP headers */
if ((m = ng_vjc_pulluphdrs(m, 1)) == NULL) {
NG_FREE_META(meta);
return (ENOBUFS);
} }
/* Run packet through uncompressor */ /* Run packet through uncompressor */
if ((m = ng_vjc_pulluphdrs(m)) == NULL)
ERROUT(ENOBUFS);
if (sl_uncompress_tcp_core(mtod(m, u_char *), if (sl_uncompress_tcp_core(mtod(m, u_char *),
m->m_len, m->m_pkthdr.len, TYPE_UNCOMPRESSED_TCP, m->m_len, m->m_pkthdr.len, TYPE_UNCOMPRESSED_TCP,
&priv->slc, &hdr, &hlen) < 0) { &priv->slc, &hdr, &hlen) < 0) {
NG_FREE_DATA(m, meta); NG_FREE_DATA(m, meta);
ERROUT(EINVAL); return (EINVAL);
} }
hook = priv->ip; hook = priv->ip;
} else if (hook == priv->vjip) /* incoming regular packet (bypass) */ } else if (hook == priv->vjip) /* incoming regular packet (bypass) */
@ -367,11 +384,8 @@ compfailmem:
else else
panic("%s: unknown hook", __FUNCTION__); panic("%s: unknown hook", __FUNCTION__);
done: /* Send result back out */
if (m != NULL) NG_SEND_DATA(error, hook, m, meta);
NG_SEND_DATA(error, hook, m, meta);
else
NG_FREE_META(meta);
return (error); return (error);
} }
@ -413,7 +427,7 @@ ng_vjc_disconnect(hook_p hook)
* a TCP packet, just pull up the IP header. * a TCP packet, just pull up the IP header.
*/ */
static struct mbuf * static struct mbuf *
ng_vjc_pulluphdrs(struct mbuf *m) ng_vjc_pulluphdrs(struct mbuf *m, int knownTCP)
{ {
struct ip *ip; struct ip *ip;
struct tcphdr *tcp; struct tcphdr *tcp;
@ -422,7 +436,7 @@ ng_vjc_pulluphdrs(struct mbuf *m)
if (m->m_len < sizeof(*ip) && (m = m_pullup(m, sizeof(*ip))) == NULL) if (m->m_len < sizeof(*ip) && (m = m_pullup(m, sizeof(*ip))) == NULL)
return (NULL); return (NULL);
ip = mtod(m, struct ip *); ip = mtod(m, struct ip *);
if (ip->ip_p != IPPROTO_TCP) if (!knownTCP && ip->ip_p != IPPROTO_TCP)
return (m); return (m);
ihlen = ip->ip_hl << 2; ihlen = ip->ip_hl << 2;
if (m->m_len < ihlen + sizeof(*tcp)) { if (m->m_len < ihlen + sizeof(*tcp)) {
@ -430,7 +444,7 @@ ng_vjc_pulluphdrs(struct mbuf *m)
return (NULL); return (NULL);
ip = mtod(m, struct ip *); ip = mtod(m, struct ip *);
} }
tcp = (struct tcphdr *) ((u_char *) ip + ihlen); tcp = (struct tcphdr *)((u_char *)ip + ihlen);
thlen = tcp->th_off << 2; thlen = tcp->th_off << 2;
if (m->m_len < ihlen + thlen) if (m->m_len < ihlen + thlen)
m = m_pullup(m, ihlen + thlen); m = m_pullup(m, ihlen + thlen);

@ -53,7 +53,7 @@
#define NG_VJC_HOOK_VJUNCOMP "vjuncomp" /* uncompressed TCP */ #define NG_VJC_HOOK_VJUNCOMP "vjuncomp" /* uncompressed TCP */
#define NG_VJC_HOOK_VJIP "vjip" /* uncompressed IP */ #define NG_VJC_HOOK_VJIP "vjip" /* uncompressed IP */
/* Minimum and maximum number of channels */ /* Minimum and maximum number of compression channels */
#define NG_VJC_MIN_CHANNELS 4 #define NG_VJC_MIN_CHANNELS 4
#define NG_VJC_MAX_CHANNELS 16 #define NG_VJC_MAX_CHANNELS 16