- if (tty != ppp->tty)
- return;
-/*
- * Fetch the pointer to the buffer. Be careful about race conditions.
- */
- if (ppp != NULL)
- buf = ppp->rbuf;
-
- if (buf == NULL)
- 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: handler called but couldn't find "
- "PPP struct.\n");
- return;
- }
- CHECK_PPP_VOID ();
-/*
- * Print the buffer if desired
- */
- if (ppp->flags & SC_LOG_RAWIN)
- ppp_print_buffer ("receive buffer", data, count);
-/*
- * Collect the character and error condition for the character. Set the toss
- * flag for the first character error.
- */
- while (count-- > 0) {
- ppp->bytes_rcvd++;
- chr = *data++;
- if (flags) {
- if (*flags && ppp->toss == 0) {
- ppp->toss = *flags;
- switch (ppp->toss) {
- case TTY_OVERRUN:
- ++ppp->estats.rx_fifo_errors;
- break;
- case TTY_FRAME:
- case TTY_BREAK:
- ++ppp->estats.rx_frame_errors;
- break;
- }
- }
- ++flags;
- }
-/*
- * 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
-/*
- * Branch on the character.
- */
- switch (chr) {
-/*
- * FLAG. This is the end of the block. If the block terminated by ESC FLAG,
- * then the block is to be ignored. In addition, characters before the very
- * first FLAG are also tossed by this procedure.
- */
- case PPP_FLAG: /* PPP_FLAG: end of frame */
- ppp->stats.ppp_ibytes += ppp->rbuf->count;
- if (ppp->escape)
- ppp->toss |= 0x80;
-/*
- * Process frames which are not to be ignored. If the processing failed,
- * then clean up the VJ tables.
- */
- if (ppp_doframe (ppp) == 0) {
- ++ppp->stats.ppp_ierrors;
- slhc_toss (ppp->slcomp);
- }
-/*
- * Reset all indicators for the new frame to follow.
- */
- buf->count = 0;
- buf->fcs = PPP_INITFCS;
- ppp->escape = 0;
- ppp->toss = 0;
- break;
-/*
- * All other characters in the data come here. If the character is in the
- * receive mask then ignore the character.
- */
- default:
- /* If we're tossing, look no further. */
- if (ppp->toss != 0)
- break;
-
- /* If this is a control char to be ignored, do so */
- if (in_rmap (ppp, chr))
- break;
-
- /*
- * 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->escape;
- ppp->escape = 0;
- } else if (chr == PPP_ESCAPE) {
- ppp->escape = PPP_TRANS;
- break;
- }
-
-/*
- * If the count sent is within reason then store the character, bump the
- * count, and update the FCS for the character.
- */
- if (buf->count < buf->size) {
- buf_base (buf)[buf->count++] = chr;
- buf->fcs = PPP_FCS (buf->fcs, chr);
- break;
- }
-/*
- * The peer sent too much data. Set the flags to discard the current frame
- * and wait for the re-synchronization FLAG to be sent.
- */
- ++ppp->estats.rx_length_errors;
- ppp->toss |= 0xC0;
- break;
- }
- }
-}
-
-/*
- * Put the input frame into the networking system for the indicated protocol
- */
-
-static int
-ppp_rcv_rx (struct ppp *ppp, __u16 proto, __u8 * data, int count)
-{
- sk_buff *skb = dev_alloc_skb (count);
-/*
- * Generate a skb buffer for the new frame.
- */
- if (skb == NULL) {
- if (ppp->flags & SC_DEBUG)
- printk (KERN_ERR
- "ppp_do_ip: packet dropped on %s (no memory)!\n",
- ppp2dev (ppp)->name);
- return 0;
- }
-/*
- * Move the received data from the input buffer to the skb buffer.
- */
- skb->dev = ppp2dev (ppp); /* We are the device */
- skb->protocol = proto;
- skb->mac.raw = skb_data(skb);
- memcpy (skb_put(skb,count), data, count); /* move data */
-/*
- * Tag the frame and kick it to the proper receive routine
- */
-#if LINUX_VERSION_CODE < VERSION(2,1,15)
- skb->free = 1;
-#endif
-
- ppp->ddinfo.recv_idle = jiffies;
- netif_rx (skb);
- return 1;
-}
-
-/*
- * Process the receipt of an IP frame
- */
-
-static int
-rcv_proto_ip (struct ppp *ppp, __u16 proto, __u8 * data, int count)
-{
- if ((ppp2dev (ppp)->flags & IFF_UP) && (count > 0))
- if (ppp->sc_npmode[NP_IP] == NPMODE_PASS)
- return ppp_rcv_rx (ppp, htons (ETH_P_IP), data, count);
- return 0;
-}
-
-/*
- * Process the receipt of an IPX frame
- */
-
-static int
-rcv_proto_ipx (struct ppp *ppp, __u16 proto, __u8 * data, int count)
-{
- if (((ppp2dev (ppp)->flags & IFF_UP) != 0) && (count > 0))
- return ppp_rcv_rx (ppp, htons (ETH_P_IPX), data, count);
- return 0;
-}
-
-/*
- * Process the receipt of an VJ Compressed frame
- */
-
-static int
-rcv_proto_vjc_comp (struct ppp *ppp, __u16 proto,
- __u8 *data, int count)
-{
- if ((ppp->flags & SC_REJ_COMP_TCP) == 0) {
- int new_count = slhc_uncompress (ppp->slcomp, data, count);
- if (new_count >= 0) {
- return rcv_proto_ip (ppp, PPP_IP, data, new_count);
- }
- if (ppp->flags & SC_DEBUG)
- printk (KERN_NOTICE
- "ppp: error in VJ decompression\n");
- }
- return 0;
-}
-
-/*
- * Process the receipt of an VJ Un-compressed frame
- */
-
-static int
-rcv_proto_vjc_uncomp (struct ppp *ppp, __u16 proto,
- __u8 *data, int count)
-{
- if ((ppp->flags & SC_REJ_COMP_TCP) == 0) {
- if (slhc_remember (ppp->slcomp, data, count) > 0) {
- return rcv_proto_ip (ppp, PPP_IP, data, count);
- }
- if (ppp->flags & SC_DEBUG)
- printk (KERN_NOTICE
- "ppp: error in VJ memorizing\n");
- }
- return 0;
-}
-
-/*
- * Receive all unclassified protocols.
- */
-
-static int
-rcv_proto_unknown (struct ppp *ppp, __u16 proto,
- __u8 *data, int len)
-{
- int totlen;
- register int current_idx;
-
-#define PUTC(c) \
-{ \
- buf_base (ppp->ubuf) [current_idx++] = (__u8) (c); \
- current_idx &= ppp->ubuf->size; \
- if (current_idx == ppp->ubuf->tail) \
- goto failure; \
-}
-
-/*
- * The total length includes the protocol data.
- * Lock the user information buffer.
- */
- if (set_bit (0, &ppp->ubuf->locked)) {
- if (ppp->flags & SC_DEBUG)
- printk (KERN_DEBUG
- "ppp_us_queue: can't get lock\n");
- } else {
- current_idx = ppp->ubuf->head;
-/*
- * Insert the buffer length (not counted), the protocol, and the data
- */
- totlen = len + 2;
- PUTC (totlen >> 8);
- PUTC (totlen);
-
- PUTC (proto >> 8);
- PUTC (proto);
-
- totlen -= 2;
- while (totlen-- > 0) {
- PUTC (*data++);
- }
-#undef PUTC
-/*
- * The frame is complete. Update the head pointer and wakeup the pppd
- * process.
- */
- ppp->ubuf->head = current_idx;
-
- clear_bit (0, &ppp->ubuf->locked);
- wake_up_interruptible (&ppp->read_wait);
- if (ppp->tty->fasync != NULL)
- kill_fasync (ppp->tty->fasync, SIGIO);
-
- return 1;
-/*
- * The buffer is full. Unlock the header
- */
-failure:
- clear_bit (0, &ppp->ubuf->locked);
- if (ppp->flags & SC_DEBUG)
- printk (KERN_DEBUG
- "ppp_us_queue: ran out of buffer space.\n");
- }
-/*
- * Discard the frame. There are no takers for this protocol.
- */
- if (ppp->flags & SC_DEBUG)
- printk (KERN_DEBUG
- "ppp: dropping packet on the floor.\n");
- slhc_toss (ppp->slcomp);
- return 0;
-}
-
-/*
- * Handle a CCP packet.
- *
- * The CCP packet is passed along to the pppd process just like any
- * other PPP frame. The difference is that some processing needs to be
- * immediate or the compressors will become confused on the peer.
- */
-
-static void ppp_proto_ccp (struct ppp *ppp, __u8 *dp, int len, int rcvd)
-{
- int slen = CCP_LENGTH(dp);
- __u8 *opt = dp + CCP_HDRLEN;
- int opt_len = slen - CCP_HDRLEN;
-
- if (slen > len)
- return;