📄 ppp.c
字号:
/* PPP for Linux * * Michael Callahan <callahan@maths.ox.ac.uk> * Al Longyear <longyear@netcom.com> * * Dynamic PPP devices by Jim Freeman <jfree@caldera.com>. * ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid <ewerlid@syscon.uu.se> * * ==FILEVERSION 970703== * * NOTE TO MAINTAINERS: * If you modify this file at all, please set the number above to the * date of the modification as YYMMDD (year month day). * ppp.c is shipped with a PPP distribution as well as with the kernel; * if everyone increases the FILEVERSION number above, then scripts * can do the right thing when deciding whether to install a new ppp.c * file. Don't change the format of that line otherwise, so the * installation script can recognize it. *//* Sources: slip.c RFC1331: The Point-to-Point Protocol (PPP) for the Transmission of Multi-protocol Datagrams over Point-to-Point Links RFC1332: IPCP ppp-2.0 Flags for this module (any combination is acceptable for testing.): OPTIMIZE_FLAG_TIME - Number of jiffies to force sending of leading flag character. This is normally set to ((HZ * 3) / 2). This is 1.5 seconds. If zero then the leading flag is always sent. CHECK_CHARACTERS - Enable the checking on all received characters for 8 data bits, no parity. This adds a small amount of processing for each received character.*/#define OPTIMIZE_FLAG_TIME ((HZ * 3)/2)#define CHECK_CHARACTERS 1#define PPP_COMPRESS 1#ifndef PPP_MAX_DEV#define PPP_MAX_DEV 256#endif/* $Id: ppp.c,v 1.1.1.1 1999/11/15 13:42:34 vadim Exp $ * Added dynamic allocation of channels to eliminate * compiled-in limits on the number of channels. * * Dynamic channel allocation code Copyright 1995 Caldera, Inc., * released under the GNU General Public License Version 2. */#include <linux/autoconf.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/fcntl.h>#include <linux/interrupt.h>#include <linux/ptrace.h>#include <linux/ioport.h>#include <linux/in.h>#include <linux/malloc.h>#include <linux/tty.h>#include <linux/errno.h>#include <linux/sched.h> /* to get the struct task_struct */#include <linux/string.h> /* used in new tty drivers */#include <linux/signal.h> /* used in new tty drivers */#include <asm/system.h>#include <asm/bitops.h>#include <asm/segment.h>#include <linux/if.h>#include <linux/if_ether.h>#include <linux/netdevice.h>#include <linux/skbuff.h>#include <linux/inet.h>#include <linux/ioctl.h>typedef struct sk_buff sk_buff;#define skb_data(skb) ((__u8 *) (skb)->data)#include <linux/ip.h>#include <linux/tcp.h>#include <linux/if_arp.h>#include <net/slhc_vj.h>#define fcstab ppp_crc16_table /* Name of the table in the kernel */#include <linux/ppp_defs.h>#include <linux/socket.h>#include <linux/if_ppp.h>#include <linux/if_pppvar.h>#undef PACKETPTR#define PACKETPTR 1#include <linux/ppp-comp.h>#undef PACKETPTR#define bsd_decompress (*ppp->sc_rcomp->decompress)#define bsd_compress (*ppp->sc_xcomp->compress)#ifndef PPP_IPX#define PPP_IPX 0x2b /* IPX protocol over PPP */#endif#ifndef PPP_LQR#define PPP_LQR 0xc025 /* Link Quality Reporting Protocol */#endifstatic int ppp_register_compressor (struct compressor *cp);static void ppp_unregister_compressor (struct compressor *cp);/* * Local functions */static struct compressor *find_compressor (int type);static void ppp_init_ctrl_blk (register struct ppp *);static void ppp_kick_tty (struct ppp *, struct ppp_buffer *bfr);static int ppp_doframe (struct ppp *);static struct ppp *ppp_alloc (void);static struct ppp *ppp_find (int pid_value);static void ppp_print_buffer (const __u8 *, const __u8 *, int);extern inline void ppp_stuff_char (struct ppp *ppp, register struct ppp_buffer *buf, register __u8 chr);extern inline int lock_buffer (register struct ppp_buffer *buf);static int rcv_proto_ip (struct ppp *, __u16, __u8 *, int);static int rcv_proto_ipx (struct ppp *, __u16, __u8 *, int);static int rcv_proto_vjc_comp (struct ppp *, __u16, __u8 *, int);static int rcv_proto_vjc_uncomp (struct ppp *, __u16, __u8 *, int);static int rcv_proto_unknown (struct ppp *, __u16, __u8 *, int);static int rcv_proto_lqr (struct ppp *, __u16, __u8 *, int);static void ppp_doframe_lower (struct ppp *, __u8 *, int);static int ppp_doframe (struct ppp *);extern int ppp_bsd_compressor_init(void);static void ppp_proto_ccp (struct ppp *ppp, __u8 *dp, int len, int rcvd);static int rcv_proto_ccp (struct ppp *, __u16, __u8 *, int);#define ins_char(pbuf,c) (buf_base(pbuf) [(pbuf)->count++] = (__u8)(c))#ifndef OPTIMIZE_FLAG_TIME#define OPTIMIZE_FLAG_TIME 0#endif#ifndef PPP_MAX_DEV#define PPP_MAX_DEV 256#endif/* * Parameters which may be changed via insmod. */static int flag_time = OPTIMIZE_FLAG_TIME;static int max_dev = PPP_MAX_DEV;/* * The "main" procedure to the ppp device */int ppp_init (struct device *);/* * Network device driver callback routines */static int ppp_dev_open (struct device *);static int ppp_dev_ioctl (struct device *dev, struct ifreq *ifr, int cmd);static int ppp_dev_close (struct device *);static int ppp_dev_xmit (sk_buff *, struct device *);static struct enet_statistics *ppp_dev_stats (struct device *);static int ppp_dev_header (sk_buff *, struct device *, __u16, void *, void *, unsigned int);static int ppp_dev_rebuild (void *eth, struct device *dev, unsigned long raddr, struct sk_buff *skb);/* * TTY callbacks */static int ppp_tty_read (struct tty_struct *, struct file *, __u8 *, unsigned int);static int ppp_tty_write (struct tty_struct *, struct file *, const __u8 *, unsigned int);static int ppp_tty_ioctl (struct tty_struct *, struct file *, unsigned int, unsigned long);static int ppp_tty_select (struct tty_struct *tty, struct inode *inode, struct file *filp, int sel_type, select_table * wait);static int ppp_tty_open (struct tty_struct *);static void ppp_tty_close (struct tty_struct *);static int ppp_tty_room (struct tty_struct *tty);static void ppp_tty_receive (struct tty_struct *tty, const __u8 * cp, char *fp, int count);static void ppp_tty_wakeup (struct tty_struct *tty);#define CHECK_PPP(a) if (!ppp->inuse) { printk (ppp_warning, __LINE__); return a;}#define CHECK_PPP_VOID() if (!ppp->inuse) { printk (ppp_warning, __LINE__); return;}#define in_xmap(ppp,c) (ppp->xmit_async_map[(c) >> 5] & (1 << ((c) & 0x1f)))#define in_rmap(ppp,c) ((((unsigned int) (__u8) (c)) < 0x20) && \ ppp->recv_async_map & (1 << (c)))#define bset(p,b) ((p)[(b) >> 5] |= (1 << ((b) & 0x1f)))#define tty2ppp(tty) ((struct ppp *) (tty->disc_data))#define dev2ppp(dev) ((struct ppp *) (dev->priv))#define ppp2tty(ppp) ((struct tty_struct *) ppp->tty)#define ppp2dev(ppp) ((struct device *) ppp->dev)struct ppp_hdr { __u8 address; __u8 control; __u8 protocol[2];};#define PPP_HARD_HDR_LEN (sizeof (struct ppp_hdr))typedef struct ppp_ctrl { struct ppp_ctrl *next; /* Next structure in the list */ char name [8]; /* Name of the device */ struct ppp ppp; /* PPP control table */ struct device dev; /* Device information table */} ppp_ctrl_t;static ppp_ctrl_t *ppp_list = NULL;#define ctl2ppp(ctl) (struct ppp *) &ctl->ppp#define ctl2dev(ctl) (struct device *) &ctl->dev#undef PPP_NRUNIT/* Buffer types */#define BUFFER_TYPE_DEV_RD 0 /* ppp read buffer */#define BUFFER_TYPE_TTY_WR 1 /* tty write buffer */#define BUFFER_TYPE_DEV_WR 2 /* ppp write buffer */#define BUFFER_TYPE_TTY_RD 3 /* tty read buffer */#define BUFFER_TYPE_VJ 4 /* vj compression buffer *//* Define this string only once for all macro invocations */static char ppp_warning[] = KERN_WARNING "PPP: ALERT! not INUSE! %d\n";static char szVersion[] = PPP_VERSION; /* * Information for the protocol decoder */typedef int (*pfn_proto) (struct ppp *, __u16, __u8 *, int);typedef struct ppp_proto_struct { int proto; pfn_proto func;} ppp_proto_type;staticppp_proto_type proto_list[] = { { PPP_IP, rcv_proto_ip }, { PPP_IPX, rcv_proto_ipx }, { PPP_VJC_COMP, rcv_proto_vjc_comp }, { PPP_VJC_UNCOMP, rcv_proto_vjc_uncomp }, { PPP_LQR, rcv_proto_lqr }, { PPP_CCP, rcv_proto_ccp }, { 0, rcv_proto_unknown } /* !!! MUST BE LAST !!! */};__u16 ppp_crc16_table[256] ={ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78};#ifdef CHECK_CHARACTERSstatic __u32 paritytab[8] ={ 0x96696996, 0x69969669, 0x69969669, 0x96696996, 0x69969669, 0x96696996, 0x96696996, 0x69969669};#endif/* local function to store a value into the LQR frame */extern inline __u8 * store_long (register __u8 *p, register int value) { *p++ = (__u8) (value >> 24); *p++ = (__u8) (value >> 16); *p++ = (__u8) (value >> 8); *p++ = (__u8) value; return p;}/************************************************************* * INITIALIZATION *************************************************************//* This procedure is called once and once only to define who we are to * the operating system and the various procedures that it may use in * accessing the ppp protocol. */static intppp_first_time (void){ static struct tty_ldisc ppp_ldisc; int status; printk (KERN_INFO "PPP: version %s (dynamic channel allocation)" "\n", szVersion);#ifndef MODULE /* slhc module logic has its own copyright announcement */ printk (KERN_INFO "TCP compression code copyright 1989 Regents of the " "University of California\n");#endif printk (KERN_INFO "PPP Dynamic channel allocation code copyright 1995 " "Caldera, Inc.\n");/* * Register the tty discipline */ (void) memset (&ppp_ldisc, 0, sizeof (ppp_ldisc)); ppp_ldisc.magic = TTY_LDISC_MAGIC; ppp_ldisc.open = ppp_tty_open; ppp_ldisc.close = ppp_tty_close; ppp_ldisc.read = ppp_tty_read; ppp_ldisc.write = ppp_tty_write; ppp_ldisc.ioctl = ppp_tty_ioctl; ppp_ldisc.select = ppp_tty_select; ppp_ldisc.receive_room = ppp_tty_room; ppp_ldisc.receive_buf = ppp_tty_receive; ppp_ldisc.write_wakeup = ppp_tty_wakeup; status = tty_register_ldisc (N_PPP, &ppp_ldisc); if (status == 0) printk (KERN_INFO "PPP line discipline registered.\n"); else printk (KERN_ERR "error registering line discipline: %d\n", status); return status;}/************************************************************* * INITIALIZATION *************************************************************//* called when the device is actually created */static intppp_init_dev (struct device *dev){ int indx; dev->hard_header = ppp_dev_header; dev->rebuild_header = ppp_dev_rebuild; dev->hard_header_len = PPP_HARD_HDR_LEN; /* device INFO */ dev->mtu = PPP_MTU; dev->hard_start_xmit = ppp_dev_xmit; dev->open = ppp_dev_open; dev->stop = ppp_dev_close; dev->get_stats = ppp_dev_stats; dev->do_ioctl = ppp_dev_ioctl; dev->addr_len = 0; dev->tx_queue_len = 10; dev->type = ARPHRD_PPP; for (indx = 0; indx < DEV_NUMBUFFS; indx++) skb_queue_head_init (&dev->buffs[indx]); /* New-style flags */#ifdef IFF_SOFTHEADERS /* Needed to make SOCK_PACKET work correctly in * memory fussy kernels. */ dev->flags = IFF_POINTOPOINT|IFF_SOFTHEADERS;#else dev->flags = IFF_POINTOPOINT;#endif dev->family = AF_INET; dev->pa_addr = 0; dev->pa_brdaddr = 0; dev->pa_mask = 0; dev->pa_alen = 4; /* sizeof (__u32) */ return 0;}/* * Local procedure to initialize the ppp structure */static voidppp_init_ctrl_blk (register struct ppp *ppp){ ppp->magic = PPP_MAGIC; ppp->toss = 0xE0; ppp->escape = 0; ppp->flags = 0; ppp->mtu = PPP_MTU; ppp->mru = PPP_MRU; memset (ppp->xmit_async_map, 0, sizeof (ppp->xmit_async_map)); ppp->xmit_async_map[0] = 0xffffffff; ppp->xmit_async_map[3] = 0x60000000; ppp->recv_async_map = 0x00000000; ppp->rbuf = NULL; ppp->wbuf = NULL; ppp->ubuf = NULL; ppp->cbuf = NULL; ppp->slcomp = NULL; ppp->read_wait = NULL; ppp->write_wait = NULL; ppp->last_xmit = jiffies - flag_time; /* clear statistics */ memset (&ppp->stats, '\0', sizeof (struct pppstat)); /* Reset the demand dial information */ ppp->ddinfo.xmit_idle= /* time since last NP packet sent */ ppp->ddinfo.recv_idle=jiffies; /* time since last NP packet received */ /* PPP compression data */ ppp->sc_xc_state = ppp->sc_rc_state = NULL;}static struct symbol_table ppp_syms = {#include <linux/symtab_begin.h> X(ppp_register_compressor), X(ppp_unregister_compressor), X(ppp_crc16_table),#include <linux/symtab_end.h>};/* called at boot/load time for each ppp device defined in the kernel */#ifndef MODULEintppp_init (struct device *dev){ static int first_time = 1; int answer = 0; if (first_time) { first_time = 0; answer = ppp_first_time(); if (answer == 0) (void) register_symtab (&ppp_syms); } if (answer == 0) answer = -ENODEV; return answer;}#endif/* * Routine to allocate a buffer for later use by the driver. */static struct ppp_buffer *ppp_alloc_buf (int size, int type){ struct ppp_buffer *buf; buf = (struct ppp_buffer *) kmalloc (size + sizeof (struct ppp_buffer), GFP_ATOMIC); if (buf != NULL) { buf->size = size - 1; /* Mask for the buffer size */ buf->type = type; buf->locked = 0; buf->count = 0; buf->head = 0; buf->tail = 0; buf->fcs = PPP_INITFCS; } return (buf);}/* * Routine to release the allocated buffer. */static voidppp_free_buf (struct ppp_buffer *ptr){ if (ptr != NULL) kfree (ptr);}/* * Lock the indicated transmit buffer */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -