patch-2.4.20 linux-2.4.20/drivers/isdn/isdn_ppp.c

Next file: linux-2.4.20/drivers/isdn/pcbit/drv.c
Previous file: linux-2.4.20/drivers/isdn/isdn_net.h
Back to the patch index
Back to the overall index

diff -urN linux-2.4.19/drivers/isdn/isdn_ppp.c linux-2.4.20/drivers/isdn/isdn_ppp.c
@@ -107,8 +107,11 @@
 	unsigned long flags;
 	struct ippp_struct *is;
 
-	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS)
+	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR __FUNCTION__": ppp_slot(%d) out of range\n",
+			lp->ppp_slot);
 		return 0;
+	}
 
 	save_flags(flags);
 	cli();
@@ -124,7 +127,12 @@
 	lp->netdev->pb->ref_ct--;
 	spin_unlock(&lp->netdev->pb->lock);
 #endif /* CONFIG_ISDN_MPP */
-
+	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR __FUNCTION__": ppp_slot(%d) now invalid\n",
+			lp->ppp_slot);
+		restore_flags(flags);
+		return 0;
+	}
 	is = ippp_table[lp->ppp_slot];
 	if ((is->state & IPPP_CONNECT))
 		isdn_ppp_closewait(lp->ppp_slot);	/* force wakeup on ippp device */
@@ -220,12 +228,13 @@
 void
 isdn_ppp_wakeup_daemon(isdn_net_local * lp)
 {
-	if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS)
+	if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR __FUNCTION__": ppp_slot(%d) out of range\n",
+			lp->ppp_slot);
 		return;
-
+	}
 	ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
-
-		wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
+	wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
 }
 
 /*
@@ -238,13 +247,14 @@
 {
 	struct ippp_struct *is;
 
-	if (slot < 0 || slot >= ISDN_MAX_CHANNELS)
+	if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR __FUNCTION__": slot(%d) out of range\n",
+			slot);
 		return 0;
+	}
 	is = ippp_table[slot];
-
 	if (is->state)
 		wake_up_interruptible(&is->wq);
-
 	is->state = IPPP_CLOSEWAIT;
 	return 1;
 }
@@ -282,8 +292,9 @@
 		return -EBUSY;
 	}
 	is = file->private_data = ippp_table[slot];
-
-		printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, min, is->state);
+	
+	printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n",
+	       slot, min, is->state);
 
 	/* compression stuff */
 	is->link_compressor   = is->compressor = NULL;
@@ -332,12 +343,20 @@
 		return;
 	is = file->private_data;
 
+	if (!is) {
+		printk(KERN_ERR __FUNCTION__": no file->private_data\n");
+		return;
+	}
 	if (is->debug & 0x1)
 		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 = is->lp->netdev;
 
+		if (!p) {
+			printk(KERN_ERR __FUNCTION__": no lp->netdev\n");
+			return;
+		}
 		is->state &= ~IPPP_CONNECT;	/* -> effect: no call of wakeup */
 		/*
 		 * isdn_net_hangup() calls isdn_ppp_free()
@@ -474,7 +493,9 @@
 			if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
 				if (lp) {
 					/* OK .. we are ready to send buffers */
+					is->pppcfg = val; /* isdn_ppp_xmit test for SC_ENABLE_IP !!! */
 					netif_wake_queue(&lp->netdev->dev);
+					break;
 				}
 			}
 			is->pppcfg = val;
@@ -629,7 +650,7 @@
 	struct ippp_struct *is;
 
 	if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
-		printk(KERN_WARNING "ippp: illegal slot.\n");
+		printk(KERN_WARNING "ippp: illegal slot(%d).\n", slot);
 		return 0;
 	}
 	is = ippp_table[slot];
@@ -906,7 +927,8 @@
 
 	slot = lp->ppp_slot;
 	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot %d\n", lp->ppp_slot);
+		printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot(%d)\n",
+			lp->ppp_slot);
 		kfree_skb(skb);
 		return;
 	}
@@ -959,7 +981,8 @@
 
 	slot = lp->ppp_slot;
 	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot %d\n", lp->ppp_slot);
+		printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot(%d)\n",
+			lp->ppp_slot);
 		goto drop_packet;
 	}
 	is = ippp_table[slot];
@@ -967,7 +990,8 @@
  	if (lp->master) { // FIXME?
  		slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
  		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
- 			printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot %d\n", lp->ppp_slot);
+ 			printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
+ 				lp->ppp_slot);
 			goto drop_packet;
  		}
  	}
@@ -1001,6 +1025,11 @@
 		case PPP_VJC_UNCOMP:
 			if (is->debug & 0x20)
 				printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
+			if (net_dev->local->ppp_slot < 0) {
+				printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n",
+					net_dev->local->ppp_slot);
+				goto drop_packet;
+			}
 			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");
 				goto drop_packet;
@@ -1022,6 +1051,11 @@
 				}
 				skb_put(skb, skb_old->len + 128);
 				memcpy(skb->data, skb_old->data, skb_old->len);
+				if (net_dev->local->ppp_slot < 0) {
+					printk(KERN_ERR __FUNCTION__": net_dev->local->ppp_slot(%d) out of range\n",
+						net_dev->local->ppp_slot);
+					goto drop_packet;
+				}
 				pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp,
 						skb->data, skb_old->len);
 				kfree_skb(skb_old);
@@ -1103,23 +1137,25 @@
 	isdn_net_dev *nd;
 	unsigned int proto = PPP_IP;     /* 0x21 */
 	struct ippp_struct *ipt,*ipts;
-	int slot;
+	int slot, retval = 0;
 
 	mlp = (isdn_net_local *) (netdev->priv);
 	nd = mlp->netdev;       /* get master lp */
 
 	slot = mlp->ppp_slot;
 	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot %d\n", mlp->ppp_slot);
+		printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
+			mlp->ppp_slot);
 		kfree_skb(skb);
-		return 0;
+		goto out;
 	}
 	ipts = ippp_table[slot];
 
 	if (!(ipts->pppcfg & SC_ENABLE_IP)) {	/* PPP connected ? */
 		if (ipts->debug & 0x1)
 			printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name);
-		return 1;
+		retval = 1;
+		goto out;
 	}
 
 	switch (ntohs(skb->protocol)) {
@@ -1133,21 +1169,23 @@
 			printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n", 
 			       skb->protocol);
 			dev_kfree_skb(skb);
-			return 0;
+			goto out;
 	}
 
 	lp = isdn_net_get_locked_lp(nd);
 	if (!lp) {
 		printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name);
-		return 1;
+		retval = 1;
+		goto unlock;
 	}
 	/* we have our lp locked from now on */
 
 	slot = lp->ppp_slot;
 	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot %d\n", lp->ppp_slot);
+		printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
+			lp->ppp_slot);
 		kfree_skb(skb);
-		return 0;
+		goto unlock;
 	}
 	ipt = ippp_table[slot];
 	lp->huptimer = 0;
@@ -1298,7 +1336,8 @@
 
  unlock:
 	spin_unlock_bh(&lp->xmit_lock);
-	return 0;
+ out:
+	return retval;
 }
 
 #ifdef CONFIG_ISDN_MPP
@@ -1350,8 +1389,15 @@
 
 static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
 {
-	struct ippp_struct * is = ippp_table[lp->ppp_slot];
-   
+	struct ippp_struct * is;
+
+	if (lp->ppp_slot < 0) {
+		printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n",
+			lp->ppp_slot);
+		return(-EINVAL);
+	}
+
+	is = ippp_table[lp->ppp_slot];
 	if (add_to) {
 		if( lp->netdev->pb )
 			lp->netdev->pb->ref_ct--;
@@ -1397,7 +1443,8 @@
         stats = &mp->stats;
 	slot = lp->ppp_slot;
 	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-		printk(KERN_ERR "isdn_ppp_mp_receive: lp->ppp_slot %d\n", lp->ppp_slot);
+		printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d)\n",
+			lp->ppp_slot);
 		stats->frame_drops++;
 		dev_kfree_skb(skb);
 		spin_unlock_irqrestore(&mp->lock, flags);
@@ -1433,7 +1480,8 @@
 	for (lpq = net_dev->queue;;) {
 		slot = lpq->ppp_slot;
 		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
-			printk(KERN_ERR "isdn_ppp_mp_receive: lpq->ppp_slot %d\n", lpq->ppp_slot);
+			printk(KERN_ERR __FUNCTION__": lpq->ppp_slot(%d)\n",
+				lpq->ppp_slot);
 		} else {
 			u32 lls = ippp_table[slot]->last_link_seqno;
 			if (MP_LT(lls, minseq))
@@ -1665,9 +1713,14 @@
 	struct sk_buff * skb;
 	unsigned int tot_len;
 
+	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n",
+			lp->ppp_slot);
+		return;
+	}
 	if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
 		if( ippp_table[lp->ppp_slot]->debug & 0x40 )
-			printk(KERN_DEBUG"isdn_mppp: reassembly: frame %d, "
+			printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, "
 					"len %d\n", MP_SEQ(from), from->len );
 		skb = from;
 		skb_pull(skb, MP_HEADER_LEN);
@@ -2230,7 +2283,7 @@
 				return;
 			}
 			rs->state = CCPResetSentReq;
-			/* We always expect an Ack if the decompressor doesnt
+			/* We always expect an Ack if the decompressor doesn't
 			   know	better */
 			rs->expra = 1;
 			rs->dlen = 0;
@@ -2429,18 +2482,31 @@
 static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
 	 struct sk_buff *skb,int proto)
 {
-	struct ippp_struct *is = ippp_table[lp->ppp_slot];
+	struct ippp_struct *is;
 	struct ippp_struct *mis;
 	int len;
 	struct isdn_ppp_resetparams rsparm;
 	unsigned char rsdata[IPPP_RESET_MAXDATABYTES];	
 
-	printk(KERN_DEBUG "Received CCP frame from peer\n");
+	printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
+		lp->ppp_slot);
+	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n",
+			lp->ppp_slot);
+		return;
+	}
+	is = ippp_table[lp->ppp_slot];
 	isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
 
-	if(lp->master)
-		mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
-	else
+	if(lp->master) {
+		int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
+		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+			printk(KERN_ERR __FUNCTION__": slot(%d) out of range\n",
+				slot);
+			return;
+		}	
+		mis = ippp_table[slot];
+	} else
 		mis = is;
 
 	switch(skb->data[0]) {
@@ -2592,13 +2658,18 @@
 
 static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
 {
-	struct ippp_struct *mis,*is = ippp_table[lp->ppp_slot];
-	int proto;
+	struct ippp_struct *mis,*is;
+	int proto, slot = lp->ppp_slot;
 	unsigned char *data;
 
 	if(!skb || skb->len < 3)
 		return;
-
+	if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+		printk(KERN_ERR __FUNCTION__": lp->ppp_slot(%d) out of range\n",
+			slot);
+		return;
+	}	
+	is = ippp_table[slot];
 	/* Daemon may send with or without address and control field comp */
 	data = skb->data;
 	if(!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) {
@@ -2614,12 +2685,17 @@
 	printk(KERN_DEBUG "Received CCP frame from daemon:\n");
 	isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
 
-        if(lp->master)
-                mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
-        else
-                mis = is;
-	
-	if(mis != is)
+	if (lp->master) {
+		slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
+		if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+			printk(KERN_ERR __FUNCTION__": slot(%d) out of range\n",
+				slot);
+			return;
+		}	
+		mis = ippp_table[slot];
+	} else
+		mis = is;
+	if (mis != is)
 		printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
 	
         switch(data[2]) {

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)