📄 ppp.c
字号:
/* * 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; ++flags; }/* * Set the flags for 8 data bits and no parity. * * Actually, it sets 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 would denote 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. Process the escape character. The sequence ESC ESC * is defined to be ESC. */ switch (chr) { case PPP_ESCAPE: /* PPP_ESCAPE: invert bit in next character */ ppp->escape = PPP_TRANS; break;/* * 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->toss & 0x80) != 0 || ppp_doframe (ppp) == 0) { 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 (in_rmap (ppp, chr)) break;/* * Adjust the character and if the frame is to be discarded then simply * ignore the character until the ending FLAG is received. */ chr ^= ppp->escape; ppp->escape = 0; if (ppp->toss != 0) 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->stats.ppp_ierrors++; ppp->toss |= 0xC0; break; } }}/* * Put the input frame into the networking system for the indicated protocol */static intppp_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 */ skb->free = 1; ppp->ddinfo.recv_idle = jiffies; netif_rx (skb); return 1;}/* * Process the receipt of an IP frame */static intrcv_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 intrcv_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 intrcv_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 intrcv_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 intrcv_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); if (ppp->flags & SC_DEBUG) printk (KERN_INFO "ppp: successfully queued %d bytes, flags = %x\n", len + 2, ppp->flags); return 1;/* * The buffer is full. Unlock the header */failure: clear_bit (0, &ppp->ubuf->locked); if (ppp->flags & SC_DEBUG) printk (KERN_INFO "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_WARNING "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; switch (CCP_CODE(dp)) { case CCP_CONFREQ: case CCP_TERMREQ: case CCP_TERMACK:/* * CCP must be going down - disable compression */ if (ppp->flags & SC_CCP_UP) { ppp->flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN); } break; case CCP_CONFACK: if ((ppp->flags & SC_CCP_OPEN) == 0) break; if (ppp->flags & SC_CCP_UP) break; if (slen < (CCP_HDRLEN + CCP_OPT_MINLEN)) break; if (slen < (CCP_OPT_LENGTH (opt) + CCP_HDRLEN)) break;/* * we're agreeing to send compressed packets. */ if (!rcvd) { if (ppp->sc_xc_state == NULL) break; if ((*ppp->sc_xcomp->comp_init) (ppp->sc_xc_state, opt, opt_len, ppp2dev (ppp)->base_addr, 0, ppp->flags)) ppp->flags |= SC_COMP_RUN; break; }/* * peer is agreeing to send compressed packets. */ if (ppp->sc_rc_state == NULL) break; if ((*ppp->sc_rcomp->decomp_init) (ppp->sc_rc_state, opt, opt_len, ppp2dev (ppp)->base_addr, 0, ppp->mru, ppp->flags)) { ppp->flags |= SC_DECOMP_RUN; ppp->flags &= ~(SC_DC_ERROR | SC_DC_FERROR); } break;/* * The protocol sequence is complete at this end */ case CCP_RESETACK: if ((ppp->flags & SC_CCP_UP) == 0) break; if (!rcvd) { if (ppp->sc_xc_state && (ppp->flags & SC_COMP_RUN)) (*ppp->sc_xcomp->comp_reset)(ppp->sc_xc_state); } else { if (ppp->sc_rc_state && (ppp->flags & SC_DECOMP_RUN)) { (*ppp->sc_rcomp->decomp_reset)(ppp->sc_rc_state); ppp->flags &= ~SC_DC_ERROR; } } break; }}static intrcv_proto_ccp (struct ppp *ppp, __u16 proto, __u8 *dp, int len){ ppp_proto_ccp (ppp, dp, len, 1); return rcv_proto_unknown (ppp, proto, dp, len);}/* * Handle a LQR packet. */static intrcv_proto_lqr (struct ppp *ppp, __u16 proto, __u8 * data, int len){ return rcv_proto_unknown (ppp, proto, data, len);}/* on entry, a received frame is in ppp->rbuf.bufr check it and dispose as appropriate */static void ppp_doframe_lower (struct ppp *ppp, __u8 *data, int count){ __u16 proto = PPP_PROTOCOL (data); ppp_proto_type *proto_ptr;/* * Ignore empty frames */ if (count <= 4) 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_HARD_HDR_LEN], count - PPP_HARD_HDR_LEN)) ppp->stats.ppp_ioctects += count; else ++ppp->stats.ppp_discards;}/* on entry, a received frame is in ppp->rbuf.bufr check it and dispose as appropriate */static intppp_doframe (struct ppp *ppp){ __u8 *data = buf_base (ppp->rbuf); int count = ppp->rbuf->count; int addr, ctrl, proto; int new_count; __u8 *new_data;#ifndef NO_RMK_TEMP_FIX int malloced_data;#endif/* * If there is a pending error from the receiver then log it and discard * the damaged frame. */ if (ppp->toss) { if (ppp->flags & SC_DEBUG) printk (KERN_WARNING "ppp_toss: tossing frame, reason = %d\n", ppp->toss); ppp->stats.ppp_ierrors++; return 0; }/* * An empty frame is ignored. This occurs if the FLAG sequence precedes and * follows each frame. */ if (count == 0) return 1;/* * Generate an error if the frame is too small. */ if (count < PPP_HARD_HDR_LEN) { if (ppp->flags & SC_DEBUG) printk (KERN_WARNING "ppp: got runt ppp frame, %d chars\n", count); slhc_toss (ppp->slcomp); ppp->stats.ppp_ierrors++; return 1; }/* * Verify the CRC of the frame and discard the CRC characters from the * end of the buffer. */ if (ppp->rbuf->fcs != PPP_GOODFCS) { if (ppp->flags & SC_DEBUG) printk (KERN_WARNING "ppp: frame with bad fcs, excess = %x\n", ppp->rbuf->fcs ^ PPP_GOODFCS); ppp->stats.ppp_ierrors++; return 0; } count -= 2; /* ignore the fcs characters *//* * Ignore the leading ADDRESS and CONTROL fields in the frame. */ addr = PPP_ALLSTATIONS; ctrl = PPP_UI; if ((data[0] == PPP_ALLSTATIONS) && (data[1] == PPP_UI)) { data += 2; count -= 2; }/* * Obtain the protocol from the frame */ proto = (__u16) *data++; if ((proto & 1) == 0) { proto = (proto << 8) | (__u16) *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;#ifndef NO_RMK_TEMP_FIX /* * rmk: should make sure that the packet received is on a word boundary. * this is a temporary fix!!! */ if ((int)data & 3) { new_data = kmalloc (ppp->mru + 4, GFP_ATOMIC); /* would like to have 'count' here */ memcpy (new_data, data, count); data = new_data;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -