patch-2.0.8 linux/drivers/isdn/isdn_ppp.c
Next file: linux/drivers/net/3c59x.c
Previous file: linux/drivers/isdn/isdn_net.c
Back to the patch index
Back to the overall index
- Lines: 301
- Date:
Wed Jul 17 11:55:48 1996
- Orig file:
v2.0.7/linux/drivers/isdn/isdn_ppp.c
- Orig date:
Wed Jul 3 22:05:09 1996
diff -u --recursive --new-file v2.0.7/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.12 1996/06/24 17:42:03 fritz Exp $
+/* $Id: isdn_ppp.c,v 1.13 1996/07/01 19:47:24 hipp Exp $
*
* Linux ISDN subsystem, functions for synchronous PPP (linklevel).
*
@@ -19,6 +19,9 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Log: isdn_ppp.c,v $
+ * Revision 1.13 1996/07/01 19:47:24 hipp
+ * Fixed memory leak in VJ handling and more VJ changes
+ *
* Revision 1.12 1996/06/24 17:42:03 fritz
* Minor bugfixes.
*
@@ -93,7 +96,7 @@
int BEbyte, int *sqno, int min_sqno);
#endif
-char *isdn_ppp_revision = "$Revision: 1.12 $";
+char *isdn_ppp_revision = "$Revision: 1.13 $";
struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
extern int isdn_net_force_dial_lp(isdn_net_local *);
@@ -137,6 +140,7 @@
ippp_table[lp->ppp_minor]->lp = NULL; /* link is down .. set lp to NULL */
lp->ppp_minor = -1; /* is this OK ?? */
restore_flags(flags);
+
return 0;
}
@@ -254,12 +258,6 @@
/*
* VJ header compression init
*/
- ippp_table[minor]->cbuf = kmalloc(ippp_table[minor]->mru + PPP_HARD_HDR_LEN + 2, GFP_KERNEL);
-
- if (ippp_table[minor]->cbuf == NULL) {
- printk(KERN_DEBUG "ippp: Can't allocate memory buffer for VJ compression.\n");
- return -ENOMEM;
- }
ippp_table[minor]->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
#endif
@@ -300,7 +298,6 @@
#ifdef CONFIG_ISDN_PPP_VJ
slhc_free(ippp_table[minor]->slcomp);
ippp_table[minor]->slcomp = NULL;
- kfree(ippp_table[minor]->cbuf);
#endif
ippp_table[minor]->state = 0;
@@ -673,7 +670,8 @@
if(skb->data[0] == 0xff && skb->data[1] == 0x03)
skb_pull(skb,2);
else if (ippp_table[lp->ppp_minor]->pppcfg & SC_REJ_COMP_AC) {
- dev_kfree_skb(skb,FREE_WRITE);
+ skb->free = 1;
+ dev_kfree_skb(skb,0 /* FREE_READ */ );
return; /* discard it silently */
}
@@ -767,7 +765,8 @@
if (!q) {
net_dev->ib.modify = 0;
printk(KERN_WARNING "ippp/MPPP: Bad! Can't alloc sq node!\n");
- dev_kfree_skb(skb,FREE_WRITE);
+ skb->free = 1;
+ dev_kfree_skb(skb, 0 /* FREE_READ */ );
return; /* discard */
}
q->skb = skb;
@@ -840,30 +839,46 @@
switch (proto) {
case PPP_IPX: /* untested */
+ if(ippp_table[lp->ppp_minor]->debug & 0x20)
+ printk(KERN_DEBUG "isdn_ppp: _IPX\n");
skb->dev = dev;
skb->mac.raw = skb->data;
skb->protocol = htons(ETH_P_IPX);
break;
#ifdef CONFIG_ISDN_PPP_VJ
case PPP_VJC_UNCOMP:
- slhc_remember(ippp_table[net_dev->local.ppp_minor]->slcomp, skb->data, skb->len);
+ if(ippp_table[lp->ppp_minor]->debug & 0x20)
+ printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
+ if(slhc_remember(ippp_table[net_dev->local.ppp_minor]->slcomp, skb->data, skb->len) <= 0) {
+ printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
+ net_dev->local.stats.rx_dropped++;
+ skb->free = 1;
+ dev_kfree_skb(skb,0 /* FREE_READ */ );
+ return;
+ }
#endif
case PPP_IP:
+ if(ippp_table[lp->ppp_minor]->debug & 0x20)
+ printk(KERN_DEBUG "isdn_ppp: IP\n");
skb->dev = dev;
skb->mac.raw = skb->data;
skb->protocol = htons(ETH_P_IP);
break;
case PPP_VJC_COMP:
+ if(ippp_table[lp->ppp_minor]->debug & 0x20)
+ printk(KERN_DEBUG "isdn_ppp: VJC_COMP\n");
#ifdef CONFIG_ISDN_PPP_VJ
{
struct sk_buff *skb_old = skb;
int pkt_len;
skb = dev_alloc_skb(skb_old->len + 40);
+ skb_old->free = 1;
+
if (!skb) {
printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
net_dev->local.stats.rx_dropped++;
- dev_kfree_skb(skb_old,FREE_WRITE);
+ dev_kfree_skb(skb_old,0 /* FREE_READ */ );
return;
}
skb->dev = dev;
@@ -872,9 +887,10 @@
skb->mac.raw = skb->data;
pkt_len = slhc_uncompress(ippp_table[net_dev->local.ppp_minor]->slcomp,
skb->data, skb_old->len);
- dev_kfree_skb(skb_old,FREE_WRITE);
+ dev_kfree_skb(skb_old,0 /* FREE_READ */ );
if(pkt_len < 0) {
- dev_kfree_skb(skb,FREE_WRITE);
+ skb->free = 1;
+ dev_kfree_skb(skb, 0 /* FREE_READ */ );
lp->stats.rx_dropped++;
return;
}
@@ -884,13 +900,15 @@
#else
printk(KERN_INFO "isdn: Ooopsa .. VJ-Compression support not compiled into isdn driver.\n");
lp->stats.rx_dropped++;
- dev_kfree_skb(skb,FREE_WRITE);
+ skb->free = 1;
+ dev_kfree_skb(skb,0 /* FREE_READ */ );
return;
#endif
break;
default:
isdn_ppp_fill_rq(skb->data, skb->len,proto, lp->ppp_minor); /* push data to pppd device */
- dev_kfree_skb(skb,FREE_WRITE);
+ skb->free = 1;
+ dev_kfree_skb(skb,0 /* FREE_READ */ );
return;
}
@@ -905,6 +923,9 @@
/*
* send ppp frame .. we expect a PIDCOMPressable proto --
* (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
+ *
+ * VJ compression may change skb pointer!!! .. requeue with old
+ * skb isn't allowed!!
*/
int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
@@ -957,8 +978,7 @@
#ifdef CONFIG_ISDN_PPP_VJ
if (ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes .. but check again */
- u_char *buf = skb->data;
- int pktlen;
+ struct sk_buff *new_skb;
int len = 4;
#ifdef CONFIG_ISDN_MPP
if (ipt->mpppcfg & SC_MP_PROT) /* sigh */ /* ipt or ipts ?? */
@@ -967,20 +987,41 @@
else
len += 5;
#endif
- buf += len;
- pktlen = slhc_compress(ipts->slcomp, buf, skb->len-len, ipts->cbuf,
- &buf, !(ipts->pppcfg & SC_NO_TCP_CCID));
- skb_trim(skb,pktlen+len);
- if(buf != skb->data+len) { /* copied to new buffer ??? (btw: WHY must slhc copy it?? *sigh*) */
- memcpy(skb->data+len,buf,pktlen);
- }
- if (skb->data[len] & SL_TYPE_COMPRESSED_TCP) { /* cslip? style -> PPP */
- proto = PPP_VJC_COMP;
- skb->data[len] ^= SL_TYPE_COMPRESSED_TCP;
- } else {
- if (skb->data[len] >= SL_TYPE_UNCOMPRESSED_TCP)
- proto = PPP_VJC_UNCOMP;
- skb->data[len] = (skb->data[len] & 0x0f) | 0x40;
+ new_skb = dev_alloc_skb(skb->len);
+ if(new_skb) {
+ u_char *buf;
+ int pktlen;
+
+ new_skb->dev = skb->dev;
+ new_skb->free = 1;
+ skb_put(new_skb,skb->len);
+ skb_pull(skb,len); /* pull PPP header */
+ skb_pull(new_skb,len); /* pull PPP header */
+ 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(new_skb->data != buf)
+ printk(KERN_ERR "isdn_ppp: FATAL error after slhc_compress!!\n");
+ dev_kfree_skb(skb,FREE_WRITE);
+ skb = new_skb;
+ }
+ else {
+ dev_kfree_skb(new_skb,0 /* FREE_WRITE */ );
+ }
+
+ skb_trim(skb,pktlen);
+ 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;
+ }
+ skb_push(skb,len);
}
}
#endif
@@ -1019,7 +1060,7 @@
/* tx-stats are now updated via BSENT-callback */
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);
+ printk(KERN_ERR "%s: whoops .. there is another stored skb!\n",dev->name);
dev_kfree_skb(skb,FREE_WRITE);
}
else
@@ -1035,8 +1076,10 @@
p->ib.sq = NULL;
while(q) {
struct sqqueue *qn = q->next;
- if(q->skb)
- dev_kfree_skb(q->skb,FREE_WRITE);
+ if(q->skb) {
+ q->skb->free = 1;
+ dev_kfree_skb(q->skb,0 /* FREE_READ */ );
+ }
kfree(q);
q = qn;
}
@@ -1048,7 +1091,8 @@
struct mpqueue *ql, *q = p->mp_last;
while (q) {
ql = q->next;
- dev_kfree_skb(q->skb,FREE_WRITE);
+ q->skb->free = 1;
+ dev_kfree_skb(q->skb,0 /* FREE_READ */ );
kfree(q);
q = ql;
}
@@ -1217,7 +1261,8 @@
if (!(*skb)) {
while (q) {
struct mpqueue *ql = q->next;
- dev_kfree_skb(q->skb,FREE_WRITE);
+ q->skb->free = 1;
+ dev_kfree_skb(q->skb,0 /* FREE_READ */ );
kfree(q);
q = ql;
}
@@ -1229,7 +1274,8 @@
struct mpqueue *ql = q->next;
memcpy((*skb)->data + cnt, q->skb->data, q->skb->len);
cnt += q->skb->len;
- dev_kfree_skb(q->skb,FREE_WRITE);
+ q->skb->free = 1;
+ dev_kfree_skb(q->skb,0 /* FREE_READ */ );
kfree(q);
q = ql;
}
@@ -1262,7 +1308,8 @@
q->next->last = NULL;
while (q) {
ql = q->last;
- dev_kfree_skb(q->skb,FREE_WRITE);
+ q->skb->free = 1;
+ dev_kfree_skb(q->skb,0 /* FREE_READ */ );
kfree(q);
#ifdef CONFIG_ISDN_PPP_VJ
toss = 1;
@@ -1380,7 +1427,7 @@
int len;
isdn_net_local *lp = (isdn_net_local *) dev->priv;
-#if 1
+#if 0
printk(KERN_DEBUG "ippp, dev_ioctl: cmd %#08x , %d \n",cmd,lp->ppp_minor);
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov