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

📄 ppp.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
		       rcvd, CCP_CODE(dp), ppp->flags);	save_flags(flags);	switch (CCP_CODE(dp)) {	case CCP_CONFREQ:	case CCP_TERMREQ:	case CCP_TERMACK:		/*		 * CCP must be going down - disable compression		 */		if (ppp->flags & SC_CCP_UP) {			cli();			ppp->flags &= ~(SC_CCP_UP   |					SC_COMP_RUN |					SC_DECOMP_RUN);		}		break;	case CCP_CONFACK:		if ((ppp->flags & SC_CCP_OPEN) == 0)			break;		if (ppp->flags & SC_CCP_UP)			break;		if (slen < (CCP_HDRLEN + CCP_OPT_MINLEN))			break;		if (slen < (CCP_OPT_LENGTH (opt) + CCP_HDRLEN))			break;		if (!rcvd) {			/*			 * we're agreeing to send compressed packets.			 */			if (ppp->sc_xc_state == NULL)				break;			if ((*ppp->sc_xcomp->comp_init)			    (ppp->sc_xc_state,			     opt, opt_len,			     ppp->line, 0, ppp->flags & SC_DEBUG)) {				if (ppp->flags & SC_DEBUG)					printk(KERN_DEBUG "%s: comp running\n",					       ppp->name);				cli();				ppp->flags |= SC_COMP_RUN;			}			break;		}		/*		 * peer is agreeing to send compressed packets.		 */		if (ppp->sc_rc_state == NULL)			break;		if ((*ppp->sc_rcomp->decomp_init)		    (ppp->sc_rc_state,		     opt, opt_len,		     ppp->line, 0, ppp->mru, ppp->flags & SC_DEBUG)) {			if (ppp->flags & SC_DEBUG)				printk(KERN_DEBUG "%s: decomp running\n",				       ppp->name);			cli();			ppp->flags |= SC_DECOMP_RUN;			ppp->flags &= ~(SC_DC_ERROR | SC_DC_FERROR);		}		break;	case CCP_RESETACK:		/*		 * CCP Reset-ack resets compressors and decompressors		 * as it passes through.		 */		if ((ppp->flags & SC_CCP_UP) == 0)			break;		if (!rcvd) {			if (ppp->sc_xc_state && (ppp->flags & SC_COMP_RUN)) {				(*ppp->sc_xcomp->comp_reset)(ppp->sc_xc_state);				if (ppp->flags & SC_DEBUG)					printk(KERN_DEBUG "%s: comp reset\n",					       ppp->name);			}		} else {			if (ppp->sc_rc_state && (ppp->flags & SC_DECOMP_RUN)) {			      (*ppp->sc_rcomp->decomp_reset)(ppp->sc_rc_state);			      if (ppp->flags & SC_DEBUG)					printk(KERN_DEBUG "%s: decomp reset\n",					       ppp->name);			      cli();			      ppp->flags &= ~SC_DC_ERROR;			}		}		break;	}	restore_flags(flags);}/* * CCP is down; free (de)compressor state if necessary. */static voidppp_ccp_closed(struct ppp *ppp){	unsigned long flags;	save_flags(flags);	cli();	ppp->flags &= ~(SC_CCP_OPEN | SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN);	restore_flags(flags);	if (ppp->flags & SC_DEBUG)		printk(KERN_DEBUG "%s: ccp closed\n", ppp->name);	if (ppp->sc_xc_state) {		(*ppp->sc_xcomp->comp_free) (ppp->sc_xc_state);		ppp->sc_xc_state = NULL;	}	if (ppp->sc_rc_state) {		(*ppp->sc_rcomp->decomp_free) (ppp->sc_rc_state);		ppp->sc_rc_state = NULL;	}}/************************************************************* * RECEIVE-SIDE ROUTINES *************************************************************//* * On entry, a received frame is in skb. * Check it and dispose as appropriate. */static intppp_receive_frame(struct ppp *ppp, struct sk_buff *skb){	__u8	*data;	int	count;	int	proto;	int	new_count;	struct sk_buff *new_skb;	ppp_proto_type	*proto_ptr;	/*	 * An empty frame is ignored. This occurs if the FLAG sequence	 * precedes and follows each frame.	 */	if (skb == NULL)		return 1;	if (skb->len == 0) {		kfree_skb(skb);		return 1;	}	data = skb->data;	count = skb->len;	/*	 * Generate an error if the frame is too small.	 */	if (count < PPP_HDRLEN + 2) {		if (ppp->flags & SC_DEBUG)			printk(KERN_DEBUG			       "ppp: got runt ppp frame, %d chars\n", count);		++ppp->estats.rx_length_errors;		return 0;	}	/*	 * Verify the FCS of the frame and discard the FCS characters	 * from the end of the buffer.	 */	if (ppp->rfcs != PPP_GOODFCS) {		if (ppp->flags & SC_DEBUG) {			printk(KERN_DEBUG			       "ppp: frame with bad fcs, length = %d\n",			       count);			ppp_print_buffer("bad frame", data, count);		}		++ppp->estats.rx_crc_errors;		return 0;	}	count -= 2;		/* ignore the fcs characters */	skb_trim(skb, count);	/*	 * Process the active decompressor.	 */	if (ppp->sc_rc_state != NULL &&	    (ppp->flags & SC_DECOMP_RUN) &&	    ((ppp->flags & (SC_DC_FERROR | SC_DC_ERROR)) == 0)) {		if (PPP_PROTOCOL(data) == PPP_COMP) {			/*			 * If the frame is compressed then decompress it.			 */			new_skb = dev_alloc_skb(ppp->mru + 128 + PPP_HDRLEN);			if (new_skb == NULL) {				printk(KERN_ERR "ppp_recv_frame: no memory\n");				new_count = DECOMP_ERROR;			} else {				new_count = (*ppp->sc_rcomp->decompress)					(ppp->sc_rc_state, data, count,					 new_skb->data, ppp->mru + PPP_HDRLEN);			}			if (new_count > 0) {				/* Frame was decompressed OK */				kfree_skb(skb);				skb = new_skb;				count = new_count;				data = skb_put(skb, count);			} else {				/*				 * On a decompression error, we pass the				 * compressed frame up to pppd as an				 * error indication.				 */				if (ppp->flags & SC_DEBUG)					printk(KERN_INFO "%s: decomp err %d\n",					       ppp->name, new_count);				if (new_skb != 0)					kfree_skb(new_skb);				if (ppp->slcomp != 0)					slhc_toss(ppp->slcomp);				++ppp->stats.ppp_ierrors;				if (new_count == DECOMP_FATALERROR) {					ppp->flags |= SC_DC_FERROR;				} else {					ppp->flags |= SC_DC_ERROR;				}			}		} else {			/*			 * The frame is not compressed. Pass it to the			 * decompression code so it can update its			 * dictionary if necessary.			 */			(*ppp->sc_rcomp->incomp)(ppp->sc_rc_state,						 data, count);		}	}	else if (PPP_PROTOCOL(data) == PPP_COMP && (ppp->flags & SC_DEBUG))		printk(KERN_INFO "%s: not decomp, rc_state=%p flags=%x\n",		       ppp->name, ppp->sc_rc_state, ppp->flags);	/*	 * Count the frame and print it	 */	++ppp->stats.ppp_ipackets;	ppp->stats.ppp_ioctects += count;	if (ppp->flags & SC_LOG_INPKT)		ppp_print_buffer ("receive frame", data, count);	/*	 * Find the procedure to handle this protocol.	 * The last one is marked as protocol 0 which is the 'catch-all'	 * to feed it to the pppd daemon.	 */	proto = PPP_PROTOCOL(data);	proto_ptr = proto_list;	while (proto_ptr->proto != 0 && proto_ptr->proto != proto)		++proto_ptr;	/*	 * Update the appropriate statistic counter.	 */	if (!(*proto_ptr->func)(ppp, skb)) {		kfree_skb(skb);		++ppp->stats.ppp_discards;	}	return 1;}/* * An input error has been detected, so we need to inform * the VJ decompressor. */static voidppp_receive_error(struct ppp *ppp){	CHECK_PPP_VOID();	if (ppp->slcomp != 0)		slhc_toss(ppp->slcomp);}/* * Put the input frame into the networking system for the indicated protocol */static intppp_rcv_rx(struct ppp *ppp, __u16 proto, struct sk_buff *skb){	/*	 * Fill in a few fields of the skb and give it to netif_rx().	 */	skb->dev      = ppp2dev(ppp);	/* We are the device */	skb->protocol = htons(proto);	skb_pull(skb, PPP_HDRLEN);	/* pull off ppp header */	skb->mac.raw   = skb->data;	ppp->last_recv = jiffies;	netif_rx (skb);	return 1;}/* * Process the receipt of an IP frame */static intrcv_proto_ip(struct ppp *ppp, struct sk_buff *skb){	CHECK_PPP(0);	if ((ppp2dev(ppp)->flags & IFF_UP) && (skb->len > 0)	    && ppp->sc_npmode[NP_IP] == NPMODE_PASS)		return ppp_rcv_rx(ppp, ETH_P_IP, skb);	return 0;}/* * Process the receipt of an IPv6 frame */static intrcv_proto_ipv6(struct ppp *ppp, struct sk_buff *skb){	CHECK_PPP(0);	if ((ppp2dev(ppp)->flags & IFF_UP) && (skb->len > 0)	    && ppp->sc_npmode[NP_IPV6] == NPMODE_PASS)		return ppp_rcv_rx(ppp, ETH_P_IPV6, skb);	return 0;}/* * Process the receipt of an IPX frame */static intrcv_proto_ipx(struct ppp *ppp, struct sk_buff *skb){	CHECK_PPP(0);	if (((ppp2dev(ppp)->flags & IFF_UP) != 0) && (skb->len > 0)	    && ppp->sc_npmode[NP_IPX] == NPMODE_PASS)		return ppp_rcv_rx(ppp, ETH_P_IPX, skb);	return 0;}/* * Process the receipt of an Appletalk frame */static intrcv_proto_at(struct ppp *ppp, struct sk_buff *skb){	CHECK_PPP(0);	if ((ppp2dev(ppp)->flags & IFF_UP) && (skb->len > 0)	    && ppp->sc_npmode[NP_AT] == NPMODE_PASS)		return ppp_rcv_rx(ppp, ETH_P_PPPTALK, skb);	return 0;}/* * Process the receipt of an VJ Compressed frame */static intrcv_proto_vjc_comp(struct ppp *ppp, struct sk_buff *skb){	int new_count;	CHECK_PPP(0);	if ((ppp->flags & SC_REJ_COMP_TCP) || ppp->slcomp == NULL)		return 0;	new_count = slhc_uncompress(ppp->slcomp, skb->data + PPP_HDRLEN,				    skb->len - PPP_HDRLEN);	if (new_count<=0) {		if (ppp->flags & SC_DEBUG)			printk(KERN_NOTICE			       "ppp: error in VJ decompression\n");		return 0;	}	new_count += PPP_HDRLEN;	if (new_count > skb->len)		skb_put(skb, new_count - skb->len);	else		skb_trim(skb, new_count);	return rcv_proto_ip(ppp, skb);}/* * Process the receipt of an VJ Un-compressed frame */static intrcv_proto_vjc_uncomp(struct ppp *ppp, struct sk_buff *skb){	CHECK_PPP(0);	if ((ppp->flags & SC_REJ_COMP_TCP) || ppp->slcomp == NULL)		return 0;	if (slhc_remember(ppp->slcomp, skb->data + PPP_HDRLEN,			  skb->len - PPP_HDRLEN) <= 0) {		if (ppp->flags & SC_DEBUG)			printk(KERN_NOTICE "ppp: error in VJ memorizing\n");		return 0;	}	return rcv_proto_ip(ppp, skb);}static intrcv_proto_ccp(struct ppp *ppp, struct sk_buff *skb){	CHECK_PPP(0);	ppp_proto_ccp (ppp, skb->data + PPP_HDRLEN, skb->len - PPP_HDRLEN, 1);	return rcv_proto_unknown(ppp, skb);}/* * Receive all unclassified protocols. */static intrcv_proto_unknown(struct ppp *ppp, struct sk_buff *skb){	CHECK_PPP(0);	/*	 * Limit queue length by dropping old frames.	 */	skb_queue_tail(&ppp->rcv_q, skb);	while (ppp->rcv_q.qlen > PPP_MAX_RCV_QLEN) {		struct sk_buff *skb = skb_dequeue(&ppp->rcv_q);		if (skb)			kfree_skb(skb);	}	wake_up_interruptible (&ppp->read_wait);	if (ppp->tty->fasync != NULL)		kill_fasync (ppp->tty->fasync, SIGIO);	return 1;}/************************************************************* * TRANSMIT-SIDE ROUTINES *************************************************************//* local function to store a value into the LQR frame */extern inline __u8 * store_long (register __u8 *p, register int value) {	*p++ = (__u8) (value >> 24);	*p++ = (__u8) (value >> 16);	*p++ = (__u8) (value >>	 8);	*p++ = (__u8) value;	return p;}/* * Compress and send an frame to the peer. * Should be called with xmit_busy == 1, having been set by the caller. * That is, we use xmit_busy as a lock to prevent reentry of this * procedure. */static voidppp_send_frame(struct ppp *ppp, struct sk_buff *skb){	int	proto;	__u8	*data;	int	count;	__u8	*p;	int	ret;	CHECK_PPP_VOID();	data = skb->data;	count = skb->len;	/* dump the buffer */	if (ppp->flags & SC_LOG_OUTPKT)		ppp_print_buffer ("write frame", data, count);	/*	 * Handle various types of protocol-specific compression	 * and other processing, including:	 * - VJ TCP header compression	 * - updating LQR packets	 * - updating CCP state on CCP packets	 */	proto = PPP_PROTOCOL(data);	switch (proto) {	case PPP_IP:		if ((ppp->flags & SC_COMP_TCP) && ppp->slcomp != NULL)			skb = ppp_vj_compress(ppp, skb);		break;	case PPP_LQR:		/*		 * Update the LQR frame with the current MIB information.		 * This way the information is accurate and up-to-date.		 */		if (count < 48)			break;		p = data + 40;	/* Point to last two items. */		p = store_long(p, ppp->stats.ppp_opackets + 1);		p = store_long(p, ppp->stats.ppp_ooctects + count);		++ppp->stats.ppp_olqrs;		break;	case PPP_CCP:		/*		 * Outbound compression control frames		 */		ppp_proto_ccp(ppp, data + PPP_HDRLEN, count - PPP_HDRLEN, 0);		break;	}	data = skb->data;	count = skb->len;	/*	 * Compress the whole frame if possible.	 */	if (((ppp->flags & SC_COMP_RUN) != 0)	&&	    (ppp->sc_xc_state != (void *) 0)	&&	    (proto != PPP_LCP)			&&	    (proto != PPP_CCP)) {		struct sk_buff *new_skb;		int new_count;		/* Allocate an skb for the compressed frame. */		new_skb = alloc_skb(ppp->mtu + PPP_HDRLEN, GFP_ATOMIC);		if (new_skb == NULL) {			printk(KERN_ERR "ppp_send_frame: no memory\n");			kfree_skb(skb);			ppp->xmit_busy = 0;			return;		}		/* Compress the frame. */		new_count = (*ppp->sc_xcomp->compress)			(ppp->sc_xc_state, data, new_skb->data,			 count, ppp->mtu + PPP_HDRLEN);		/* Did it compress? */		if (new_count > 0 && (ppp->flags & SC_CCP_UP)) {			skb_put(new_skb, new_count);			kfree_skb(skb);			skb = new_skb;		} else {			/*			 * The frame could not be compressed, or it could not			 * be sent in compressed form because CCP is down.			 */			kfree_skb(new_skb);		}	}	/*	 * Send the frame	 */	ret = ppp_async_send(ppp, skb);	if (ret > 0) {		/* we can release the lock */		ppp->xmit_busy = 0;	} else if (ret < 0) {		/* can't happen, since the caller got the xmit_busy lock */		printk(KERN_ERR "ppp: ppp_async_send didn't accept pkt\n");	}}/* * Apply VJ TCP header compression to a packet. */static struct sk_buff *ppp_vj_compress(struct ppp *ppp, struct sk_buff *skb){

⌨️ 快捷键说明

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