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

📄 ppp.c

📁 arm平台上的uclinux系统全部源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
extern inline intlock_buffer (register struct ppp_buffer *buf){	register int state;	int flags;/* * Save the current state and if free then set it to the "busy" state */	save_flags (flags);	cli ();	state = buf->locked;	if (state == 0)		buf->locked = 2;	restore_flags (flags);	return (state);}/* * MTU has been changed by the IP layer. Unfortunately we are not told * about this, but we spot it ourselves and fix things up. We could be * in an upcall from the tty driver, or in an ip packet queue. */static intppp_changedmtu (struct ppp *ppp, int new_mtu, int new_mru){	struct device *dev;	struct ppp_buffer *new_rbuf;	struct ppp_buffer *new_wbuf;	struct ppp_buffer *new_cbuf;	struct ppp_buffer *new_tbuf;	struct ppp_buffer *old_rbuf;	struct ppp_buffer *old_wbuf;	struct ppp_buffer *old_cbuf;	struct ppp_buffer *old_tbuf;	int mtu, mru;/* *  Allocate the buffer from the kernel for the data */	dev = ppp2dev (ppp);	mru = new_mru;	/* allow for possible escaping of every character */	mtu = (new_mtu * 2) + 20;	/* RFC 1331, section 7.2 says the minimum value is 1500 bytes */	if (mru < PPP_MRU)		mru = PPP_MRU;	mru += 10;		if (ppp->flags & SC_DEBUG)		printk (KERN_INFO "ppp: channel %s mtu = %d, mru = %d\n",			dev->name, new_mtu, new_mru);	new_wbuf = ppp_alloc_buf (mtu+PPP_HARD_HDR_LEN,	BUFFER_TYPE_DEV_WR);	new_tbuf = ppp_alloc_buf ((PPP_MTU * 2) + 24,	BUFFER_TYPE_TTY_WR);	new_rbuf = ppp_alloc_buf (mru + 84,		BUFFER_TYPE_DEV_RD);	new_cbuf = ppp_alloc_buf (mru+PPP_HARD_HDR_LEN,	BUFFER_TYPE_VJ);/* *  If the buffers failed to allocate then complain and release the partial *  allocations. */	if (new_wbuf == NULL || new_tbuf == NULL ||	    new_rbuf == NULL || new_cbuf == NULL) {		if (ppp->flags & SC_DEBUG)			printk (KERN_ERR				"ppp: failed to allocate new buffers\n");		ppp_free_buf (new_wbuf);		ppp_free_buf (new_tbuf);		ppp_free_buf (new_rbuf);		ppp_free_buf (new_cbuf);		return 0;	}/* *  Update the pointers to the new buffer structures. */	cli ();	old_wbuf = ppp->wbuf;	old_rbuf = ppp->rbuf;	old_cbuf = ppp->cbuf;	old_tbuf = ppp->tbuf;	ppp->wbuf = new_wbuf;	ppp->rbuf = new_rbuf;	ppp->cbuf = new_cbuf;	ppp->tbuf = new_tbuf;	ppp->rbuf->size -= 80;  /* reserve space for vj header expansion */	dev->mem_start  = (unsigned long) buf_base (new_wbuf);	dev->mem_end    = (unsigned long) (dev->mem_start + mtu);	dev->rmem_start = (unsigned long) buf_base (new_rbuf);	dev->rmem_end   = (unsigned long) (dev->rmem_start + mru);/* *  Update the parameters for the new buffer sizes */	ppp->toss   = 0xE0;	/* To ignore characters until new FLAG */	ppp->escape = 0;	/* No pending escape character */	dev->mtu    =	ppp->mtu    = new_mtu;	ppp->mru    = new_mru;	ppp->s1buf  = NULL;	ppp->s2buf  = NULL;	ppp->xbuf   = NULL;	ppp->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);	ppp->flags      &= ~SC_XMIT_BUSY;	sti ();/* *  Release old buffer pointers */	ppp_free_buf (old_rbuf);	ppp_free_buf (old_wbuf);	ppp_free_buf (old_cbuf);	ppp_free_buf (old_tbuf);	return 1;}/* * CCP is down; free (de)compressor state if necessary. */static voidppp_ccp_closed (struct ppp *ppp){	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;	}}/* * Called to release all of the information in the current PPP structure. * * It is called when the ppp device goes down or if it is unable to go * up. */static voidppp_release (struct ppp *ppp){	struct tty_struct *tty;	struct device *dev;	tty = ppp2tty (ppp);	dev = ppp2dev (ppp);	ppp_ccp_closed (ppp);	/* Ensure that the pppd process is not hanging on select() */	wake_up_interruptible (&ppp->read_wait);	wake_up_interruptible (&ppp->write_wait);		if (tty != NULL && tty->disc_data == ppp)		tty->disc_data = NULL;	/* Break the tty->ppp link */	if (dev && dev->flags & IFF_UP) {		dev_close (dev); /* close the device properly */		dev->flags &= ~IFF_UP;  /* prevent recursion */	}	ppp_free_buf (ppp->rbuf);	ppp_free_buf (ppp->wbuf);	ppp_free_buf (ppp->cbuf);	ppp_free_buf (ppp->ubuf);	ppp_free_buf (ppp->tbuf);	ppp->rbuf  =	ppp->wbuf  =	ppp->cbuf  =	ppp->tbuf  =	ppp->xbuf  =	ppp->s1buf =	ppp->s2buf =	ppp->ubuf  = NULL;	if (ppp->slcomp) {		slhc_free (ppp->slcomp);		ppp->slcomp = NULL;	}	ppp->inuse = 0;	ppp->tty   = NULL;}/* * Device callback. * * Called when the PPP device goes down in response to an ifconfig request. */static voidppp_tty_close_local (struct tty_struct *tty, int sc_xfer){	struct ppp *ppp = tty2ppp (tty);	if (ppp != NULL) {		if (ppp->magic != PPP_MAGIC) {			if (ppp->flags & SC_DEBUG)				printk (KERN_WARNING				       "ppp: trying to close unopened tty!\n");		} else {			CHECK_PPP_VOID();			ppp->sc_xfer = sc_xfer;			if (ppp->flags & SC_DEBUG)				printk (KERN_INFO "ppp: channel %s closing.\n",					ppp2dev(ppp) -> name);			ppp_release (ppp);			MOD_DEC_USE_COUNT;		}	}}static voidppp_tty_close (struct tty_struct *tty){	ppp_tty_close_local (tty, 0);}/* * TTY callback. * * Called when the tty discipline is switched to PPP. */static intppp_tty_open (struct tty_struct *tty){	struct ppp *ppp = tty2ppp (tty);	int indx;/* * There should not be an existing table for this slot. */	if (ppp) {		if (ppp->flags & SC_DEBUG)			printk (KERN_ERR			"ppp_tty_open: gack! tty already associated to %s!\n",			ppp->magic == PPP_MAGIC ? ppp2dev(ppp)->name						: "unknown");		return -EEXIST;	}/* * Allocate the structure from the system */ 	ppp = ppp_find(current->pid); 	if (ppp == NULL) { 		ppp = ppp_find(0); 		if (ppp == NULL) 			ppp = ppp_alloc(); 	} 	if (ppp == NULL) {		if (ppp->flags & SC_DEBUG)			printk (KERN_ERR			"ppp_tty_open: couldn't allocate ppp channel\n");		return -ENFILE;	}/* * Initialize the control block */	ppp_init_ctrl_blk (ppp);	ppp->tty       = tty;	tty->disc_data = ppp;/* * Flush any pending characters in the driver and discipline. */	if (tty->ldisc.flush_buffer)		tty->ldisc.flush_buffer (tty);	if (tty->driver.flush_buffer)		tty->driver.flush_buffer (tty);/* * Allocate space for the default VJ header compression slots */	ppp->slcomp = slhc_init (16, 16);	if (ppp->slcomp == NULL) {		if (ppp->flags & SC_DEBUG)			printk (KERN_ERR			"ppp_tty_open: no space for compression buffers!\n");		ppp_release (ppp);		return -ENOMEM;	}/* * Allocate space for the MTU and MRU buffers */	if (ppp_changedmtu (ppp, ppp2dev(ppp)->mtu, ppp->mru) == 0) {		ppp_release (ppp);		return -ENOMEM;	}/* * Allocate space for a user level buffer */	ppp->ubuf = ppp_alloc_buf (RBUFSIZE, BUFFER_TYPE_TTY_RD);	if (ppp->ubuf == NULL) {		if (ppp->flags & SC_DEBUG)			printk (KERN_ERR		       "ppp_tty_open: no space for user receive buffer\n");		ppp_release (ppp);		return -ENOMEM;	}	if (ppp->flags & SC_DEBUG)		printk (KERN_INFO "ppp: channel %s open\n",			ppp2dev(ppp)->name);	for (indx = 0; indx < NUM_NP; ++indx)		ppp->sc_npmode[indx] = NPMODE_PASS;	MOD_INC_USE_COUNT;	return (ppp->line);}/* * Local function to send the next portion of the buffer. * * Called by the tty driver's tty_wakeup function should it be entered * because the partial buffer was transmitted. * * Called by kick_tty to send the initial portion of the buffer. * * Completion processing of the buffer transmission is handled here. */static voidppp_tty_wakeup_code (struct ppp *ppp, struct tty_struct *tty,		     struct ppp_buffer *xbuf){	register int count, actual;/* * Prevent re-entrancy by ensuring that this routine is called only once. */	cli ();	if (ppp->flags & SC_XMIT_BUSY) {		sti ();		return;	}	ppp->flags |= SC_XMIT_BUSY;	sti ();/* * Send the next block of data to the modem */	count = xbuf->count - xbuf->tail;	actual = tty->driver.write (tty, 0,				    buf_base (xbuf) + xbuf->tail, count);/* * Terminate transmission of any block which may have an error. * This could occur should the carrier drop. */	if (actual < 0) {	        ppp->stats.ppp_oerrors++;		actual = count;	} else		ppp->bytes_sent += actual;/* * If the buffer has been transmitted then clear the indicators. */	xbuf->tail += actual;	if (actual == count) {		xbuf = NULL;		ppp->flags &= ~SC_XMIT_BUSY;/* * Complete the transmission on the current buffer. */		xbuf = ppp->xbuf;		if (xbuf != NULL) {			tty->flags  &= ~(1 << TTY_DO_WRITE_WAKEUP);			xbuf->locked = 0;			ppp->xbuf    = NULL;/* * If the completed buffer came from the device write, then complete the * transmission block. */			if (ppp2dev (ppp) -> flags & IFF_UP) {				if (xbuf->type == BUFFER_TYPE_DEV_WR)				        ppp2dev (ppp)->tbusy = 0;				mark_bh (NET_BH);			}/* * Wake up the transmission queue for all completion events. */			wake_up_interruptible (&ppp->write_wait);/* * Look at the priorities. Choose a daemon write over the device driver. */			cli();			xbuf = ppp->s1buf;			ppp->s1buf = NULL;			if (xbuf == NULL) {				xbuf = ppp->s2buf;				ppp->s2buf = NULL;			}			sti();/* * If there is a pending buffer then transmit it now. */			if (xbuf != NULL) {				ppp->flags &= ~SC_XMIT_BUSY;				ppp_kick_tty (ppp, xbuf);				return;			}		}	}/* * Clear the re-entry flag */	ppp->flags &= ~SC_XMIT_BUSY;}/* * This function is called by the tty driver when the transmit buffer has * additional space. It is used by the ppp code to continue to transmit * the current buffer should the buffer have been partially sent. * * In addition, it is used to send the first part of the buffer since the * logic and the inter-locking would be identical. */static voidppp_tty_wakeup (struct tty_struct *tty){	struct ppp_buffer *xbuf;	struct ppp *ppp = tty2ppp (tty);	if (!ppp)		return;	if (ppp->magic != PPP_MAGIC)		return;/* * Ensure that there is a transmission pending. Clear the re-entry flag if * there is no pending buffer. Otherwise, send the buffer. */	xbuf = ppp->xbuf;	if (xbuf == NULL)		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);	else		ppp_tty_wakeup_code (ppp, tty, xbuf);}/* * This function is called to transmit a buffer to the remote. The buffer * is placed on the pending queue if there is presently a buffer being * sent or it is transmitted with the aid of ppp_tty_wakeup. */static voidppp_kick_tty (struct ppp *ppp, struct ppp_buffer *xbuf){	register int flags;/* * Hold interrupts. */	save_flags (flags);	cli ();/* * Control the flags which are best performed with the interrupts masked. */	xbuf->locked     = 1;	xbuf->tail       = 0;/* * If the transmitter is busy then place the buffer on the appropriate * priority queue. */	if (ppp->xbuf != NULL) {		if (xbuf->type == BUFFER_TYPE_TTY_WR)			ppp->s1buf = xbuf;		else			ppp->s2buf = xbuf;		restore_flags (flags);		return;	}/* * If the transmitter is not busy then this is the highest priority frame */	ppp->flags      &= ~SC_XMIT_BUSY;	ppp->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);	ppp->xbuf        = xbuf;	restore_flags (flags);/* * Do the "tty wakeup_code" to actually send this buffer. */	ppp_tty_wakeup_code (ppp, ppp2tty (ppp), xbuf);}/************************************************************* * TTY INPUT *    The following functions handle input that arrives from *    the TTY.	It recognizes PPP frames and either hands them *    to the network layer or queues them for delivery to a *    user process reading this TTY. *************************************************************//* * 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);	register struct ppp_buffer *buf = NULL;	__u8 chr;/* * Fetch the pointer to the buffer. Be careful about race conditions. */	if (ppp != NULL)		buf = ppp->rbuf;	if (buf == NULL)		return;

⌨️ 快捷键说明

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