Commit 79e94f70 authored by Kai Germaschewski's avatar Kai Germaschewski

ISDN/PPP: Separate out VJ header compression

Collect code which is related to VJ header compression and put it
into isdn_ppp_vj.[hc]
 
Also, make the PPP protocol type a u16 everywhere.
parent ecf2c214
...@@ -20,6 +20,7 @@ isdn-objs := isdn_net.o isdn_net_lib.o \ ...@@ -20,6 +20,7 @@ isdn-objs := isdn_net.o isdn_net_lib.o \
# Optional parts of multipart objects. # Optional parts of multipart objects.
isdn-objs-$(CONFIG_ISDN_PPP) += isdn_ppp.o isdn_ppp_ccp.o isdn-objs-$(CONFIG_ISDN_PPP) += isdn_ppp.o isdn_ppp_ccp.o
isdn-objs-$(CONFIG_ISDN_PPP_VJ) += isdn_ppp_vj.o
isdn-objs-$(CONFIG_ISDN_X25) += isdn_concap.o isdn_x25iface.o isdn-objs-$(CONFIG_ISDN_X25) += isdn_concap.o isdn_x25iface.o
isdn-objs-$(CONFIG_ISDN_AUDIO) += isdn_audio.o isdn-objs-$(CONFIG_ISDN_AUDIO) += isdn_audio.o
isdn-objs-$(CONFIG_ISDN_TTY_FAX) += isdn_ttyfax.o isdn-objs-$(CONFIG_ISDN_TTY_FAX) += isdn_ttyfax.o
......
...@@ -19,11 +19,9 @@ ...@@ -19,11 +19,9 @@
#include "isdn_common.h" #include "isdn_common.h"
#include "isdn_ppp.h" #include "isdn_ppp.h"
#include "isdn_ppp_ccp.h" #include "isdn_ppp_ccp.h"
#include "isdn_ppp_vj.h"
#include "isdn_net.h" #include "isdn_net.h"
static struct sk_buff *
isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask);
static int static int
isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *); isdn_ppp_set_compressor(isdn_net_dev *idev, struct isdn_ppp_comp_data *);
...@@ -446,26 +444,12 @@ ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd, ...@@ -446,26 +444,12 @@ ipppd_ioctl(struct inode *ino, struct file *file, unsigned int cmd,
break; break;
case PPPIOCSMPMTU: case PPPIOCSMPMTU:
break; break;
#ifdef CONFIG_ISDN_PPP_VJ
case PPPIOCSMAXCID: /* set the maximum compression slot id */ case PPPIOCSMAXCID: /* set the maximum compression slot id */
{
struct slcompress *sltmp;
r = get_arg(arg, &val, sizeof(val)); r = get_arg(arg, &val, sizeof(val));
if (r) if (r)
break; break;
val++; r = ippp_vj_set_maxcid(idev, val);
sltmp = slhc_init(16, val);
if (!sltmp) {
r = -ENOMEM;
break;
}
if (idev->mlp->slcomp)
slhc_free(idev->mlp->slcomp);
idev->mlp->slcomp = sltmp;
r = 0;
break; break;
}
#endif
case PPPIOCSCOMPRESSOR: case PPPIOCSCOMPRESSOR:
r = get_arg(arg, &data, sizeof(data)); r = get_arg(arg, &data, sizeof(data));
if (r) if (r)
...@@ -563,11 +547,17 @@ ipppd_queue_read(struct ipppd *is, u16 proto, unsigned char *buf, int len) ...@@ -563,11 +547,17 @@ ipppd_queue_read(struct ipppd *is, u16 proto, unsigned char *buf, int len)
} }
/* ====================================================================== */ /* ====================================================================== */
/* interface to isdn_net_lib */
/* ====================================================================== */
/* Prototypes */ /* Prototypes */
static void isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, static void
struct sk_buff *skb, int proto); isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
static int isdn_ppp_if_get_unit(char *namebuf); struct sk_buff *skb, u16 proto);
static int
isdn_ppp_if_get_unit(char *namebuf);
static void static void
isdn_ppp_dev_push_header(void *priv, struct sk_buff *skb, u16 proto); isdn_ppp_dev_push_header(void *priv, struct sk_buff *skb, u16 proto);
...@@ -853,28 +843,29 @@ isdn_ppp_cleanup(void) ...@@ -853,28 +843,29 @@ isdn_ppp_cleanup(void)
* check for address/control field and skip if allowed * check for address/control field and skip if allowed
* retval != 0 -> discard packet silently * retval != 0 -> discard packet silently
*/ */
static int isdn_ppp_skip_ac(isdn_net_dev *idev, struct sk_buff *skb) static int
isdn_ppp_skip_ac(isdn_net_dev *idev, struct sk_buff *skb)
{ {
u8 val; u8 val;
if (skb->len < 1) if (skb->len < 1)
return -1; return -EINVAL;
get_u8(skb->data, &val); get_u8(skb->data, &val);
if (val != PPP_ALLSTATIONS) { if (val != PPP_ALLSTATIONS) {
/* if AC compression was not negotiated, but no AC present, /* if AC compression was not negotiated, but no AC present,
discard packet */ discard packet */
if (idev->pppcfg & SC_REJ_COMP_AC) if (idev->pppcfg & SC_REJ_COMP_AC)
return -1; return -EINVAL;
return 0; return 0;
} }
if (skb->len < 2) if (skb->len < 2)
return -1; return -EINVAL;
get_u8(skb->data + 1, &val); get_u8(skb->data + 1, &val);
if (val != PPP_UI) if (val != PPP_UI)
return -1; return -EINVAL;
/* skip address/control (AC) field */ /* skip address/control (AC) field */
skb_pull(skb, 2); skb_pull(skb, 2);
...@@ -885,26 +876,26 @@ static int isdn_ppp_skip_ac(isdn_net_dev *idev, struct sk_buff *skb) ...@@ -885,26 +876,26 @@ static int isdn_ppp_skip_ac(isdn_net_dev *idev, struct sk_buff *skb)
* get the PPP protocol header and pull skb * get the PPP protocol header and pull skb
* retval < 0 -> discard packet silently * retval < 0 -> discard packet silently
*/ */
int isdn_ppp_strip_proto(struct sk_buff *skb) int
isdn_ppp_strip_proto(struct sk_buff *skb, u16 *proto)
{ {
u16 proto;
u8 val; u8 val;
if (skb->len < 1) if (skb->len < 1)
return -1; return -EINVAL;
get_u8(skb->data, &val); get_u8(skb->data, &val);
if (val & 0x1) { if (val & 0x1) {
/* protocol field is compressed */ /* protocol field is compressed */
proto = val; *proto = val;
skb_pull(skb, 1); skb_pull(skb, 1);
} else { } else {
if (skb->len < 2) if (skb->len < 2)
return -1; return -1;
get_u16(skb->data, &proto); get_u16(skb->data, proto);
skb_pull(skb, 2); skb_pull(skb, 2);
} }
return proto; return 0;
} }
/* /*
...@@ -914,7 +905,7 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -914,7 +905,7 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ipppd *is; struct ipppd *is;
int proto; u16 proto;
is = idev->ipppd; is = idev->ipppd;
if (!is) if (!is)
...@@ -929,8 +920,7 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -929,8 +920,7 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev,
if (isdn_ppp_skip_ac(idev, skb) < 0) if (isdn_ppp_skip_ac(idev, skb) < 0)
goto err; goto err;
proto = isdn_ppp_strip_proto(skb); if (isdn_ppp_strip_proto(skb, &proto))
if (proto < 0)
goto err; goto err;
/* Don't reset huptimer on LCP packets. */ /* Don't reset huptimer on LCP packets. */
...@@ -968,7 +958,7 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -968,7 +958,7 @@ static void isdn_ppp_receive(isdn_net_local *lp, isdn_net_dev *idev,
*/ */
static void static void
isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
struct sk_buff *skb, int proto) struct sk_buff *skb, u16 proto)
{ {
struct net_device *dev = &lp->dev; struct net_device *dev = &lp->dev;
struct ipppd *is = idev->ipppd; struct ipppd *is = idev->ipppd;
...@@ -996,42 +986,14 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev, ...@@ -996,42 +986,14 @@ isdn_ppp_push_higher(isdn_net_local *lp, isdn_net_dev *idev,
case PPP_COMPFRAG: case PPP_COMPFRAG:
printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n"); printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n");
goto drop; goto drop;
#ifdef CONFIG_ISDN_PPP_VJ
case PPP_VJC_UNCOMP: case PPP_VJC_UNCOMP:
if (is->debug & 0x20)
printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
if (slhc_remember(lp->slcomp, skb->data, skb->len) <= 0) {
printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
goto drop;
}
skb->protocol = htons(ETH_P_IP);
break;
case PPP_VJC_COMP: case PPP_VJC_COMP:
if (is->debug & 0x20) skb = ippp_vj_decompress(lp->slcomp, skb, proto);
printk(KERN_DEBUG "isdn_ppp: VJC_COMP\n");
{
struct sk_buff *skb_old = skb;
int pkt_len;
skb = dev_alloc_skb(skb_old->len + 128);
if (!skb) { if (!skb) {
printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); lp->stats.rx_dropped++;
skb = skb_old; goto out;
goto drop;
}
skb_put(skb, skb_old->len + 128);
memcpy(skb->data, skb_old->data, skb_old->len);
pkt_len = slhc_uncompress(lp->slcomp,
skb->data, skb_old->len);
kfree_skb(skb_old);
if (pkt_len < 0)
goto drop;
skb_trim(skb, pkt_len);
skb->protocol = htons(ETH_P_IP);
} }
break; break;
#endif
case PPP_CCPFRAG: case PPP_CCPFRAG:
ippp_ccp_receive_ccp(idev->ccp, skb); ippp_ccp_receive_ccp(idev->ccp, skb);
goto ccp; goto ccp;
...@@ -1078,7 +1040,7 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1078,7 +1040,7 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{ {
isdn_net_local *mlp = ndev->priv; isdn_net_local *mlp = ndev->priv;
isdn_net_dev *idev = list_entry(mlp->online.next, isdn_net_dev, online); isdn_net_dev *idev = list_entry(mlp->online.next, isdn_net_dev, online);
unsigned int proto = PPP_IP; /* 0x21 */ u16 proto = PPP_IP; /* 0x21 */
struct ipppd *ipppd; struct ipppd *ipppd;
ndev->trans_start = jiffies; ndev->trans_start = jiffies;
...@@ -1112,65 +1074,16 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev) ...@@ -1112,65 +1074,16 @@ isdn_ppp_start_xmit(struct sk_buff *skb, struct net_device *ndev)
ipppd = idev->ipppd; ipppd = idev->ipppd;
idev->huptimer = 0; idev->huptimer = 0;
/*
* after this line .. requeueing in the device queue is no longer allowed!!!
*/
if (ipppd->debug & 0x4) if (ipppd->debug & 0x4)
printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len); printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
if (ipppd->debug & 0x40) if (ipppd->debug & 0x40)
isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32, ipppd->unit, -1); isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32, ipppd->unit, -1);
#ifdef CONFIG_ISDN_PPP_VJ
if (proto == PPP_IP && idev->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */
struct sk_buff *new_skb;
unsigned short hl;
/* /*
* we need to reserve enought space in front of * after this line .. requeueing in the device queue is no longer allowed!!!
* sk_buff. old call to dev_alloc_skb only reserved
* 16 bytes, now we are looking what the driver want.
*/
hl = isdn_slot_hdrlen(idev->isdn_slot) + IPPP_MAX_HEADER;;
/*
* Note: hl might still be insufficient because the method
* above does not account for a possibible MPPP slave channel
* which had larger HL header space requirements than the
* master.
*/ */
new_skb = alloc_skb(hl+skb->len, GFP_ATOMIC);
if (new_skb) {
u_char *buf;
int pktlen;
skb_reserve(new_skb, hl);
new_skb->dev = skb->dev;
skb_put(new_skb, skb->len);
buf = skb->data;
pktlen = slhc_compress(mlp->slcomp, skb->data, skb->len, new_skb->data,
&buf, !(idev->pppcfg & SC_NO_TCP_CCID));
if (buf != skb->data) {
if (new_skb->data != buf)
printk(KERN_ERR "isdn_ppp: FATAL error after slhc_compress!!\n");
dev_kfree_skb(skb);
skb = new_skb;
} else {
dev_kfree_skb(new_skb);
}
skb_trim(skb, pktlen); skb = ippp_vj_compress(idev, skb, &proto);
if (skb->data[0] & SL_TYPE_COMPRESSED_TCP) { /* cslip? style -> PPP */
proto = PPP_VJC_COMP;
skb->data[0] ^= SL_TYPE_COMPRESSED_TCP;
} else {
if (skb->data[0] >= SL_TYPE_UNCOMPRESSED_TCP)
proto = PPP_VJC_UNCOMP;
skb->data[0] = (skb->data[0] & 0x0f) | 0x40;
}
}
}
#endif
/* /*
* normal (single link) or bundle compression * normal (single link) or bundle compression
...@@ -1909,7 +1822,7 @@ __isdn_ppp_alloc_skb(isdn_net_dev *idev, int len, unsigned int gfp_mask) ...@@ -1909,7 +1822,7 @@ __isdn_ppp_alloc_skb(isdn_net_dev *idev, int len, unsigned int gfp_mask)
return skb; return skb;
} }
static struct sk_buff * struct sk_buff *
isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask) isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask)
{ {
isdn_net_dev *idev = priv; isdn_net_dev *idev = priv;
...@@ -1997,12 +1910,14 @@ isdn_ppp_open(isdn_net_local *lp) ...@@ -1997,12 +1910,14 @@ isdn_ppp_open(isdn_net_local *lp)
lp->mpppcfg = 0; /* mppp configuration */ lp->mpppcfg = 0; /* mppp configuration */
lp->mp_seqno = 0; /* MP sequence number */ lp->mp_seqno = 0; /* MP sequence number */
#ifdef CONFIG_ISDN_PPP_VJ lp->slcomp = ippp_vj_alloc();
lp->slcomp = slhc_init(16, 16); if (!lp->slcomp)
#endif goto err;
lp->ccp = ippp_ccp_alloc(); lp->ccp = ippp_ccp_alloc();
if (!lp->ccp) if (!lp->ccp)
return -ENOMEM; goto err_vj;
lp->ccp->proto = PPP_COMP; lp->ccp->proto = PPP_COMP;
lp->ccp->priv = lp; lp->ccp->priv = lp;
lp->ccp->alloc_skb = isdn_ppp_lp_alloc_skb; lp->ccp->alloc_skb = isdn_ppp_lp_alloc_skb;
...@@ -2011,17 +1926,22 @@ isdn_ppp_open(isdn_net_local *lp) ...@@ -2011,17 +1926,22 @@ isdn_ppp_open(isdn_net_local *lp)
lp->ccp->kick_up = isdn_ppp_lp_kick_up; lp->ccp->kick_up = isdn_ppp_lp_kick_up;
return 0; return 0;
err_vj:
ippp_vj_free(lp->slcomp);
lp->slcomp = NULL;
err:
return -ENOMEM;
} }
static void static void
isdn_ppp_close(isdn_net_local *lp) isdn_ppp_close(isdn_net_local *lp)
{ {
#ifdef CONFIG_ISDN_PPP_VJ
slhc_free(lp->slcomp);
lp->slcomp = NULL;
#endif
ippp_ccp_free(lp->ccp); ippp_ccp_free(lp->ccp);
lp->ccp = NULL; lp->ccp = NULL;
ippp_vj_free(lp->slcomp);
lp->slcomp = NULL;
} }
struct isdn_netif_ops isdn_ppp_ops = { struct isdn_netif_ops isdn_ppp_ops = {
...@@ -2037,3 +1957,4 @@ struct isdn_netif_ops isdn_ppp_ops = { ...@@ -2037,3 +1957,4 @@ struct isdn_netif_ops isdn_ppp_ops = {
.open = isdn_ppp_open, .open = isdn_ppp_open,
.close = isdn_ppp_close, .close = isdn_ppp_close,
}; };
...@@ -23,7 +23,11 @@ int isdn_ppp_hangup_slave(char *); ...@@ -23,7 +23,11 @@ int isdn_ppp_hangup_slave(char *);
void void
isdn_ppp_frame_log(char *info, char *data, int len, int maxlen, isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,
int unit, int slot); int unit, int slot);
int int
isdn_ppp_strip_proto(struct sk_buff *skb); isdn_ppp_strip_proto(struct sk_buff *skb, u16 *proto);
struct sk_buff *
isdn_ppp_dev_alloc_skb(void *priv, int len, int gfp_mask);
#define IPPP_MAX_HEADER 10 #define IPPP_MAX_HEADER 10
...@@ -250,7 +250,7 @@ ippp_ccp_get_flags(struct ippp_ccp *ccp) ...@@ -250,7 +250,7 @@ ippp_ccp_get_flags(struct ippp_ccp *ccp)
* and a new skb otherwise * and a new skb otherwise
*/ */
struct sk_buff * struct sk_buff *
ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb_in, int *proto) ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb_in, u16 *proto)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -260,7 +260,7 @@ ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb_in, int *proto) ...@@ -260,7 +260,7 @@ ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb_in, int *proto)
return skb_in; return skb_in;
} }
/* we do not compress control protocols */ /* we do not compress control protocols */
if (*proto < 0 || *proto > 0x3fff) { if (*proto > 0x3fff) {
return skb_in; return skb_in;
} }
if (!ccp->compressor || !ccp->comp_stat) { if (!ccp->compressor || !ccp->comp_stat) {
...@@ -294,7 +294,7 @@ ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb_in, int *proto) ...@@ -294,7 +294,7 @@ ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb_in, int *proto)
*/ */
struct sk_buff * struct sk_buff *
ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb_in, int *proto) ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb_in, u16 *proto)
{ {
struct sk_buff *skb; struct sk_buff *skb;
struct isdn_ppp_resetparams rsparm; struct isdn_ppp_resetparams rsparm;
...@@ -344,8 +344,7 @@ ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb_in, int *proto) ...@@ -344,8 +344,7 @@ ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb_in, int *proto)
kfree_skb(skb); kfree_skb(skb);
return NULL; return NULL;
} }
*proto = isdn_ppp_strip_proto(skb); if (isdn_ppp_strip_proto(skb, proto)) {
if (*proto < 0) {
kfree_skb(skb); kfree_skb(skb);
return NULL; return NULL;
} }
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
*/ */
struct ippp_ccp { struct ippp_ccp {
int proto; u16 proto;
struct isdn_ppp_compressor *compressor; struct isdn_ppp_compressor *compressor;
struct isdn_ppp_compressor *decompressor; struct isdn_ppp_compressor *decompressor;
void *comp_stat; void *comp_stat;
...@@ -45,10 +45,10 @@ unsigned int ...@@ -45,10 +45,10 @@ unsigned int
ippp_ccp_get_flags(struct ippp_ccp *ccp); ippp_ccp_get_flags(struct ippp_ccp *ccp);
struct sk_buff * struct sk_buff *
ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb, int *proto); ippp_ccp_compress(struct ippp_ccp *ccp, struct sk_buff *skb, u16 *proto);
struct sk_buff * struct sk_buff *
ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb, int *proto); ippp_ccp_decompress(struct ippp_ccp *ccp, struct sk_buff *skb, u16 *proto);
void void
ippp_ccp_send_ccp(struct ippp_ccp *ccp, struct sk_buff *skb); ippp_ccp_send_ccp(struct ippp_ccp *ccp, struct sk_buff *skb);
......
#include "isdn_ppp_vj.h"
#include "isdn_common.h"
#include "isdn_net.h"
#include "isdn_ppp.h"
/* ====================================================================== */
/* VJ header compression */
/* ====================================================================== */
struct slcompress *
ippp_vj_alloc(void)
{
return slhc_init(16, 16);
}
void
ippp_vj_free(struct slcompress *slcomp)
{
slhc_free(slcomp);
}
int
ippp_vj_set_maxcid(isdn_net_dev *idev, int val)
{
struct slcompress *sltmp;
sltmp = slhc_init(16, val + 1);
if (!sltmp)
return -ENOMEM;
if (idev->mlp->slcomp)
slhc_free(idev->mlp->slcomp);
idev->mlp->slcomp = sltmp;
return 0;
}
struct sk_buff *
ippp_vj_decompress(struct slcompress *slcomp, struct sk_buff *skb_old,
u16 proto)
{
struct sk_buff *skb;
int len;
switch (proto) {
case PPP_VJC_UNCOMP:
if (slhc_remember(slcomp, skb_old->data, skb_old->len) <= 0)
goto drop;
skb = skb_old;
break;
case PPP_VJC_COMP:
skb = dev_alloc_skb(skb_old->len + 128);
if (!skb)
goto drop;
memcpy(skb->data, skb_old->data, skb_old->len);
len = slhc_uncompress(slcomp, skb->data, skb_old->len);
if (len < 0)
goto drop_both;
skb_put(skb, len);
kfree_skb(skb_old);
break;
default:
isdn_BUG();
goto drop;
}
skb->protocol = htons(ETH_P_IP);
return skb;
drop_both:
kfree_skb(skb);
drop:
kfree_skb(skb_old);
return NULL;
}
struct sk_buff *
ippp_vj_compress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 *proto)
{
struct sk_buff *skb;
unsigned char *buf;
int len;
if (!(idev->pppcfg & SC_COMP_TCP) || *proto != PPP_IP)
return skb_old;
skb = isdn_ppp_dev_alloc_skb(idev, skb_old->len, GFP_ATOMIC);
if (!skb)
return skb_old;
skb_put(skb, skb_old->len);
buf = skb_old->data;
len = slhc_compress(idev->mlp->slcomp, skb_old->data, skb_old->len,
skb->data, &buf, !(idev->pppcfg & SC_NO_TCP_CCID));
if (buf == skb_old->data) {
kfree_skb(skb);
skb = skb_old;
} else {
kfree_skb(skb_old);
}
skb_trim(skb, len);
/* cslip style -> PPP */
if ((skb->data[0] & SL_TYPE_COMPRESSED_TCP) == SL_TYPE_COMPRESSED_TCP) {
skb->data[0] &= ~SL_TYPE_COMPRESSED_TCP;
*proto = PPP_VJC_COMP;
} else if ((skb->data[0] & SL_TYPE_UNCOMPRESSED_TCP) == SL_TYPE_UNCOMPRESSED_TCP) {
skb->data[0] &= ~SL_TYPE_UNCOMPRESSED_TCP;
skb->data[0] |= SL_TYPE_IP;
*proto = PPP_VJC_UNCOMP;
}
return skb;
}
#ifndef __ISDN_PPP_VJ_H__
#define __ISDN_PPP_VJ_H__
#include <linux/kernel.h>
#include <linux/isdn.h>
#ifdef CONFIG_ISDN_PPP_VJ
struct slcompress *
ippp_vj_alloc(void);
void
ippp_vj_free(struct slcompress *slcomp);
int
ippp_vj_set_maxcid(isdn_net_dev *idev, int val);
struct sk_buff *
ippp_vj_decompress(struct slcompress *slcomp, struct sk_buff *skb_old,
u16 proto);
struct sk_buff *
ippp_vj_compress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 *proto);
#else
static inline struct slcompress *
ippp_vj_alloc(void)
{ return (struct slcompress *) !NULL; }
static inline void
ippp_vj_free(struct slcompress *slcomp)
{ }
static inline int
ippp_vj_set_maxcid(isdn_net_dev *idev, int val)
{ return -EINVAL; }
static inline struct sk_buff *
ippp_vj_decompress(struct slcompress *slcomp, struct sk_buff *skb_old,
u16 proto)
{ return skb_old; }
static inline struct sk_buff *
ippp_vj_compress(isdn_net_dev *idev, struct sk_buff *skb_old, u16 *proto)
{ return skb_old; }
#endif
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment