⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isdn_ppp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		kfree_skb(skb);		return;	}	is = ippp_table[slot];	if (is->debug & 0x4) {		printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n",		       (long)is,(long)lp,lp->ppp_slot,is->unit,(int) skb->len);		isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot);	} 	if (isdn_ppp_skip_ac(is, skb) < 0) { 		kfree_skb(skb); 		return; 	}  	proto = isdn_ppp_strip_proto(skb); 	if (proto < 0) { 		kfree_skb(skb); 		return; 	}  #ifdef CONFIG_ISDN_MPP 	if (is->compflags & SC_LINK_DECOMP_ON) { 		skb = isdn_ppp_decompress(skb, is, NULL, &proto); 		if (!skb) // decompression error 			return; 	}	 	if (!(is->mpppcfg & SC_REJ_MP_PROT)) { // we agreed to receive MPPP  		if (proto == PPP_MP) {  			isdn_ppp_mp_receive(net_dev, lp, skb); 			return; 		} 	} #endif 	isdn_ppp_push_higher(net_dev, lp, skb, proto);}/* * we receive a reassembled frame, MPPP has been taken care of before. * address/control and protocol have been stripped from the skb * note: net_dev has to be master net_dev */static voidisdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb, int proto){	struct net_device *dev = &net_dev->dev; 	struct ippp_struct *is, *mis;	isdn_net_local *mlp = NULL;	int slot;	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);		goto drop_packet;	}	is = ippp_table[slot]; 	 	if (lp->master) { // FIXME?		mlp = (isdn_net_local *) lp->master->priv; 		slot = mlp->ppp_slot; 		if (slot < 0 || slot > ISDN_MAX_CHANNELS) { 			printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n", 				lp->ppp_slot);			goto drop_packet; 		} 	} 	mis = ippp_table[slot];	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,is->unit,lp->ppp_slot);	}	if (mis->compflags & SC_DECOMP_ON) {		skb = isdn_ppp_decompress(skb, is, mis, &proto);		if (!skb) // decompression error  			return;  	}	switch (proto) {		case PPP_IPX:  /* untested */			if (is->debug & 0x20)				printk(KERN_DEBUG "isdn_ppp: IPX\n");			skb->protocol = htons(ETH_P_IPX);			break;		case PPP_IP:			if (is->debug & 0x20)				printk(KERN_DEBUG "isdn_ppp: IP\n");			skb->protocol = htons(ETH_P_IP);			break;		case PPP_COMP:		case PPP_COMPFRAG:			printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n");			goto drop_packet;#ifdef CONFIG_ISDN_PPP_VJ		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 "%s: net_dev->local->ppp_slot(%d) out of range\n",					__FUNCTION__, 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;			}			skb->protocol = htons(ETH_P_IP);			break;		case PPP_VJC_COMP:			if (is->debug & 0x20)				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) {					printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);					skb = skb_old;					goto drop_packet;				}				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 "%s: net_dev->local->ppp_slot(%d) out of range\n",						__FUNCTION__, 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);				if (pkt_len < 0)					goto drop_packet;				skb_trim(skb, pkt_len);				skb->protocol = htons(ETH_P_IP);			}			break;#endif		case PPP_CCP:		case PPP_CCPFRAG:			isdn_ppp_receive_ccp(net_dev,lp,skb,proto);			/* Dont pop up ResetReq/Ack stuff to the daemon any			   longer - the job is done already */			if(skb->data[0] == CCP_RESETREQ ||			   skb->data[0] == CCP_RESETACK)				break;			/* fall through */		default:			isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot);	/* push data to pppd device */			kfree_skb(skb);			return;	}#ifdef CONFIG_IPPP_FILTER	/* check if the packet passes the pass and active filters	 * the filter instructions are constructed assuming	 * a four-byte PPP header on each packet (which is still present) */	skb_push(skb, 4);	{		u_int16_t *p = (u_int16_t *) skb->data;		*p = 0;	/* indicate inbound */	}	if (is->pass_filter	    && sk_run_filter(skb, is->pass_filter, is->pass_len) == 0) {		if (is->debug & 0x2)			printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");		kfree_skb(skb);		return;	}	if (!(is->active_filter	      && sk_run_filter(skb, is->active_filter,	                       is->active_len) == 0)) {		if (is->debug & 0x2)			printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");		lp->huptimer = 0;		if (mlp)			mlp->huptimer = 0;	}	skb_pull(skb, 4);#else /* CONFIG_IPPP_FILTER */	lp->huptimer = 0;	if (mlp)		mlp->huptimer = 0;#endif /* CONFIG_IPPP_FILTER */	skb->dev = dev;	skb->mac.raw = skb->data;	netif_rx(skb);	/* net_dev->local->stats.rx_packets++; done in isdn_net.c */	return; drop_packet:	net_dev->local->stats.rx_dropped++;	kfree_skb(skb);}/* * 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) {		struct sk_buff *nskb = skb_realloc_headroom(skb, len);		if (!nskb) {			printk(KERN_ERR "isdn_ppp_skb_push: can't realloc headroom!\n");			dev_kfree_skb(skb);			return NULL;		}		printk(KERN_DEBUG "isdn_ppp_skb_push:under %d %d\n",skb_headroom(skb),len);		dev_kfree_skb(skb);		*skb_p = nskb;		return skb_push(nskb, len);	}	return skb_push(skb,len);}/* * 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!! */intisdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev){	isdn_net_local *lp,*mlp;	isdn_net_dev *nd;	unsigned int proto = PPP_IP;     /* 0x21 */	struct ippp_struct *ipt,*ipts;	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);		kfree_skb(skb);		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);		retval = 1;		goto out;	}	switch (ntohs(skb->protocol)) {		case ETH_P_IP:			proto = PPP_IP;			break;		case ETH_P_IPX:			proto = PPP_IPX;	/* untested */			break;		default:			printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n", 			       skb->protocol);			dev_kfree_skb(skb);			goto out;	}	lp = isdn_net_get_locked_lp(nd);	if (!lp) {		printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name);		retval = 1;		goto out;	}	/* 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);		kfree_skb(skb);		goto unlock;	}	ipt = ippp_table[slot];	/*	 * after this line .. requeueing in the device queue is no longer allowed!!!	 */	/* Pull off the fake header we stuck on earlier to keep	 * the fragmentation code happy.	 */	skb_pull(skb,IPPP_MAX_HEADER);#ifdef CONFIG_IPPP_FILTER	/* check if we should pass this packet	 * the filter instructions are constructed assuming	 * a four-byte PPP header on each packet */	*skb_push(skb, 4) = 1; /* indicate outbound */	{		u_int16_t *p = (u_int16_t *) skb->data;		p++;		*p   = htons(proto);	}	if (ipt->pass_filter	    && sk_run_filter(skb, ipt->pass_filter, ipt->pass_len) == 0) {		if (ipt->debug & 0x4)			printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");		kfree_skb(skb);		goto unlock;	}	if (!(ipt->active_filter	      && sk_run_filter(skb, ipt->active_filter,		               ipt->active_len) == 0)) {		if (ipt->debug & 0x4)			printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");		lp->huptimer = 0;	}	skb_pull(skb, 4);#else /* CONFIG_IPPP_FILTER */	lp->huptimer = 0;#endif /* CONFIG_IPPP_FILTER */	if (ipt->debug & 0x4)		printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);        if (ipts->debug & 0x40)                isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32,ipts->unit,lp->ppp_slot);#ifdef CONFIG_ISDN_PPP_VJ	if (proto == PPP_IP && ipts->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		 * sk_buff. old call to dev_alloc_skb only reserved		 * 16 bytes, now we are looking what the driver want.		 */		hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + 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(ipts->slcomp, skb->data, skb->len, new_skb->data,				 &buf, !(ipts->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);			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	 */	if(ipts->compflags & SC_COMP_ON) {		/* We send compressed only if both down- und upstream		   compression is negotiated, that means, CCP is up */		if(ipts->compflags & SC_DECOMP_ON) {			skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);		} else {			printk(KERN_DEBUG "isdn_ppp: CCP not yet up - sending as-is\n");		}	}	if (ipt->debug & 0x24)		printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);#ifdef CONFIG_ISDN_MPP	if (ipt->mpppcfg & SC_MP_PROT) {		/* we get mp_seqno from static isdn_net_local */		long mp_seqno = ipts->mp_seqno;		ipts->mp_seqno++;		if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) {			unsigned char *data = isdn_ppp_skb_push(&skb, 3);			if(!data)				goto unlock;			mp_seqno &= 0xfff;			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 = isdn_ppp_skb_push(&skb, 5);			if(!data)				goto unlock;			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;			data[3] = (mp_seqno >> 0) & 0xff;			data[4] = proto;	/* PID compression */		}		proto = PPP_MP; /* MP Protocol, 0x003d */	}#endif	/*	 * 'link in bundle' compression  ...	 */	if(ipt->compflags & SC_LINK_COMP_ON)		skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);	if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) {		unsigned char *data = isdn_ppp_skb_push(&skb,1);		if(!data)			goto unlock;		data[0] = proto & 0xff;	}	else {		unsigned char *data = isdn_ppp_skb_push(&skb,2);		if(!data)			goto unlock;		data[0] = (proto >> 8) & 0xff;		data[1] = proto & 0xff;	}	if(!(ipt->pppcfg & SC_COMP_AC)) {		unsigned char *data = isdn_ppp_skb_push(&skb,2);		if(!data)			goto unlock;		data[0] = 0xff;    /* All Stations */		data[1] = 0x03;    /* Unnumbered information */	}	/* tx-stats are now updated via BSENT-callback */	if (ipts->debug & 0x40) {		printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);		isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,lp->ppp_slot);	}		isdn_net_writebuf_skb(lp, skb); unlock:	spin_unlock_bh(&lp->xmit_lock); out:	return retval;}#ifdef CONFIG_IPPP_FILTER/* * check if this packet may trigger auto-dial. */int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp){	struct ippp_struct *is = ippp_table[lp->ppp_slot];	u_int16_t proto;	int drop = 0;	switch (ntohs(skb->protocol)) {	case ETH_P_IP:		proto = PPP_IP;		break;	case ETH_P_IPX:		proto = PPP_IPX;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -