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

📄 ppp.c

📁 unix and linux net driver
💻 C
📖 第 1 页 / 共 5 页
字号:
 * If this procedure returns 0, ppp_output_wakeup will be called * exactly once. */static intppp_async_send(struct ppp *ppp, struct sk_buff *skb){	CHECK_PPP(0);	ppp_tty_push(ppp);	if (ppp->tpkt != NULL)		return -1;	ppp->tpkt = skb;	ppp->tpkt_pos = 0;	return ppp_tty_push(ppp);}/* * Push as much data as possible out to the tty. * Returns 1 if we finished encoding the current frame, 0 otherwise. */static intppp_tty_push(struct ppp *ppp){	int avail, sent, done = 0;	struct tty_struct *tty = ppp2tty(ppp);		if (ppp->flags & SC_SYNC) 		return ppp_tty_sync_push(ppp);	CHECK_PPP(0);	if (ppp->tty_pushing) {		ppp->woke_up = 1;		return 0;	}	if (tty == NULL || tty->disc_data != (void *) ppp)		goto flush;	while (ppp->optr < ppp->olim || ppp->tpkt != 0) {		ppp->tty_pushing = 1;		mb();		ppp->woke_up = 0;		avail = ppp->olim - ppp->optr;		if (avail > 0) {			tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);			sent = tty->driver.write(tty, 0, ppp->optr, avail);			if (sent < 0)				goto flush;	/* error, e.g. loss of CD */			ppp->stats.ppp_obytes += sent;			ppp->optr += sent;			if (sent < avail) {				wmb();				ppp->tty_pushing = 0;				mb();				if (ppp->woke_up)					continue;				return done;			}		}		if (ppp->tpkt != 0)			done = ppp_async_encode(ppp);		wmb();		ppp->tty_pushing = 0;	}	return done;flush:	ppp->tty_pushing = 1;	mb();	ppp->stats.ppp_oerrors++;	if (ppp->tpkt != 0) {		KFREE_SKB(ppp->tpkt);		ppp->tpkt = 0;		done = 1;	}	ppp->optr = ppp->olim;	wmb();	ppp->tty_pushing = 0;	return done;}/* * Procedure to encode the data for async serial transmission. * Does octet stuffing (escaping) and address/control * and protocol compression. * Assumes ppp->opkt != 0 on entry. * Returns 1 if we finished the current frame, 0 otherwise. */static intppp_async_encode(struct ppp *ppp){	int fcs, i, count, c;	unsigned char *buf, *buflim;	unsigned char *data;	int islcp;	CHECK_PPP(0);	buf = ppp->obuf;	ppp->olim = buf;	ppp->optr = buf;	i = ppp->tpkt_pos;	data = ppp->tpkt->data;	count = ppp->tpkt->len;	fcs = ppp->tfcs;	/*	 * LCP packets with code values between 1 (configure-reqest)	 * and 7 (code-reject) must be sent as though no options	 * had been negotiated.	 */	islcp = PPP_PROTOCOL(data) == PPP_LCP		&& 1 <= data[PPP_HDRLEN] && data[PPP_HDRLEN] <= 7;	if (i == 0) {		/*		 * Start of a new packet - insert the leading FLAG		 * character if necessary.		 */		if (islcp || flag_time == 0		    || jiffies - ppp->last_xmit >= flag_time)			*buf++ = PPP_FLAG;		/* only reset idle time for data packets */		if (PPP_PROTOCOL(data) < 0x8000)			ppp->last_xmit = jiffies;		fcs = PPP_INITFCS;		++ppp->stats.ppp_opackets;		ppp->stats.ppp_ooctects += count;		/*		 * Do address/control compression		 */		if ((ppp->flags & SC_COMP_AC) != 0 && !islcp		    && PPP_ADDRESS(data) == PPP_ALLSTATIONS		    && PPP_CONTROL(data) == PPP_UI)			i += 2;	}	/*	 * Once we put in the last byte, we need to put in the FCS	 * and closing flag, so make sure there is at least 7 bytes	 * of free space in the output buffer.	 */	buflim = buf + OBUFSIZE - 6;	while (i < count && buf < buflim) {		c = data[i++];		if (i == 3 && c == 0 && (ppp->flags & SC_COMP_PROT))			continue;	/* compress protocol field */		fcs = PPP_FCS(fcs, c);		if (in_xmap(ppp, c) || (islcp && c < 0x20)) {			*buf++ = PPP_ESCAPE;			c ^= 0x20;		}		*buf++ = c;	}	if (i == count) {		/*		 * We have finished the packet.  Add the FCS and flag.		 */		fcs = ~fcs;		c = fcs & 0xff;		if (in_xmap(ppp, c) || (islcp && c < 0x20)) {			*buf++ = PPP_ESCAPE;			c ^= 0x20;		}		*buf++ = c;		c = (fcs >> 8) & 0xff;		if (in_xmap(ppp, c) || (islcp && c < 0x20)) {			*buf++ = PPP_ESCAPE;			c ^= 0x20;		}		*buf++ = c;		*buf++ = PPP_FLAG;		ppp->olim = buf;		KFREE_SKB(ppp->tpkt);		ppp->tpkt = 0;		return 1;	}	/*	 * Remember where we are up to in this packet.	 */	ppp->olim = buf;	ppp->tpkt_pos = i;	ppp->tfcs = fcs;	return 0;}/* * Flush output from our internal buffers. * Called for the TCFLSH ioctl. */static voidppp_tty_flush_output(struct ppp *ppp){	struct sk_buff *skb;	int done = 0;	while ((skb = skb_dequeue(&ppp->xmt_q)) != NULL)		KFREE_SKB(skb);	ppp->tty_pushing = 1;	mb();	ppp->optr = ppp->olim;	if (ppp->tpkt != NULL) {		KFREE_SKB(ppp->tpkt);		ppp->tpkt = 0;		done = 1;	}	wmb();	ppp->tty_pushing = 0;	if (done)		ppp_output_wakeup(ppp);}/* * Callback function from tty driver. Return the amount of space left * in the receiver's buffer to decide if remote transmitter is to be * throttled. */static intppp_tty_room (struct tty_struct *tty){	return 65536;	    /* We can handle an infinite amount of data. :-) */}/* * Callback function when data is available at the tty driver. */static voidppp_tty_receive (struct tty_struct *tty, const __u8 * data,		 char *flags, int count){	register struct ppp *ppp = tty2ppp (tty);	struct sk_buff *skb;	int chr, flg;	unsigned char *p;	if (ppp != 0)		CHECK_PPP_VOID();	/*	 * This can happen if stuff comes in on the backup tty.	 */	if (ppp == 0 || tty != ppp->tty)		return;	/*	 * Verify the table pointer and ensure that the line is	 * still in PPP discipline.	 */	if (ppp->magic != PPP_MAGIC) {		if (ppp->flags & SC_DEBUG)			printk(KERN_DEBUG			       "PPP: tty_receive called but couldn't find "			       "PPP struct.\n");		return;	}	/*	 * Print the buffer if desired	 */	if (ppp->flags & SC_LOG_RAWIN)		ppp_print_buffer ("receive buffer", data, count);	ppp->stats.ppp_ibytes += count;	skb = ppp->rpkt;		if ( ppp->flags & SC_SYNC ) {		/* synchronous mode */				if (ppp->toss==0xE0) {			/* this is the 1st frame, reset vj comp */			ppp_receive_error(ppp);			ppp->toss = 0;		}				/*		 * Allocate an skbuff for frame.		 * The 128 is room for VJ header expansion.		 */				if (skb == NULL)			skb = dev_alloc_skb(ppp->mru + 128 + PPP_HDRLEN);					if (skb == NULL) {			if (ppp->flags & SC_DEBUG)				printk(KERN_DEBUG "couldn't "				       "alloc skb for recv\n");		} else {			LIBERATE_SKB(skb);			/*			 * Decompress A/C and protocol compression here.			 */			p = skb_put(skb, 2);			p[0] = PPP_ALLSTATIONS;			p[1] = PPP_UI;			if (*data == PPP_ALLSTATIONS) {				data += 2;				count -= 2;			}			if ((*data & 1) != 0) {				p = skb_put(skb, 1);				p[0] = 0;			}			/* copy frame to socket buffer */			p = skb_put(skb, count);			memcpy(p,data,count);						/*			 * Check if we've overflowed the MRU			 */			if (skb->len >= ppp->mru + PPP_HDRLEN + 2			    || skb_tailroom(skb) <= 0) {				++ppp->estats.rx_length_errors;				if (ppp->flags & SC_DEBUG)					printk(KERN_DEBUG "rcv frame too long: "					       "len=%d mru=%d hroom=%d troom=%d\n",					       skb->len, ppp->mru, skb_headroom(skb),					       skb_tailroom(skb));			} else {				if (!ppp_receive_frame(ppp, skb)) {					KFREE_SKB(skb);					ppp_receive_error(ppp);				}			}					/* Reset for the next frame */			skb = NULL;		}		ppp->rpkt = skb;		return;	}		while (count-- > 0) {		/*		 * Collect the character and error condition for the character.		 * Set the toss flag for the first character error.		 */		chr = *data++;		if (flags) {			flg = *flags++;			if (flg) {				if (ppp->toss == 0)					ppp->toss = flg;				switch (flg) {				case TTY_OVERRUN:					++ppp->estats.rx_fifo_errors;					break;				case TTY_FRAME:				case TTY_BREAK:					++ppp->estats.rx_frame_errors;					break;				}				continue;			}		}		/*		 * Set the flags for d7 being 0/1 and parity being		 * even/odd so that the normal processing would have		 * all flags set at the end of the session.  A		 * missing flag bit indicates an error condition.		 */#ifdef CHECK_CHARACTERS		if (chr & 0x80)			ppp->flags |= SC_RCV_B7_1;		else			ppp->flags |= SC_RCV_B7_0;		if (paritytab[chr >> 5] & (1 << (chr & 0x1F)))			ppp->flags |= SC_RCV_ODDP;		else			ppp->flags |= SC_RCV_EVNP;#endif		if (chr == PPP_FLAG) {			/*			 * FLAG. This is the end of the block. If the block			 * ends with ESC FLAG, then the block is to be ignored.			 */			if (ppp->escape)				ppp->toss |= 0x80;			/*			 * Process the frame if it was received correctly.			 * If there was an error, let the VJ decompressor know.			 * There are 4 cases here:			 * skb != NULL, toss != 0: error in frame			 * skb != NULL, toss == 0: frame ok			 * skb == NULL, toss != 0: very first frame,			 *	error on 1st char, or alloc_skb failed			 * skb == NULL, toss == 0: empty frame (~~)			 */			if (ppp->toss || !ppp_receive_frame(ppp, skb)) {				if (ppp->toss && (ppp->flags & SC_DEBUG))					printk(KERN_DEBUG					       "ppp: tossing frame (%x)\n",					       ppp->toss);				if (skb != NULL)					KFREE_SKB(skb);				if (!(ppp->toss == 0xE0 || ppp->toss == 0x80))					++ppp->stats.ppp_ierrors;				ppp_receive_error(ppp);			}			/*			 * Reset for the next frame.			 */			skb = NULL;			ppp->rfcs = PPP_INITFCS;			ppp->escape = 0;			ppp->toss = 0;			continue;		}		/* If we're tossing, look no further. */		if (ppp->toss != 0)			continue;		/* If this is a control char to be ignored, do so */		if (in_rmap(ppp, chr))			continue;		/*		 * Modify the next character if preceded by escape.		 * The escape character (0x7d) could be an escaped		 * 0x5d, if it follows an escape :-)		 */		if (ppp->escape) {			chr ^= PPP_TRANS;			ppp->escape = 0;		} else if (chr == PPP_ESCAPE) {			ppp->escape = PPP_TRANS;			continue;		}		/*		 * Allocate an skbuff on the first character received.		 * The 128 is room for VJ header expansion and FCS.		 */		if (skb == NULL) {			skb = dev_alloc_skb(ppp->mru + 128 + PPP_HDRLEN);			if (skb == NULL) {				if (ppp->flags & SC_DEBUG)					printk(KERN_DEBUG "couldn't "					       "alloc skb for recv\n");				ppp->toss = 1;				continue;			}			LIBERATE_SKB(skb);		}		/*		 * Decompress A/C and protocol compression here.		 */		if (skb->len == 0 && chr != PPP_ALLSTATIONS) {			p = skb_put(skb, 2);			p[0] = PPP_ALLSTATIONS;			p[1] = PPP_UI;		}		if (skb->len == 2 && (chr & 1) != 0) {			p = skb_put(skb, 1);			p[0] = 0;		}		/*		 * Check if we've overflowed the MRU		 */		if (skb->len >= ppp->mru + PPP_HDRLEN + 2		    || skb_tailroom(skb) <= 0) {			++ppp->estats.rx_length_errors;			ppp->toss = 0xC0;			if (ppp->flags & SC_DEBUG)				printk(KERN_DEBUG "rcv frame too long: "				       "len=%d mru=%d hroom=%d troom=%d\n",				       skb->len, ppp->mru, skb_headroom(skb),				       skb_tailroom(skb));			continue;		}		/*		 * Store the character and update the FCS.		 */		p = skb_put(skb, 1);		*p = chr;		ppp->rfcs = PPP_FCS(ppp->rfcs, chr);	}	ppp->rpkt = skb;}/************************************************************* * PPP NETWORK INTERFACE SUPPORT *	The following code implements the PPP network *	interface device and handles those parts of *	the PPP processing which are independent of the *	type of hardware link being used, including *	VJ and packet compression. *************************************************************//* * Network device driver callback routines */static int ppp_init_dev(struct device *dev);static int ppp_dev_open(struct device *);static int ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd);static int ppp_dev_close(struct device *);static int ppp_dev_xmit(struct sk_buff *, struct device *);static struct net_device_stats *ppp_dev_stats (struct device *);#if LINUX_VERSION_CODE < VERSION(2,1,15)static int ppp_dev_header(struct sk_buff *, struct device *, __u16,			  void *, void *, unsigned int);static int ppp_dev_rebuild(void *eth, struct device *dev,			   unsigned long raddr, struct sk_buff *skb);#endif/* * Information for the protocol decoder */typedef int (*pfn_proto)  (struct ppp *, struct sk_buff *);typedef struct ppp_proto_struct {	int		proto;	pfn_proto	func;} ppp_proto_type;static int rcv_proto_ip		(struct ppp *, struct sk_buff *);static int rcv_proto_ipv6	(struct ppp *, struct sk_buff *);static int rcv_proto_ipx	(struct ppp *, struct sk_buff *);static int rcv_proto_at		(struct ppp *, struct sk_buff *);static int rcv_proto_vjc_comp	(struct ppp *, struct sk_buff *);static int rcv_proto_vjc_uncomp (struct ppp *, struct sk_buff *);static int rcv_proto_ccp	(struct ppp *, struct sk_buff *);static int rcv_proto_unknown	(struct ppp *, struct sk_buff *);staticppp_proto_type proto_list[] = {	{ PPP_IP,	  rcv_proto_ip	       },	{ PPP_IPV6,	  rcv_proto_ipv6       },	{ PPP_IPX,	  rcv_proto_ipx	       },	{ PPP_AT,	  rcv_proto_at	       },	{ PPP_VJC_COMP,	  rcv_proto_vjc_comp   },	{ PPP_VJC_UNCOMP, rcv_proto_vjc_uncomp },	{ PPP_CCP,	  rcv_proto_ccp	       },	{ 0,		  rcv_proto_unknown    }  /* !!! MUST BE LAST !!! */};/* * Called when the PPP network interface device is actually created. */static intppp_init_dev (struct device *dev){	dev->hard_header_len  = PPP_HDRLEN;#if LINUX_VERSION_CODE < VERSION(2,1,15)	dev->hard_header      = ppp_dev_header;

⌨️ 快捷键说明

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