patch-2.0.26 linux/drivers/isdn/isdn_ppp.c
Next file: linux/drivers/isdn/isdn_ppp.h
Previous file: linux/drivers/isdn/isdn_net.c
Back to the patch index
Back to the overall index
- Lines: 787
- Date:
Wed Nov 13 08:36:19 1996
- Orig file:
v2.0.25/linux/drivers/isdn/isdn_ppp.c
- Orig date:
Sun Sep 1 09:15:32 1996
diff -u --recursive --new-file v2.0.25/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.14 1996/08/12 16:26:47 hipp Exp $
+/* $Id: isdn_ppp.c,v 1.20 1996/10/30 12:21:58 fritz Exp $
*
* Linux ISDN subsystem, functions for synchronous PPP (linklevel).
*
@@ -19,6 +19,25 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_ppp.c,v $
+ * Revision 1.20 1996/10/30 12:21:58 fritz
+ * Cosmetic fix: Compiler warning when compiling without MPP.
+ *
+ * Revision 1.19 1996/10/25 19:03:21 hipp
+ * changed/added some defines to (re)allow compilation without MP/VJ
+ *
+ * Revision 1.18 1996/10/22 23:14:00 fritz
+ * Changes for compatibility to 2.0.X and 2.1.X kernels.
+ *
+ * Revision 1.17 1996/10/22 09:39:49 hipp
+ * a few MP changes and bugfixes
+ *
+ * Revision 1.16 1996/09/23 01:58:10 fritz
+ * Fix: With syncPPP encapsulation, discard LCP packets
+ * when calculating hangup timeout.
+ *
+ * Revision 1.15 1996/09/07 12:50:12 hipp
+ * bugfixes (unknown device after failed dial attempt, minor bugs)
+ *
* Revision 1.14 1996/08/12 16:26:47 hipp
* code cleanup
* changed connection management from minors to slots
@@ -73,6 +92,8 @@
/* TODO: right tbusy handling when using MP */
+#undef ISDN_SYNCPPP_READDRESS
+
#include <linux/config.h>
#define __NO_VERSION__
#include <linux/module.h>
@@ -84,6 +105,8 @@
#ifndef PPP_IPX
#define PPP_IPX 0x002b
#endif
+
+/* set this if you use dynamic addressing */
/* Prototypes */
static int isdn_ppp_fill_rq(unsigned char *buf, int len,int proto, int slot);
@@ -95,23 +118,45 @@
#ifdef CONFIG_ISDN_MPP
static int isdn_ppp_bundle(struct ippp_struct *, int unit);
static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask);
-static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min);
+static void isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min);
+static void isdn_ppp_cleanup_sqqueue(isdn_net_dev * dev,isdn_net_local *, long min);
static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb,
- int BEbyte, int *sqno, int min_sqno);
+ int BEbyte, long *sqno, int min_sqno);
#endif
-char *isdn_ppp_revision = "$Revision: 1.14 $";
+char *isdn_ppp_revision = "$Revision: 1.20 $";
+
struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
extern int isdn_net_force_dial_lp(isdn_net_local *);
/*
+ * frame log (debug)
+ */
+static void isdn_ppp_frame_log(char *info,char *data,int len,int maxlen)
+{
+ int cnt,j,i;
+ char buf[80];
+
+ if(len < maxlen)
+ maxlen = len;
+
+ for(i=0,cnt=0;cnt<maxlen;i++) {
+ for(j=0;j<16 && cnt<maxlen;j++,cnt++)
+ sprintf(buf+j*3,"%02x ",(unsigned char) data[cnt]);
+ printk(KERN_DEBUG "%s[%d]: %s\n",info,i,buf);
+ }
+}
+
+/*
* unbind isdn_net_local <=> ippp-device
* note: it can happen, that we hangup/free the master before the slaves
*/
int isdn_ppp_free(isdn_net_local *lp)
{
+#ifdef CONFIG_ISDN_MPP
isdn_net_local *master_lp=lp;
+#endif
unsigned long flags;
struct ippp_struct *is;
@@ -131,7 +176,7 @@
if(master_lp->netdev->queue == lp) {
master_lp->netdev->queue = lp->next;
if(lp->next == lp) { /* last link in queue? */
- master_lp->netdev->ib.bundled = 0;
+ master_lp->netdev->ib.bundled = 0;
isdn_ppp_free_mpqueue(master_lp->netdev);
isdn_ppp_free_sqqueue(master_lp->netdev);
}
@@ -139,12 +184,20 @@
lp->next = lp->last = lp; /* (re)set own pointers */
#endif
- isdn_ppp_closewait(lp->ppp_slot); /* force wakeup on ippp device */
+ if( (is->state & IPPP_CONNECT) )
+ isdn_ppp_closewait(lp->ppp_slot); /* force wakeup on ippp device */
+ else if(is->state & IPPP_ASSIGNED)
+ is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGEND' staet */
+
if(is->debug & 0x1)
printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp,(long) is->lp);
is->lp = NULL; /* link is down .. set lp to NULL */
+#ifdef ISDN_SYNCPPP_READDRESS
+ is->old_pa_addr = 0x0;
+ is->old_pa_dstaddr = 0x0;
+#endif
lp->ppp_slot = -1; /* is this OK ?? */
restore_flags(flags);
@@ -209,7 +262,7 @@
is = ippp_table[i];
is->lp = lp;
is->unit = unit;
- is->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
+ is->state = IPPP_OPEN | IPPP_ASSIGNED; /* assigned to a netdevice but not connected */
restore_flags(flags);
@@ -223,6 +276,11 @@
void isdn_ppp_wakeup_daemon(isdn_net_local *lp)
{
+ if(lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS)
+ return;
+
+ ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
+
if (ippp_table[lp->ppp_slot]->wq)
wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
}
@@ -270,6 +328,9 @@
int slot;
struct ippp_struct *is;
+ if(min < 0 || min > ISDN_MAX_CHANNELS)
+ return -ENODEV;
+
slot = isdn_ppp_get_slot();
if(slot < 0) {
return -EBUSY;
@@ -322,11 +383,15 @@
printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp);
if (is->lp) { /* a lp address says: this link is still up */
- isdn_net_dev *p = dev->netdev;
- p = is->lp->netdev;
- is->lp->ppp_slot = -1;
- isdn_net_hangup(&p->dev); /* lp->ppp_slot==-1 => no calling of isdn_ppp_closewait() */
- is->lp = NULL;
+ isdn_net_dev *p = is->lp->netdev;
+
+ is->state &= ~IPPP_CONNECT; /* -> effect: no call of wakeup */
+ /*
+ * isdn_net_hangup() calls isdn_ppp_free()
+ * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1
+ * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon()
+ */
+ isdn_net_hangup(&p->dev);
}
for (i = 0; i < NUM_RCV_BUFFS; i++) {
if (is->rq[i].buf) {
@@ -348,24 +413,33 @@
/*
* get_arg .. ioctl helper
*/
-static int get_arg(void *b, unsigned long *val)
+static int get_arg(void *b,void *val,int len)
{
int r;
- if ((r = verify_area(VERIFY_READ, (void *) b, sizeof(unsigned long))))
+ if(len <= 0)
+ len = sizeof(unsigned long);
+ if ((r = verify_area(VERIFY_READ, (void *) b, len )))
return r;
- memcpy_fromfs((void *) val, b, sizeof(unsigned long));
+ copy_from_user((void *) val, b, len );
return 0;
}
/*
* set arg .. ioctl helper
*/
-static int set_arg(void *b, unsigned long val)
+static int set_arg(void *b, unsigned long val,void *str)
{
int r;
- if ((r = verify_area(VERIFY_WRITE, b, sizeof(unsigned long))))
- return r;
- memcpy_tofs(b, (void *) &val, sizeof(unsigned long));
+ if(!str) {
+ if ((r = verify_area(VERIFY_WRITE, b, 4 )))
+ return r;
+ copy_to_user(b, (void *) &val, 4 );
+ }
+ else {
+ if ((r = verify_area(VERIFY_WRITE, b,val)))
+ return r;
+ copy_to_user(b,str,val);
+ }
return 0;
}
@@ -389,7 +463,9 @@
switch (cmd) {
case PPPIOCBUNDLE:
#ifdef CONFIG_ISDN_MPP
- if ((r = get_arg((void *) arg, &val)))
+ if( !(is->state & IPPP_CONNECT) )
+ return -EINVAL;
+ if ((r = get_arg((void *) arg, &val,0)))
return r;
printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
(int) min, (int) is->unit, (int) val);
@@ -399,41 +475,50 @@
#endif
break;
case PPPIOCGUNIT: /* get ppp/isdn unit number */
- if ((r = set_arg((void *) arg, is->unit)))
+ if ((r = set_arg((void *) arg, is->unit,NULL)))
return r;
break;
case PPPIOCGMPFLAGS: /* get configuration flags */
- if ((r = set_arg((void *) arg, is->mpppcfg)))
+ if ((r = set_arg((void *) arg, is->mpppcfg,NULL)))
return r;
break;
case PPPIOCSMPFLAGS: /* set configuration flags */
- if ((r = get_arg((void *) arg, &val)))
+ if ((r = get_arg((void *) arg, &val,0)))
return r;
is->mpppcfg = val;
break;
case PPPIOCGFLAGS: /* get configuration flags */
- if ((r = set_arg((void *) arg, is->pppcfg)))
+ if ((r = set_arg((void *) arg, is->pppcfg,NULL)))
return r;
break;
case PPPIOCSFLAGS: /* set configuration flags */
- if ((r = get_arg((void *) arg, &val))) {
+ if ((r = get_arg((void *) arg, &val,0))) {
return r;
}
- if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP)) {
+ if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT) ) {
isdn_net_local *lp = is->lp;
- lp->netdev->dev.tbusy = 0;
- mark_bh(NET_BH); /* OK .. we are ready to send buffers */
+ if(lp) {
+ lp->netdev->dev.tbusy = 0;
+ mark_bh(NET_BH); /* OK .. we are ready to send buffers */
+ }
}
is->pppcfg = val;
break;
#if 0
case PPPIOCGSTAT: /* read PPP statistic information */
break;
- case PPPIOCGTIME: /* read time delta information */
- break;
#endif
+ case PPPIOCGIDLE: /* get idle time information */
+ if(is->lp)
+ {
+ struct ppp_idle pidle;
+ pidle.xmit_idle = pidle.recv_idle = is->lp->huptimer;
+ if((r = set_arg((void *) arg,sizeof(struct ppp_idle),&pidle)))
+ return r;
+ }
+ break;
case PPPIOCSMRU: /* set receive unit size for PPP */
- if ((r = get_arg((void *) arg, &val)))
+ if ((r = get_arg((void *) arg, &val,0)))
return r;
is->mru = val;
break;
@@ -442,7 +527,7 @@
case PPPIOCSMPMTU:
break;
case PPPIOCSMAXCID: /* set the maximum compression slot id */
- if ((r = get_arg((void *) arg, &val)))
+ if ((r = get_arg((void *) arg, &val,0)))
return r;
val++;
if(is->maxcid != val) {
@@ -465,14 +550,25 @@
}
break;
case PPPIOCGDEBUG:
- if ((r = set_arg((void *) arg, is->debug)))
+ if ((r = set_arg((void *) arg, is->debug,0)))
return r;
break;
case PPPIOCSDEBUG:
- if ((r = get_arg((void *) arg, &val)))
+ if ((r = get_arg((void *) arg, &val,0)))
return r;
is->debug = val;
break;
+ case PPPIOCSCOMPRESS:
+#if 0
+ {
+ struct ppp_option_data pod;
+ r = get_arg((void *) arg,&pod,sizeof(struct ppp_option_data));
+ if(r)
+ return r;
+ ippp_set_compression(is,&pod);
+ }
+#endif
+ break;
default:
break;
}
@@ -607,7 +703,7 @@
}
if (b->len < count)
count = b->len;
- memcpy_tofs(buf, b->buf, count);
+ copy_to_user(buf, b->buf, count);
kfree(b->buf);
b->buf = NULL;
is->first = b;
@@ -624,6 +720,8 @@
{
isdn_net_local *lp;
struct ippp_struct *is;
+ int proto;
+ unsigned char protobuf[4];
is = file->private_data;
@@ -637,12 +735,21 @@
if (!lp)
printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n");
else {
- lp->huptimer = 0;
+ /*
+ * Don't reset huptimer for
+ * LCP packets. (Echo requests).
+ */
+ copy_from_user(protobuf, buf, 4);
+ proto = PPP_PROTOCOL(protobuf);
+ if (proto != PPP_LCP)
+ lp->huptimer = 0;
+
if (lp->isdn_device < 0 || lp->isdn_channel < 0)
return 0;
if (dev->drv[lp->isdn_device]->running && lp->dialstate == 0 &&
(lp->flags & ISDN_NET_CONNECTED)) {
+ int cnt;
struct sk_buff *skb;
skb = dev_alloc_skb(count);
if(!skb) {
@@ -650,17 +757,22 @@
return count;
}
skb->free = 1;
- memcpy_fromfs(skb_put(skb, count), buf, count);
- if(isdn_writebuf_skb_stub(lp->isdn_device,lp->isdn_channel,skb) != count) {
+ copy_from_user(skb_put(skb, count), buf, count);
+ if(is->debug & 0x40) {
+ printk(KERN_DEBUG "ppp xmit: len %ld\n",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(lp->sav_skb) {
dev_kfree_skb(lp->sav_skb,FREE_WRITE);
- printk(KERN_INFO "isdn_ppp_write: freeing sav_skb!\n");
+ printk(KERN_INFO "isdn_ppp_write: freeing sav_skb (%d,%d)!\n",cnt,count);
}
+ else
+ printk(KERN_INFO "isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n",cnt,count);
lp->sav_skb = skb;
}
}
}
-
return count;
}
@@ -706,14 +818,15 @@
/*
* 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)
{
struct ippp_struct *is;
is = ippp_table[lp->ppp_slot];
- if(is->debug & 0x4)
- printk(KERN_DEBUG "recv skb, len: %ld\n",skb->len);
+ if(is->debug & 0x4) {
+ printk(KERN_DEBUG "ippp_receive: len: %ld\n",skb->len);
+ isdn_ppp_frame_log("receive",skb->data,skb->len,32);
+ }
if(net_dev->local.master) {
printk(KERN_WARNING "isdn_ppp_receice: net_dev != master\n");
@@ -741,7 +854,7 @@
}
if (proto == PPP_MP) {
isdn_net_local *lpq;
- int 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 ,
@@ -758,7 +871,7 @@
if ((tseq = is->last_link_seqno) >= sqno) {
int range = is->range;
if (tseq + 1024 < range + sqno) /* redundancy check .. not MP conform */
- printk(KERN_WARNING "isdn_ppp_receive, MP, detected overflow with sqno: %d, last: %d !!!\n", sqno, tseq);
+ printk(KERN_WARNING "isdn_ppp_receive, MP, detected overflow with sqno: %ld, last: %ld !!!\n", sqno, tseq);
else {
sqno += range;
is->last_link_seqno = sqno;
@@ -766,16 +879,19 @@
} else
is->last_link_seqno = sqno;
- for (min_sqno = 0, lpq = net_dev->queue;;) {
- if (ippp_table[lpq->ppp_slot]->last_link_seqno > min_sqno)
- min_sqno = ippp_table[lpq->ppp_slot]->last_link_seqno;
+ 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)
+ min_sqno = lls;
lpq = lpq->next;
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
isdn_ppp_mask_queue(net_dev, mask);
net_dev->ib.next_num &= mask;
{
@@ -795,11 +911,18 @@
}
if ((BEbyte & (MP_BEGIN_FRAG | MP_END_FRAG)) != (MP_BEGIN_FRAG | MP_END_FRAG)) {
printk(KERN_DEBUG "ippp: trying ;) to fill mp_queue %d .. UNTESTED!!\n", lp->ppp_slot);
- if ((sqno_end = isdn_ppp_fill_mpqueue(net_dev, &skb , BEbyte, &sqno, min_sqno)) < 0)
+ if ((sqno_end = isdn_ppp_fill_mpqueue(net_dev, &skb , BEbyte, &sqno, min_sqno)) < 0) {
+ net_dev->ib.modify = 1; /* block timeout-timer */
+ isdn_ppp_cleanup_sqqueue(net_dev,lp,min_sqno);
+ net_dev->ib.modify = 0;
return; /* no packet complete */
+ }
} else
sqno_end = sqno;
+ if(is->debug & 0x40)
+ printk(KERN_DEBUG "min_sqno: %ld sqno_end %d next: %ld\n",min_sqno,sqno_end,net_dev->ib.next_num );
+
/*
* MP buffer management .. reorders incoming packets ..
* lotsa mem-copies and not heavily tested.
@@ -842,27 +965,14 @@
ql->next = q;
}
}
- net_dev->ib.modify = 0;
- return;
} else {
/*
* packet was 'in order' .. push it higher
*/
- struct sqqueue *q;
-
net_dev->ib.next_num = sqno_end + 1;
isdn_ppp_push_higher(net_dev, lp, skb, -1);
-
- /*
- * check queue, whether we have still buffered the next packet(s)
- */
- while ((q = net_dev->ib.sq) && q->sqno_start == net_dev->ib.next_num) {
- isdn_ppp_push_higher(net_dev, lp, q->skb, -1);
- net_dev->ib.sq = q->next;
- net_dev->ib.next_num = q->sqno_end + 1;
- kfree(q);
- }
}
+ isdn_ppp_cleanup_sqqueue(net_dev,lp,min_sqno);
net_dev->ib.modify = 0;
} else
@@ -872,7 +982,6 @@
isdn_ppp_push_higher(net_dev, lp, skb , -1);
}
-
/*
* push frame to higher layers
* note: net_dev has to be master net_dev
@@ -892,13 +1001,15 @@
}
}
- if(is->debug & 0x10)
+ if(is->debug & 0x10) {
printk(KERN_DEBUG "push, skb %ld %04x\n",skb->len,proto);
+ isdn_ppp_frame_log("rpush",skb->data,skb->len,32);
+ }
switch (proto) {
case PPP_IPX: /* untested */
if(is->debug & 0x20)
- printk(KERN_DEBUG "isdn_ppp: _IPX\n");
+ printk(KERN_DEBUG "isdn_ppp: IPX\n");
skb->dev = dev;
skb->mac.raw = skb->data;
skb->protocol = htons(ETH_P_IPX);
@@ -971,7 +1082,7 @@
}
netif_rx(skb);
- net_dev->local.stats.rx_packets++;
+/* net_dev->local.stats.rx_packets++; */ /* done in isdn_net.c */
/* Reset hangup-timer */
lp->huptimer = 0;
@@ -986,7 +1097,7 @@
* skb isn't allowed!!
*/
-static void isdn_ppp_skb_destructor(struct sk_buff *skb)
+static void isdn_ppp_skb_destructor(struct sk_buff *skb) /* debug function */
{
char outstr[80],*outpnt=outstr;
int i;
@@ -1009,22 +1120,55 @@
if(mdev)
mlp = (isdn_net_local *) (mdev->priv);
- else
+ else {
+ mdev = dev;
mlp = (isdn_net_local *) (dev->priv);
+ }
nd = mlp->netdev; /* get master lp */
ipts = ippp_table[mlp->ppp_slot];
if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
+#ifdef ISDN_SYNCPPP_READDRESS
+ if(!ipts->old_pa_addr)
+ ipts->old_pa_addr = mdev->pa_addr;
+ if(!ipts->old_pa_dstaddr)
+ ipts->old_pa_dstaddr = mdev->pa_dstaddr;
+#endif
if(ipts->debug & 0x1) {
printk(KERN_INFO "%s: IP frame delayed.\n",dev->name);
skb->destructor = isdn_ppp_skb_destructor;
}
return 1;
- }
+ }
skb->destructor = NULL;
+ switch(ntohs(skb->protocol)) {
+ case ETH_P_IP:
+ proto = PPP_IP;
+#ifdef ISDN_SYNCPPP_READDRESS
+ if(ipts->old_pa_addr != mdev->pa_addr)
+ {
+ struct iphdr *ipfr;
+ ipfr = (struct iphdr *) skb->data;
+printk(KERN_DEBUG "IF-address changed from %lx to %lx\n",ipts->old_pa_addr,mdev->pa_addr);
+ if(ipfr->version == 4) {
+ if(ipfr->saddr == ipts->old_pa_addr) {
+printk(KERN_DEBUG "readdressing %lx to %lx\n",ipfr->saddr,mdev->pa_addr);
+ ipfr->saddr = mdev->pa_addr;
+ }
+ }
+ }
+ /* dstaddr change not so improtant */
+#endif
+ break;
+ case ETH_P_IPX:
+ proto = PPP_IPX; /* untested */
+ break;
+ }
+
lp = nd->queue; /* get lp on top of queue */
+
if(lp->sav_skb) { /* find a non-busy device */
isdn_net_local *nlp = lp->next;
while(lp->sav_skb) {
@@ -1046,7 +1190,7 @@
printk(KERN_DEBUG "xmit skb, len %ld\n",skb->len);
#ifdef CONFIG_ISDN_PPP_VJ
- if (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 this check again */
struct sk_buff *new_skb;
new_skb = dev_alloc_skb(skb->len);
@@ -1118,6 +1262,12 @@
skb->data[3] = proto & 0xff;
/* tx-stats are now updated via BSENT-callback */
+
+ if(ipts->debug & 0x40) {
+ printk(KERN_DEBUG "skb xmit: len: %ld\n",skb->len);
+ isdn_ppp_frame_log("xmit",skb->data,skb->len,32);
+ }
+
if(isdn_net_send_skb(dev , lp , skb)) {
if(lp->sav_skb) { /* whole sav_skb processing with disabled IRQs ?? */
printk(KERN_ERR "%s: whoops .. there is another stored skb!\n",dev->name);
@@ -1129,6 +1279,8 @@
return 0;
}
+#ifdef CONFIG_ISDN_MPP
+
void isdn_ppp_free_sqqueue(isdn_net_dev * p)
{
struct sqqueue *q = p->ib.sq;
@@ -1158,8 +1310,6 @@
}
}
-#ifdef CONFIG_ISDN_MPP
-
static int isdn_ppp_bundle(struct ippp_struct *is, int unit)
{
char ifn[IFNAMSIZ + 1];
@@ -1215,8 +1365,7 @@
}
}
-
-static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int BEbyte, int *sqnop, int min_sqno)
+static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int BEbyte, long *sqnop, int min_sqno)
{
struct mpqueue *qe, *q1, *q;
long cnt, flags;
@@ -1228,7 +1377,7 @@
printk(KERN_WARNING "isdn_ppp_fill_mpqueue: Can't alloc struct memory.\n");
save_flags(flags);
cli();
- isdn_ppp_cleanup_queue(dev, min_sqno);
+ isdn_ppp_cleanup_mpqueue(dev, min_sqno);
restore_flags(flags);
return -1;
}
@@ -1244,7 +1393,7 @@
dev->mp_last = q1;
q1->next = NULL;
q1->last = NULL;
- isdn_ppp_cleanup_queue(dev, min_sqno); /* not necessary */
+ isdn_ppp_cleanup_mpqueue(dev, min_sqno); /* not necessary */
restore_flags(flags);
return -1;
}
@@ -1278,7 +1427,7 @@
while (!(q->BEbyte & MP_END_FRAG)) {
cnt++;
if (!(q->next) || q->next->sqno != cnt) {
- isdn_ppp_cleanup_queue(dev, min_sqno);
+ isdn_ppp_cleanup_mpqueue(dev, min_sqno);
restore_flags(flags);
return -1;
}
@@ -1293,7 +1442,7 @@
while (!(q->BEbyte & MP_BEGIN_FRAG)) {
cnt--;
if (!(q->last) || q->last->sqno != cnt) {
- isdn_ppp_cleanup_queue(dev, min_sqno);
+ isdn_ppp_cleanup_mpqueue(dev, min_sqno);
restore_flags(flags);
return -1;
}
@@ -1313,7 +1462,7 @@
sqno_end = qe->sqno;
*sqnop = q->sqno;
- isdn_ppp_cleanup_queue(dev, min_sqno);
+ isdn_ppp_cleanup_mpqueue(dev, min_sqno);
restore_flags(flags);
*skb = dev_alloc_skb(pktlen + 40); /* not needed: +40 for VJ compression .. */
@@ -1344,10 +1493,32 @@
}
/*
- * remove stale packets from list
+ * check sq-queue, whether we have still buffered the next packet(s)
+ * or packets with a sqno less or equal to min_sqno
+ * net_dev: master netdevice , lp: 'real' local connection
*/
+static void isdn_ppp_cleanup_sqqueue(isdn_net_dev *net_dev, isdn_net_local *lp,long min_sqno)
+{
+ struct sqqueue *q;
+
+ while ((q = net_dev->ib.sq) && (q->sqno_start == net_dev->ib.next_num || q->sqno_end <= min_sqno) ) {
+ 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);
+#endif
+ }
+ isdn_ppp_push_higher(net_dev, lp, q->skb, -1);
+ net_dev->ib.sq = q->next;
+ net_dev->ib.next_num = q->sqno_end + 1;
+ kfree(q);
+ }
+}
-static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min_sqno)
+/*
+ * remove stale packets from list
+ */
+static void isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min_sqno)
{
#ifdef CONFIG_ISDN_PPP_VJ
int toss = 0;
@@ -1404,9 +1575,9 @@
while (net_dev) {
isdn_net_local *lp = &net_dev->local;
if (net_dev->ib.modify || lp->master) { /* interface locked or slave?*/
- net_dev = net_dev->next;
+ net_dev = net_dev->next;
continue;
- }
+ }
q = net_dev->ib.sq;
while (q) {
@@ -1475,7 +1646,7 @@
}
#endif
}
- memcpy_tofs (res, &t, sizeof (struct ppp_stats));
+ copy_to_user (res, &t, sizeof (struct ppp_stats));
return 0;
}
@@ -1500,7 +1671,7 @@
len = strlen(PPP_VERSION) + 1;
error = verify_area(VERIFY_WRITE, r, len);
if (!error)
- memcpy_tofs(r, PPP_VERSION, len);
+ copy_to_user(r, PPP_VERSION, len);
break;
case SIOCGPPPSTATS:
error = isdn_ppp_dev_ioctl_stats (lp->ppp_slot, ifr, dev);
@@ -1596,4 +1767,14 @@
return -1;
#endif
}
+
+#if 0
+static struct symbol_table isdn_ppp_syms = {
+#include <linux/symtab_begin.h>
+ X(isdn_ppp_register_compressor),
+ X(isdn_ppp_unregister_compressor),
+#include <linux/symtab_end.h>
+};
+#endif
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov