+ * If the frame is compressed then decompress it.
+ */
+ new_data = kmalloc (ppp->mru + PPP_HDRLEN, GFP_ATOMIC);
+ if (new_data == NULL) {
+ if (ppp->flags & SC_DEBUG)
+ printk (KERN_ERR
+ "ppp_doframe: no memory\n");
+ new_count = DECOMP_ERROR;
+ } else {
+ new_count = (*ppp->sc_rcomp->decompress)
+ (ppp->sc_rc_state, data, count,
+ new_data, ppp->mru + PPP_HDRLEN);
+ }
+ switch (new_count) {
+ default:
+ ppp_doframe_lower (ppp, new_data, new_count);
+ kfree (new_data);
+ return 1;
+
+ case DECOMP_ERROR:
+ ppp->flags |= SC_DC_ERROR;
+ break;
+
+ case DECOMP_FATALERROR:
+ ppp->flags |= SC_DC_FERROR;
+ if (ppp->flags & SC_DEBUG)
+ printk(KERN_ERR "ppp: fatal decomp error\n");
+ break;
+ }
+/*
+ * Log the error condition and discard the frame.
+ */
+ if (new_data != 0)
+ kfree (new_data);
+ slhc_toss (ppp->slcomp);
+ ++ppp->stats.ppp_ierrors;
+ } else {
+/*
+ * 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;
+}
+
+static void ppp_doframe_lower (struct ppp *ppp, __u8 *data, int count)
+{
+ __u16 proto = PPP_PROTOCOL (data);
+ ppp_proto_type *proto_ptr;
+
+ CHECK_PPP_VOID();
+/*
+ * Ignore empty frames
+ */
+ if (count <= PPP_HDRLEN)
+ return;
+/*
+ * Count the frame and print it
+ */
+ ++ppp->stats.ppp_ipackets;
+ if (ppp->flags & SC_LOG_INPKT)
+ ppp_print_buffer ("receive frame", data, count);
+/*
+ * Find the procedure to handle this protocol. The last one is marked
+ * as a protocol 0 which is the 'catch-all' to feed it to the pppd daemon.
+ */
+ proto_ptr = proto_list;
+ while (proto_ptr->proto != 0 && proto_ptr->proto != proto)
+ ++proto_ptr;
+/*
+ * Update the appropriate statistic counter.
+ */
+ if ((*proto_ptr->func) (ppp, proto,
+ &data[PPP_HDRLEN],
+ count - PPP_HDRLEN))
+ ppp->stats.ppp_ioctects += count;
+ else
+ ++ppp->stats.ppp_discards;
+}
+
+/*
+ * 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->last_recv = 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)
+{
+ CHECK_PPP(0);
+ 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)
+{
+ CHECK_PPP(0);
+ 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)
+{
+ CHECK_PPP(0);
+ 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