- if ((data[0] == PPP_ALLSTATIONS) && (data[1] == PPP_UI)) {
- data += 2;
- count -= 2;
- }
-/*
- * Obtain the protocol from the frame
- */
- proto = (u_short) *data++;
- if ((proto & 1) == 0) {
- proto = (proto << 8) | (u_short) *data++;
- --count;
- }
-/*
- * Rewrite the header with the full information. This may encroach upon
- * the 'filler' area in the buffer header. This is the purpose for the
- * filler.
- */
- *(--data) = proto;
- *(--data) = proto >> 8;
- *(--data) = ctrl;
- *(--data) = addr;
- count += 3;
-/*
- * 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);
- 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);
- 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);
- 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);
- 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 int
-ppp_tty_read (struct tty_struct *tty, struct file *file, u_char * buf,
- unsigned int nr)
-{
- struct ppp *ppp = tty2ppp (tty);
- u_char c;
- int len, indx;
-
-#define GETC(c) \
-{ \
- c = buf_base (ppp->ubuf) [ppp->ubuf->tail++]; \
- ppp->ubuf->tail &= ppp->ubuf->size; \
-}
-
-/*
- * Validate the pointer to the PPP structure
- */
- 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 "
- "(EWOULDBLOCK)\n");
- return -EWOULDBLOCK;
- }
- 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 and return an error to the caller.
- */
- 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_byte_user (PPP_ALLSTATIONS, buf++);
- put_byte_user (PPP_UI, buf++);
-
- indx = len;
-/*
- * Copy the received data from the buffer to the caller's area.
- */
- while (indx-- > 0) {
- GETC (c);
- put_byte_user (c, buf);
- ++buf;
- }
-/*
- * Release the lock and return the character count in the buffer area.
- */
- 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 void
-ppp_stuff_char (struct ppp *ppp, register struct ppp_buffer *buf,
- register u_char 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 escapement and send the
- * data to the remote system.
- */
-
-static void
-ppp_dev_xmit_lower (struct ppp *ppp, struct ppp_buffer *buf,
- u_char *data, int count, int non_ip)
-{
- unsigned short int 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);