patch-2.1.92 linux/drivers/isdn/isdn_ppp.c
Next file: linux/drivers/isdn/isdn_ppp.h
Previous file: linux/drivers/isdn/isdn_net.h
Back to the patch index
Back to the overall index
- Lines: 913
- Date:
Wed Apr 1 16:21:03 1998
- Orig file:
v2.1.91/linux/drivers/isdn/isdn_ppp.c
- Orig date:
Tue Mar 10 10:03:32 1998
diff -u --recursive --new-file v2.1.91/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.27 1997/03/30 16:51:17 calle Exp $
+/* $Id: isdn_ppp.c,v 1.33 1998/02/20 17:11:54 fritz Exp $
*
* Linux ISDN subsystem, functions for synchronous PPP (linklevel).
*
@@ -19,6 +19,37 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_ppp.c,v $
+ * Revision 1.33 1998/02/20 17:11:54 fritz
+ * Changes for recent kernels.
+ *
+ * Revision 1.32 1998/01/31 19:29:55 calle
+ * Merged changes from and for 2.1.82, not tested only compiled ...
+ *
+ * Revision 1.31 1997/10/09 21:29:01 fritz
+ * New HL<->LL interface:
+ * New BSENT callback with nr. of bytes included.
+ * Sending without ACK.
+ * New L1 error status (not yet in use).
+ * Cleaned up obsolete structures.
+ * Implemented Cisco-SLARP.
+ * Changed local net-interface data to be dynamically allocated.
+ * Removed old 2.0 compatibility stuff.
+ *
+ * Revision 1.30 1997/10/01 09:20:38 fritz
+ * Removed old compatibility stuff for 2.0.X kernels.
+ * From now on, this code is for 2.1.X ONLY!
+ * Old stuff is still in the separate branch.
+ *
+ * Revision 1.29 1997/08/21 23:11:44 fritz
+ * Added changes for kernels >= 2.1.45
+ *
+ * Revision 1.28 1997/06/17 13:05:57 hipp
+ * Applied Eric's underflow-patches (slightly modified)
+ * more compression changes (but disabled at the moment)
+ * changed one copy_to_user() to run with enabled IRQs
+ * a few MP changes
+ * changed 'proto' handling in the isdn_ppp receive code
+ *
* Revision 1.27 1997/03/30 16:51:17 calle
* changed calls to copy_from_user/copy_to_user and removed verify_area
* were possible.
@@ -128,9 +159,7 @@
#include <linux/module.h>
#include <linux/version.h>
#include <linux/isdn.h>
-#if (LINUX_VERSION_CODE >= 0x020117)
#include <linux/poll.h>
-#endif
#include "isdn_common.h"
#include "isdn_ppp.h"
#include "isdn_net.h"
@@ -148,6 +177,12 @@
struct sk_buff *skb, int proto);
static int isdn_ppp_if_get_unit(char *namebuf);
static int isdn_ppp_set_compressor(struct ippp_struct *is,int num);
+static struct sk_buff *isdn_ppp_decompress(struct sk_buff *,
+ struct ippp_struct *,struct ippp_struct *);
+static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp,
+ struct sk_buff *skb);
+static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
+ struct ippp_struct *is,struct ippp_struct *master,int type);
#ifdef CONFIG_ISDN_MPP
static int isdn_ppp_bundle(struct ippp_struct *, int unit);
@@ -160,7 +195,7 @@
static void isdn_ppp_free_mpqueue(isdn_net_dev *);
#endif
-char *isdn_ppp_revision = "$Revision: 1.27 $";
+char *isdn_ppp_revision = "$Revision: 1.33 $";
static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
static struct isdn_ppp_compressor *ipc_head = NULL;
@@ -267,7 +302,7 @@
char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */
memset(exclusive, 0, ISDN_MAX_CHANNELS);
while (net_dev) { /* step through net devices to find exclusive minors */
- isdn_net_local *lp = &net_dev->local;
+ isdn_net_local *lp = net_dev->local;
if (lp->pppbind >= 0)
exclusive[lp->pppbind] = 1;
net_dev = net_dev->next;
@@ -382,7 +417,12 @@
if (is->debug & 0x1)
printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, min, is->state);
+ /* compression stuff */
is->compressor = NULL;
+ is->decomp_stat = is->comp_stat = NULL;
+ is->link_compressor = NULL;
+ is->link_decomp_stat = is->link_comp_stat = NULL;
+
is->lp = NULL;
is->mp_seqno = 0; /* MP sequence number */
is->pppcfg = 0; /* ppp configuration */
@@ -644,50 +684,6 @@
return 0;
}
-#if (LINUX_VERSION_CODE < 0x020117)
-int
-isdn_ppp_select(int min, struct file *file, int type, select_table * st)
-{
- struct ippp_buf_queue *bf,
- *bl;
- unsigned long flags;
- struct ippp_struct *is;
-
- is = file->private_data;
-
- if (is->debug & 0x2)
- printk(KERN_DEBUG "isdn_ppp_select: minor: %d, type: %d \n", min, type);
-
- if (!(is->state & IPPP_OPEN))
- return -EINVAL;
-
- switch (type) {
- case SEL_IN:
- save_flags(flags);
- cli();
- bl = is->last;
- bf = is->first;
- /*
- * if IPPP_NOBLOCK is set we return even if we have nothing to read
- */
- if (bf->next == bl && !(is->state & IPPP_NOBLOCK)) {
- select_wait(&is->wq, st);
- restore_flags(flags);
- return 0;
- }
- is->state &= ~IPPP_NOBLOCK;
- restore_flags(flags);
- return 1;
- case SEL_OUT:
- /* we're always ready to send .. */
- return 1;
- case SEL_EX:
- select_wait(&is->wq1, st);
- return 0;
- }
- return 1;
-}
-#else
unsigned int
isdn_ppp_poll(struct file *file, poll_table * wait)
{
@@ -700,7 +696,8 @@
is = file->private_data;
if (is->debug & 0x2)
- printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n", MINOR(file->f_dentry->d_inode->i_rdev));
+ printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
+ MINOR(file->f_dentry->d_inode->i_rdev));
poll_wait(file, &is->wq, wait);
@@ -725,8 +722,6 @@
restore_flags(flags);
return mask;
}
-#endif
-
/*
* fill up isdn_ppp_read() queue ..
@@ -798,31 +793,35 @@
struct ippp_buf_queue *b;
int r;
unsigned long flags;
+ unsigned char *save_buf;
is = file->private_data;
if (!(is->state & IPPP_OPEN))
return 0;
+ if ((r = verify_area(VERIFY_WRITE, (void *) buf, count)))
+ return r;
+
save_flags(flags);
cli();
b = is->first->next;
- if (!b->buf) {
+ save_buf = b->buf;
+ if (!save_buf) {
restore_flags(flags);
return -EAGAIN;
}
if (b->len < count)
count = b->len;
- if ((r = copy_to_user(buf, b->buf, count))) {
- restore_flags(flags);
- return r;
- }
- kfree(b->buf);
b->buf = NULL;
is->first = b;
+
restore_flags(flags);
+ copy_to_user(buf, save_buf, count);
+ kfree(save_buf);
+
return count;
}
@@ -872,14 +871,13 @@
printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
return count;
}
- SET_SKB_FREE(skb);
if (copy_from_user(skb_put(skb, count), buf, count))
return -EFAULT;
if (is->debug & 0x40) {
printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
isdn_ppp_frame_log("xmit", skb->data, skb->len, 32);
}
- if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, skb)) != count) {
+ if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb)) != count) {
if (lp->sav_skb) {
dev_kfree_skb(lp->sav_skb);
printk(KERN_INFO "isdn_ppp_write: freeing sav_skb (%d,%d)!\n", cnt, count);
@@ -935,45 +933,65 @@
}
/*
+ * get the PPP protocol header and pull skb
+ */
+static int isdn_ppp_strip_proto(struct sk_buff *skb)
+{
+ int proto;
+ if (skb->data[0] & 0x1) {
+ proto = skb->data[0];
+ skb_pull(skb, 1); /* protocol ID is only 8 bit */
+ } else {
+ proto = ((int) skb->data[0] << 8) + skb->data[1];
+ skb_pull(skb, 2);
+ }
+ return proto;
+}
+
+
+/*
* handler for incoming packets on a syncPPP interface
*/
-void
-isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb)
+void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb)
{
struct ippp_struct *is;
+ int proto;
+
is = ippp_table[lp->ppp_slot];
if (is->debug & 0x4) {
printk(KERN_DEBUG "ippp_receive: len: %d\n", (int) skb->len);
isdn_ppp_frame_log("receive", skb->data, skb->len, 32);
}
- if (net_dev->local.master) {
+ if (net_dev->local->master) {
printk(KERN_WARNING "isdn_ppp_receice: net_dev != master\n");
- net_dev = ((isdn_net_local *) net_dev->local.master->priv)->netdev;
+ net_dev = ((isdn_net_local *) net_dev->local->master->priv)->netdev;
}
if (skb->data[0] == 0xff && skb->data[1] == 0x03)
skb_pull(skb, 2);
else if (is->pppcfg & SC_REJ_COMP_AC) {
- SET_SKB_FREE(skb);
dev_kfree_skb(skb);
return; /* discard it silently */
}
+
+ proto = isdn_ppp_strip_proto(skb);
+
#ifdef CONFIG_ISDN_MPP
if (!(is->mpppcfg & SC_REJ_MP_PROT)) {
- int proto;
int sqno_end;
- if (skb->data[0] & 0x1) {
- proto = skb->data[0];
- skb_pull(skb, 1); /* protocol ID is only 8 bit */
- } else {
- proto = ((int) skb->data[0] << 8) + skb->data[1];
- skb_pull(skb, 2);
+
+ if(proto == PPP_LINK_COMP) {
+ printk(KERN_DEBUG "received single link compressed frame\n");
+ skb = isdn_ppp_decompress(skb,is,NULL);
+ if(!skb)
+ return;
+ proto = isdn_ppp_strip_proto(skb);
}
+
if (proto == PPP_MP) {
isdn_net_local *lpq;
- long sqno,
- min_sqno,
- tseq;
+ long sqno, min_sqno, tseq;
+
u_char BEbyte = skb->data[0];
if (is->debug & 0x8)
printk(KERN_DEBUG "recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n", lp->ppp_slot, proto,
@@ -987,6 +1005,10 @@
skb_pull(skb, 2);
}
+ /*
+ * new sequence number lower than last number? (this is only allowed
+ * for overflow case)
+ */
if ((tseq = is->last_link_seqno) >= sqno) {
int range = is->range;
if (tseq + 1024 < range + sqno) /* redundancy check .. not MP conform */
@@ -995,9 +1017,14 @@
sqno += range;
is->last_link_seqno = sqno;
}
- } else
+ } else {
+ /* here, we should also add an redundancy check */
is->last_link_seqno = sqno;
+ }
+ /*
+ * step over all links to find lowest link number
+ */
for (min_sqno = LONG_MAX, lpq = net_dev->queue;;) {
long lls = ippp_table[lpq->ppp_slot]->last_link_seqno;
if (lls >= 0 && lls < min_sqno)
@@ -1006,11 +1033,14 @@
if (lpq == net_dev->queue)
break;
}
- if (min_sqno >= ippp_table[lpq->ppp_slot]->range) { /* OK, every link overflowed */
- int mask = ippp_table[lpq->ppp_slot]->range - 1; /* range is a power of 2 */
-#if 0
- isdn_ppp_cleanup_queue(net_dev, min_sqno);
-#endif
+
+ /*
+ * for the case, that the last frame numbers of all
+ * links are overflowed: mask/reduce the sequenece number to
+ * 'normal' numbering.
+ */
+ if (min_sqno >= ippp_table[lpq->ppp_slot]->range) {
+ int mask = ippp_table[lpq->ppp_slot]->range-1; /* range is power of two, so a mask will do the job */
isdn_ppp_mask_queue(net_dev, mask);
net_dev->ib.next_num &= mask;
{
@@ -1064,7 +1094,6 @@
if (!q) {
net_dev->ib.modify = 0;
printk(KERN_WARNING "ippp/MPPP: Bad! Can't alloc sq node!\n");
- SET_SKB_FREE(skb);
dev_kfree_skb(skb);
return; /* discard */
}
@@ -1093,7 +1122,8 @@
* packet was 'in order' .. push it higher
*/
net_dev->ib.next_num = sqno_end + 1;
- isdn_ppp_push_higher(net_dev, lp, skb, -1);
+ proto = isdn_ppp_strip_proto(skb);
+ isdn_ppp_push_higher(net_dev, lp, skb, proto);
}
isdn_ppp_cleanup_sqqueue(net_dev, lp, min_sqno);
net_dev->ib.modify = 0;
@@ -1102,7 +1132,7 @@
isdn_ppp_push_higher(net_dev, lp, skb, proto);
} else
#endif
- isdn_ppp_push_higher(net_dev, lp, skb, -1);
+ isdn_ppp_push_higher(net_dev, lp, skb, proto);
}
/*
@@ -1115,19 +1145,21 @@
struct device *dev = &net_dev->dev;
struct ippp_struct *is = ippp_table[lp->ppp_slot];
- if (proto < 0) { /* MP, oder normales Paket bei REJ_MP, MP Pakete gehen bei REJ zum pppd */
- if (skb->data[0] & 0x01) { /* is it odd? */
- proto = (unsigned char) skb->data[0];
- skb_pull(skb, 1); /* protocol ID is only 8 bit */
- } else {
- proto = ((int) (unsigned char) skb->data[0] << 8) + (unsigned char) skb->data[1];
- skb_pull(skb, 2);
- }
- }
if (is->debug & 0x10) {
printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
isdn_ppp_frame_log("rpush", skb->data, skb->len, 32);
}
+
+ if(proto == PPP_COMP) {
+ if(!lp->master)
+ skb = isdn_ppp_decompress(skb,is,is);
+ else
+ skb = isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot]);
+ if(!skb)
+ return;
+ proto = isdn_ppp_strip_proto(skb);
+ }
+
switch (proto) {
case PPP_IPX: /* untested */
if (is->debug & 0x20)
@@ -1140,10 +1172,9 @@
case PPP_VJC_UNCOMP:
if (is->debug & 0x20)
printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
- if (slhc_remember(ippp_table[net_dev->local.ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
+ if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
- net_dev->local.stats.rx_dropped++;
- SET_SKB_FREE(skb);
+ net_dev->local->stats.rx_dropped++;
dev_kfree_skb(skb);
return;
}
@@ -1164,11 +1195,9 @@
int pkt_len;
skb = dev_alloc_skb(skb_old->len + 40);
- SET_SKB_FREE(skb_old);
-
if (!skb) {
printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
- net_dev->local.stats.rx_dropped++;
+ net_dev->local->stats.rx_dropped++;
dev_kfree_skb(skb_old);
return;
}
@@ -1176,11 +1205,10 @@
skb_put(skb, skb_old->len + 40);
memcpy(skb->data, skb_old->data, skb_old->len);
skb->mac.raw = skb->data;
- pkt_len = slhc_uncompress(ippp_table[net_dev->local.ppp_slot]->slcomp,
+ pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp,
skb->data, skb_old->len);
dev_kfree_skb(skb_old);
if (pkt_len < 0) {
- SET_SKB_FREE(skb);
dev_kfree_skb(skb);
lp->stats.rx_dropped++;
return;
@@ -1191,20 +1219,21 @@
#else
printk(KERN_INFO "isdn: Ooopsa .. VJ-Compression support not compiled into isdn driver.\n");
lp->stats.rx_dropped++;
- SET_SKB_FREE(skb);
dev_kfree_skb(skb);
return;
#endif
break;
+ case PPP_CCP:
+ isdn_ppp_receive_ccp(net_dev,lp,skb);
+ /* fall through */
default:
isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot); /* push data to pppd device */
- SET_SKB_FREE(skb);
dev_kfree_skb(skb);
return;
}
netif_rx(skb);
- /* net_dev->local.stats.rx_packets++; *//* done in isdn_net.c */
+ /* net_dev->local->stats.rx_packets++; *//* done in isdn_net.c */
/* Reset hangup-timer */
lp->huptimer = 0;
@@ -1212,6 +1241,24 @@
}
/*
+ * isdn_ppp_skb_push ..
+ * checks whether we have enough space at the beginning of the SKB
+ * and allocs a new SKB if necessary
+ */
+static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len)
+{
+ struct sk_buff *skb = *skb_p;
+
+ if(skb_headroom(skb) < len) {
+ printk(KERN_ERR "isdn_ppp_skb_push:under %d %d\n",skb_headroom(skb),len);
+ dev_kfree_skb(skb);
+ return NULL;
+ }
+ return skb_push(skb,len);
+}
+
+
+/*
* send ppp frame .. we expect a PIDCOMPressable proto --
* (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
*
@@ -1223,12 +1270,10 @@
isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
{
struct device *mdev = ((isdn_net_local *) (dev->priv))->master; /* get master (for redundancy) */
- isdn_net_local *lp,
- *mlp;
+ isdn_net_local *lp,*mlp;
isdn_net_dev *nd;
unsigned int proto = PPP_IP; /* 0x21 */
- struct ippp_struct *ipt,
- *ipts;
+ struct ippp_struct *ipt,*ipts;
if (mdev)
mlp = (isdn_net_local *) (mdev->priv);
@@ -1250,6 +1295,7 @@
printk(KERN_INFO "%s: IP frame delayed.\n", dev->name);
return 1;
}
+
switch (ntohs(skb->protocol)) {
case ETH_P_IP:
proto = PPP_IP;
@@ -1297,11 +1343,18 @@
* after this line .. requeueing in the device queue is no longer allowed!!!
*/
+ /* Pull off the fake header we stuck on earlier to keep
+ * the fragemntation code happy.
+ * this will break the ISDN_SYNCPPP_READDRESS hack a few lines
+ * above. So, enabling this is no longer allowed
+ */
+ skb_pull(skb,IPPP_MAX_HEADER);
+
if (ipt->debug & 0x4)
printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
#ifdef CONFIG_ISDN_PPP_VJ
- if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes .. but this check again */
+ if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */
struct sk_buff *new_skb;
new_skb = dev_alloc_skb(skb->len);
@@ -1310,14 +1363,13 @@
int pktlen;
new_skb->dev = skb->dev;
- SET_SKB_FREE(new_skb);
skb_put(new_skb, skb->len);
buf = skb->data;
pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data,
&buf, !(ipts->pppcfg & SC_NO_TCP_CCID));
- if (buf != skb->data) { /* copied to new buffer ??? (btw: WHY must slhc copy it?? *sigh*) */
+ if (buf != skb->data) {
if (new_skb->data != buf)
printk(KERN_ERR "isdn_ppp: FATAL error after slhc_compress!!\n");
dev_kfree_skb(skb);
@@ -1339,6 +1391,11 @@
}
#endif
+ /*
+ * normal or bundle compression
+ */
+ skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
+
if (ipt->debug & 0x24)
printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
@@ -1349,13 +1406,17 @@
ipts->mp_seqno++;
nd->queue = nd->queue->next;
if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) {
- unsigned char *data = skb_push(skb, 3);
+ unsigned char *data = isdn_ppp_skb_push(&skb, 3);
+ if(!data)
+ return 0;
mp_seqno &= 0xfff;
- data[0] = MP_BEGIN_FRAG | MP_END_FRAG | (mp_seqno >> 8); /* (B)egin & (E)ndbit .. */
+ data[0] = MP_BEGIN_FRAG | MP_END_FRAG | ((mp_seqno >> 8) & 0xf); /* (B)egin & (E)ndbit .. */
data[1] = mp_seqno & 0xff;
data[2] = proto; /* PID compression */
} else {
- unsigned char *data = skb_push(skb, 5);
+ unsigned char *data = isdn_ppp_skb_push(&skb, 5);
+ if(!data)
+ return 0;
data[0] = MP_BEGIN_FRAG | MP_END_FRAG; /* (B)egin & (E)ndbit .. */
data[1] = (mp_seqno >> 16) & 0xff; /* sequence number: 24bit */
data[2] = (mp_seqno >> 8) & 0xff;
@@ -1365,17 +1426,29 @@
proto = PPP_MP; /* MP Protocol, 0x003d */
}
#endif
+
+ /*
+ * 'link' compression
+ */
+ skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
+
if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) {
- unsigned char *data = skb_push(skb,1);
+ unsigned char *data = isdn_ppp_skb_push(&skb,1);
+ if(!data)
+ return 0;
data[0] = proto & 0xff;
}
else {
- unsigned char *data = skb_push(skb,2);
+ unsigned char *data = isdn_ppp_skb_push(&skb,2);
+ if(!data)
+ return 0;
data[0] = (proto >> 8) & 0xff;
data[1] = proto & 0xff;
}
if(!(ipt->pppcfg & SC_COMP_AC)) {
- unsigned char *data = skb_push(skb,2);
+ unsigned char *data = isdn_ppp_skb_push(&skb,2);
+ if(!data)
+ return 0;
data[0] = 0xff; /* All Stations */
data[1] = 0x03; /* Unnumbered information */
}
@@ -1406,10 +1479,8 @@
p->ib.sq = NULL;
while (q) {
struct sqqueue *qn = q->next;
- if (q->skb) {
- SET_SKB_FREE(q->skb);
+ if (q->skb)
dev_kfree_skb(q->skb);
- }
kfree(q);
q = qn;
}
@@ -1424,7 +1495,6 @@
while (q) {
struct mpqueue *ql = q->next;
- SET_SKB_FREE(q->skb);
dev_kfree_skb(q->skb);
kfree(q);
q = ql;
@@ -1599,7 +1669,6 @@
if (!(*skb)) {
while (q) {
struct mpqueue *ql = q->next;
- SET_SKB_FREE(q->skb);
dev_kfree_skb(q->skb);
kfree(q);
q = ql;
@@ -1612,7 +1681,6 @@
struct mpqueue *ql = q->next;
memcpy((*skb)->data + cnt, q->skb->data, q->skb->len);
cnt += q->skb->len;
- SET_SKB_FREE(q->skb);
dev_kfree_skb(q->skb);
kfree(q);
q = ql;
@@ -1632,13 +1700,15 @@
struct sqqueue *q;
while ((q = net_dev->ib.sq) && (q->sqno_start == net_dev->ib.next_num || q->sqno_end <= min_sqno)) {
+ int proto;
if (q->sqno_start != net_dev->ib.next_num) {
printk(KERN_DEBUG "ippp: MP, stepping over missing frame: %ld\n", net_dev->ib.next_num);
#ifdef CONFIG_ISDN_PPP_VJ
- slhc_toss(ippp_table[net_dev->local.ppp_slot]->slcomp);
+ slhc_toss(ippp_table[net_dev->local->ppp_slot]->slcomp);
#endif
}
- isdn_ppp_push_higher(net_dev, lp, q->skb, -1);
+ proto = isdn_ppp_strip_proto(q->skb);
+ isdn_ppp_push_higher(net_dev, lp, q->skb, proto);
net_dev->ib.sq = q->next;
net_dev->ib.next_num = q->sqno_end + 1;
kfree(q);
@@ -1663,32 +1733,30 @@
struct mpqueue *ql,
*q = dev->mp_last;
- while (q) {
- if (q->sqno < min_sqno) {
- if (q->BEbyte & MP_END_FRAG) {
- printk(KERN_DEBUG "ippp: freeing stale packet!\n");
- if ((dev->mp_last = q->next))
- q->next->last = NULL;
- while (q) {
- ql = q->last;
- SET_SKB_FREE(q->skb);
- dev_kfree_skb(q->skb);
- kfree(q);
+ while(q && (q->sqno < min_sqno) ) {
+ if ( (q->BEbyte & MP_END_FRAG) ||
+ (q->next && (q->next->sqno <= min_sqno) && (q->next->BEbyte & MP_BEGIN_FRAG)) ) {
+ printk(KERN_DEBUG "ippp: freeing stale packet(s), min_sq: %ld!\n",min_sqno);
+ if ((dev->mp_last = q->next))
+ q->next->last = NULL;
+ while (q) {
+ ql = q->last;
+ printk(KERN_DEBUG "ippp, freeing packet with sqno: %ld\n",q->sqno);
+ dev_kfree_skb(q->skb);
+ kfree(q);
#ifdef CONFIG_ISDN_PPP_VJ
- toss = 1;
+ toss = 1;
#endif
- q = ql;
- }
- q = dev->mp_last;
- } else
- q = q->next;
+ q = ql;
+ }
+ q = dev->mp_last;
} else
- break;
+ q = q->next;
}
#ifdef CONFIG_ISDN_PPP_VJ
/* did we free a stale frame ? */
if (toss)
- slhc_toss(ippp_table[dev->local.ppp_slot]->slcomp);
+ slhc_toss(ippp_table[dev->local->ppp_slot]->slcomp);
#endif
}
@@ -1708,7 +1776,7 @@
*qn;
while (net_dev) {
- isdn_net_local *lp = &net_dev->local;
+ isdn_net_local *lp = net_dev->local;
if (net_dev->ib.modify || lp->master) { /* interface locked or slave? */
net_dev = net_dev->next;
continue;
@@ -1728,7 +1796,8 @@
net_dev->ib.next_num = q->sqno_end + 1;
q->next = NULL;
for (; ql;) {
- isdn_ppp_push_higher(net_dev, lp, ql->skb, -1);
+ int proto = isdn_ppp_strip_proto(ql->skb);
+ isdn_ppp_push_higher(net_dev, lp, ql->skb, proto);
qn = ql->next;
kfree(ql);
ql = qn;
@@ -1804,7 +1873,7 @@
case SIOCGPPPVER:
r = (char *) ifr->ifr_ifru.ifru_data;
len = strlen(PPP_VERSION) + 1;
- error = copy_to_user(r, PPP_VERSION, len);
+ error = copy_to_user(r, PPP_VERSION, len);
break;
case SIOCGPPPSTATS:
error = isdn_ppp_dev_ioctl_stats(lp->ppp_slot, ifr, dev);
@@ -1853,7 +1922,7 @@
if (!(ndev = isdn_net_findif(name)))
return 1;
- lp = &ndev->local;
+ lp = ndev->local;
if (!(lp->flags & ISDN_NET_CONNECTED))
return 5;
@@ -1884,7 +1953,7 @@
if (!(ndev = isdn_net_findif(name)))
return 1;
- lp = &ndev->local;
+ lp = ndev->local;
if (!(lp->flags & ISDN_NET_CONNECTED))
return 5;
@@ -1905,6 +1974,128 @@
#endif
}
+/*
+ * PPP compression stuff
+ */
+static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master)
+{
+#if 1
+ printk(KERN_ERR "compression not included!\n");
+ dev_kfree_skb(skb);
+ return NULL;
+#else
+ if(!master) {
+ /*
+ * single link compression
+ */
+ if(!is->link_compressor) {
+ printk(KERN_ERR "ippp: no (link) compressor defined!\n");
+ dev_kfree_skb(skb);
+ return NULL;
+ }
+ if(!is->link_decomp_stat) {
+ printk(KERN_DEBUG "ippp: initialize link compressor\n");
+ }
+/*
+ -> decompress link
+*/
+ }
+ else {
+ /*
+ * 'normal' or bundle-compression
+ */
+ if(!master->compressor) {
+ printk(KERN_ERR "ippp: no (link) compressor defined!\n");
+ dev_kfree_skb(skb);
+ return NULL;
+ }
+ if(!master->decomp_stat) {
+#if 0
+ master->decomp_stat = (master->compressor->decomp_alloc)( .. );
+#endif
+ printk(KERN_DEBUG "ippp: initialize compressor\n");
+ }
+ }
+
+ return skb;
+#endif
+}
+
+/*
+ * compress a frame
+ * type=0: normal/bundle compression
+ * =1: link compression
+ * returns original skb if we haven't compressed the frame
+ * and a new skb pointer if we've done it
+ */
+static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
+ struct ippp_struct *is,struct ippp_struct *master,int type)
+{
+#if 1
+ return skb_in;
+#else
+ int ret;
+ int new_proto;
+ struct isdn_ppp_compressor *compressor;
+ void *stat;
+ struct sk_buff *skb_out;
+
+ if(type) { /* type=1 => Link compression */
+ compressor = is->link_compressor;
+ stat = is->link_comp_stat;
+ new_proto = PPP_LINK_COMP;
+ }
+ else {
+ if(!master) {
+ compressor = is->compressor;
+ stat = is->comp_stat;
+ }
+ else {
+ compressor = master->compressor;
+ stat = master->comp_stat;
+ }
+ new_proto = PPP_COMP;
+ }
+
+ if(!compressor) {
+ printk(KERN_ERR "No compressor set!\n");
+ return skb_in;
+ }
+ if(!stat) {
+ /* init here ? */
+ return skb_in;
+ }
+
+ skb_out = dev_alloc_skb(skb_in->len);
+ if(!skb_out)
+ return skb_in;
+
+ ret = (compressor->compress)(stat,skb_in,skb_out,*proto);
+ if(!ret) {
+ dev_kfree_skb(skb_out);
+ return skb_in;
+ }
+
+ dev_kfree_skb(skb_in);
+ *proto = new_proto;
+ return skb_out;
+#endif
+
+}
+
+/*
+ * we received a CCP frame ..
+ * not a clean solution, but we SHOULD handle a few cased in the kernel
+ */
+static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
+ struct sk_buff *skb)
+{
+#if 0
+ printk(KERN_DEBUG "isdn_ppp_receive_cpp: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ skb->data[0],skb->data[1],skb->data[2],skb->data[3],
+ skb->data[4],skb->data[5],skb->data[6],skb->data[7] );
+#endif
+}
int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
{
@@ -1937,6 +2128,7 @@
if(ipc->num == num) {
return 0;
is->compressor = ipc;
+ is->link_compressor = ipc;
}
ipc = ipc->next;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov