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

📄 ppp.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		malloced_data = 1;	} else		malloced_data = 0;#endif/* * Process the active decompressor. */	if ((ppp->sc_rc_state != (void *) 0) &&	    (ppp->flags & SC_DECOMP_RUN)     &&	    ((ppp->flags & (SC_DC_FERROR | SC_DC_ERROR)) == 0)) {		if (proto == PPP_COMP) {/* * If the frame is compressed then decompress it. */			new_data = kmalloc (ppp->mru + 4, GFP_ATOMIC);			if (new_data == NULL) {				if (ppp->flags & SC_DEBUG)					printk (KERN_ERR						"ppp_doframe: no memory\n");				slhc_toss (ppp->slcomp);				(*ppp->sc_rcomp->incomp) (ppp->sc_rc_state,							  data,							  count);#ifndef NO_RMK_TEMP_FIX				if (malloced_data) kfree (data);#endif							  				return 1;			}/* * Decompress the frame */			new_count = bsd_decompress (ppp->sc_rc_state,						    data,						    count,						    new_data,						    ppp->mru + 4);			switch (new_count) {			default:				ppp_doframe_lower (ppp, new_data, new_count);				kfree (new_data);#ifndef NO_RMK_TEMP_FIX				if (malloced_data) kfree (data);#endif				return 1;			case DECOMP_OK:				break;			case DECOMP_ERROR:				ppp->flags |= SC_DC_ERROR;				break;			case DECOMP_FATALERROR:				ppp->flags |= SC_DC_FERROR;				break;			}/* * Log the error condition and discard the frame. */			if (ppp->flags & SC_DEBUG)				printk (KERN_ERR					"ppp_proto_comp: "					"decompress err %d\n", new_count);			kfree (new_data);			slhc_toss (ppp->slcomp);#ifndef NO_RMK_TEMP_FIX			if (malloced_data) kfree (data);#endif							  			return 1;		}/* * The frame is not special. Pass it through the compressor without * actually compressing the data */		(*ppp->sc_rcomp->incomp) (ppp->sc_rc_state,					  data,					  count);	}/* * Process the uncompressed frame. */	ppp_doframe_lower (ppp, data, count);#ifndef NO_RMK_TEMP_FIX	if (malloced_data) kfree (data);#endif							  	return 1;}/************************************************************* * LINE DISCIPLINE SUPPORT *    The following functions form support user programs *    which read and write data on a TTY with the PPP line *    discipline.  Reading is done from a circular queue, *    filled by the lower TTY levels. *************************************************************//* read a PPP frame from the us_rbuff circular buffer,   waiting if necessary*/static intppp_tty_read (struct tty_struct *tty, struct file *file, __u8 * buf,	      unsigned int nr){	struct ppp *ppp = tty2ppp (tty);	__u8 c;	int len, indx;#define GETC(c)						\{							\	c = buf_base (ppp->ubuf) [ppp->ubuf->tail++];	\	ppp->ubuf->tail &= ppp->ubuf->size;		\}/* * Validate the pointers */	if (!ppp)		return -EIO;	if (ppp->magic != PPP_MAGIC)		return -EIO;	CHECK_PPP (-ENXIO);	if (ppp->flags & SC_DEBUG)		printk (KERN_DEBUG			"ppp_tty_read: called buf=%p nr=%u\n",			buf, nr);/* * Acquire the read lock. */	for (;;) {		ppp = tty2ppp (tty);		if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse)			return 0;		if (set_bit (0, &ppp->ubuf->locked) != 0) {			if (ppp->flags & SC_DEBUG)				printk (KERN_DEBUG				     "ppp_tty_read: sleeping(ubuf)\n");			current->timeout = 0;			current->state   = TASK_INTERRUPTIBLE;			schedule ();			if (current->signal & ~current->blocked)				return -EINTR;			continue;		}/* * Before we attempt to write the frame to the user, ensure that the * user has access to the pages for the total buffer length. */		indx = verify_area (VERIFY_WRITE, buf, nr);		if (indx != 0)			return (indx);/* * Fetch the length of the buffer from the first two bytes. */		if (ppp->ubuf->head == ppp->ubuf->tail)			len = 0;		else {			GETC (c);			len = c << 8;			GETC (c);			len += c;		}/* * If there is no length then wait for the data to arrive. */		if (len == 0) {			/* no data */			clear_bit (0, &ppp->ubuf->locked);			if (file->f_flags & O_NONBLOCK) {				if (ppp->flags & SC_DEBUG)					printk (KERN_DEBUG						"ppp_tty_read: no data "						"(EAGAIN)\n");				return -EAGAIN;			}			current->timeout = 0;			if (ppp->flags & SC_DEBUG)				printk (KERN_DEBUG					"ppp_tty_read: sleeping(read_wait)\n");			interruptible_sleep_on (&ppp->read_wait);			if (current->signal & ~current->blocked)				return -EINTR;			continue;		}/* * Reset the time of the last read operation. */		if (ppp->flags & SC_DEBUG)			printk (KERN_DEBUG "ppp_tty_read: len = %d\n", len);/* * Ensure that the frame will fit within the caller's buffer. If not, then * discard the frame from the input buffer. */		if (len + 2 > nr) {			/* Can't copy it, update us_rbuff_head */			if (ppp->flags & SC_DEBUG)				printk (KERN_DEBUG				"ppp: read of %u bytes too small for %d "				"frame\n", nr, len + 2);			ppp->ubuf->tail += len;			ppp->ubuf->tail &= ppp->ubuf->size;			clear_bit (0, &ppp->ubuf->locked);			ppp->stats.ppp_ierrors++;			return -EOVERFLOW;		}/* * Before we attempt to write the frame to the user, ensure that the * page tables are proper. */		indx = verify_area (VERIFY_WRITE, buf, len + 2);		if (indx != 0) {			ppp->ubuf->tail += len;			ppp->ubuf->tail &= ppp->ubuf->size;			clear_bit (0, &ppp->ubuf->locked);			return (indx);		}/* * Fake the insertion of the ADDRESS and CONTROL information because these * were not saved in the buffer. */		put_user (PPP_ALLSTATIONS, buf++);		put_user (PPP_UI,          buf++);		indx = len;/* * Copy the received data from the buffer to the caller's area. */		while (indx-- > 0) {			GETC (c);			put_user (c, buf);			++buf;		}		clear_bit (0, &ppp->ubuf->locked);		len += 2; /* Account for ADDRESS and CONTROL bytes */		if (ppp->flags & SC_DEBUG)			printk (KERN_DEBUG				"ppp_tty_read: passing %d bytes up\n", len);		return len;	}#undef GETC}/* stuff a character into the transmit buffer, using PPP's way of escaping   special characters.   also, update fcs to take account of new character */extern inline voidppp_stuff_char (struct ppp *ppp, register struct ppp_buffer *buf,		register __u8 chr){/* * The buffer should not be full. */	if (ppp->flags & SC_DEBUG) {		if ((buf->count < 0) || (buf->count > 3000))			printk (KERN_DEBUG "ppp_stuff_char: %x %d\n",				(unsigned int) buf->count,				(unsigned int) chr);	}/* * Update the FCS and if the character needs to be escaped, do it. */	buf->fcs = PPP_FCS (buf->fcs, chr);	if (in_xmap (ppp, chr)) {		chr ^= PPP_TRANS;		ins_char (buf, PPP_ESCAPE);	}/* * Add the character to the buffer. */	ins_char (buf, chr);}/* * Procedure to encode the data with the proper escaping and send the * data to the remote system. */static voidppp_dev_xmit_lower (struct ppp *ppp, struct ppp_buffer *buf,		    __u8 *data, int count, int non_ip){	__u16 write_fcs;	int     address, control;	int	proto;/* * Insert the leading FLAG character */	buf->count = 0;	if (non_ip || flag_time == 0)		ins_char (buf, PPP_FLAG);	else {		if (jiffies - ppp->last_xmit > flag_time)			ins_char (buf, PPP_FLAG);	}	ppp->last_xmit = jiffies;	buf->fcs       = PPP_INITFCS;/* * Emit the address/control information if needed */	address = PPP_ADDRESS  (data);	control = PPP_CONTROL  (data);	proto   = PPP_PROTOCOL (data);	if (address != PPP_ALLSTATIONS ||	    control != PPP_UI ||	    (ppp->flags & SC_COMP_AC) == 0) {		ppp_stuff_char (ppp, buf, address);		ppp_stuff_char (ppp, buf, control);	}/* * Emit the protocol (compressed if possible) */	if ((ppp->flags & SC_COMP_PROT) == 0 || (proto & 0xFF00))		ppp_stuff_char (ppp, buf, proto >> 8);	ppp_stuff_char (ppp, buf, proto);/* * Insert the data */	data  += 4;	count -= 4;	while (count-- > 0)		ppp_stuff_char (ppp, buf, *data++);/* * Add the trailing CRC and the final flag character */	write_fcs = buf->fcs ^ 0xFFFF;	ppp_stuff_char (ppp, buf, write_fcs);	ppp_stuff_char (ppp, buf, write_fcs >> 8);	if (ppp->flags & SC_DEBUG)		printk (KERN_DEBUG "ppp_dev_xmit_lower: fcs is %hx\n",			write_fcs);/* * Add the trailing flag character */	ins_char (buf, PPP_FLAG);/* * Print the buffer */	if (ppp->flags & SC_LOG_FLUSH)		ppp_print_buffer ("ppp flush", buf_base (buf),				  buf->count);	else {		if (ppp->flags & SC_DEBUG)			printk (KERN_DEBUG				"ppp_dev_xmit: writing %d chars\n",				buf->count);	}/* * Send the block to the tty driver. */	ppp->stats.ppp_obytes += buf->count;	ppp_kick_tty (ppp, buf);}/* * Send an frame to the remote with the proper bsd compression. * * Return 0 if frame was queued for transmission. *        1 if frame must be re-queued for later driver support. */static intppp_dev_xmit_frame (struct ppp *ppp, struct ppp_buffer *buf,		    __u8 *data, int count){	int	proto;	int     address, control;	__u8 *new_data;	int     new_count;/* * Print the buffer */	if (ppp->flags & SC_LOG_OUTPKT)		ppp_print_buffer ("write frame", data, count);/* * Determine if the frame may be compressed. Attempt to compress the * frame if possible. */	proto   = PPP_PROTOCOL (data);	address = PPP_ADDRESS  (data);	control = PPP_CONTROL  (data);	if (((ppp->flags & SC_COMP_RUN) != 0)	&&	    (ppp->sc_xc_state != (void *) 0)	&&	    (address == PPP_ALLSTATIONS)	&&	    (control == PPP_UI)			&&	    (proto != PPP_LCP)			&&	    (proto != PPP_CCP)) {		new_data = kmalloc (count, GFP_ATOMIC);		if (new_data == NULL) {			if (ppp->flags & SC_DEBUG)				printk (KERN_ERR					"ppp_dev_xmit_frame: no memory\n");			return 1;		}		new_count = bsd_compress (ppp->sc_xc_state,					  data,					  new_data,					  count,					  count);		if (new_count > 0) {			++ppp->stats.ppp_opackets;			ppp->stats.ppp_ooctects += new_count;			ppp_dev_xmit_lower (ppp, buf, new_data,					    new_count, 0);			kfree (new_data);			return 0;		}/* * The frame could not be compressed. */		kfree (new_data);	}/* * The frame may not be compressed. Update the statistics before the * count field is destroyed. The frame will be transmitted. */	++ppp->stats.ppp_opackets;	ppp->stats.ppp_ooctects += count;/* * Go to the escape encoding */	ppp_dev_xmit_lower (ppp, buf, data, count, !!(proto & 0xFF00));	return 0;}/* * Revise the tty frame for specific protocols. */static intsend_revise_frame (register struct ppp *ppp, __u8 *data, int len){	__u8 *p;	switch (PPP_PROTOCOL (data)) {/* * Update the LQR frame with the current MIB information. This saves having * the daemon read old MIB data from the driver. */	case PPP_LQR:		len = 48;			/* total size of this frame */		p   = (__u8 *) &data [40];	/* Point to last two items. */		p   = store_long (p, ppp->stats.ppp_opackets + 1);		p   = store_long (p, ppp->stats.ppp_ooctects + len);		break;/* * Outbound compression frames */	case PPP_CCP:		ppp_proto_ccp (ppp,			       data + PPP_HARD_HDR_LEN,			       len  - PPP_HARD_HDR_LEN,			       0);		break;	default:		break;	}	return len;}/* * write a frame with NR chars from BUF to TTY * we have to put the FCS field on ourselves */static intppp_tty_write (struct tty_struct *tty, struct file *file, const __u8 * data,	       unsigned int count){	struct ppp *ppp = tty2ppp (tty);	__u8 *new_data;	int status;/* * Verify the pointers. */	if (!ppp)		return -EIO;	if (ppp->magic != PPP_MAGIC)		return -EIO;	CHECK_PPP (-ENXIO);/* * Ensure that the caller does not wish to send too much. */	if (count > PPP_MTU) {		if (ppp->flags & SC_DEBUG)			printk (KERN_WARNING				"ppp_tty_write: truncating user packet "				"from %u to mtu %d\n", count, PPP_MTU);		count = PPP_MTU;	}/* * Allocate a buffer for the data and fetch it from the user space. */	new_data = kmalloc (count, GFP_KERNEL);	if (new_data == NULL) {		if (ppp->flags & SC_DEBUG)			printk (KERN_ERR				"ppp_tty_write: no memory\n");		return 0;	}/* * lock this PPP unit so we will be the only writer; * sleep if necessary */	while (lock_buffer (ppp->tbuf) != 0) {		current->timeout = 0;		if (ppp->flags & SC_DEBUG)			printk (KERN_DEBUG "ppp_tty_write: sleeping\n");		interruptible_sleep_on (&ppp->write_wait);		ppp = tty2ppp (tty);		if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse) {			kfree (new_data);

⌨️ 快捷键说明

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