>> Edit article
이름
제목
패스워드
제가 고친건 아니지만 여기 적수네 동네에서 받은 거 같습니다. 어디서 받았는지 기억이 안나서-_-;; 그냥 올려봅니다. 그럼.. ----------------여기서 자르세요---------------------- --- /dev/null Tue May 5 16:32:27 1998 +++ 2216/drivers/net/pppox.c Sat Feb 19 17:15:46 2000 @@ -0,0 +1,672 @@ +/* + * linux/drivers/net/pppox.c + * + * + * Author: Jamal Hadi Salim (hadi@cyberus.ca) + * + * Initial revision 1999/09/24 (my interpretation of the RFC) + * Partial Rewrite 1999/10/02 (after testing) + * + * Hacked by Andi Kleen <ak@suse.de> in 1999/10/29 for modularization + * and various cleanups. + * + * This driver tries to be a generic PPP over X encapsulator/ + * Decapsulator: + * + * X could imply a lot of things (eg Ethernet in PPPOE, + * ATM in the case PPP over ATM, UDP sockets in the case of L2TP, SONET + * in case of PPP over Sonet,etc). It seems everyone loves PPP + * framing. Small overhead, and can encapsulate multiple protocols. + * + * This code assumes Synchronous PPP framing + * + * Eventually, split this into two parts: A generic part, which should really + * be part of PPP and a "specific" part which is mostly the encapsulation, + * decapsulation and the ioctls. I have tried to comment on the "generic" + * and PPPOE "specific" split. + * + * TODO: + * Introduce a registration API which binds the "specific" part to the + * the generic. + */ + +#include <linux/config.h> +#include <linux/module.h> + +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/tty.h> +#include <linux/tty_flip.h> +#include <linux/fcntl.h> +#include <linux/string.h> +#include <linux/major.h> +#include <linux/mm.h> +#include <linux/init.h> +#include <linux/notifier.h> + +#include <asm/uaccess.h> +#include <asm/system.h> +#include <asm/bitops.h> + +#include <linux/netdevice.h> +#include <linux/skbuff.h> +#include <linux/if_ether.h> + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/init.h> + +#include <linux/devpts_fs.h> +#include <linux/if.h> /* ifreq */ + +#include <linux/ppp_defs.h> + +#include <linux/pppoe.h> + +#define PPPOX_MAJOR 144 +#define PPPOE_MINOR_START 0 /* - 63 for PPPoE */ + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + +int pox_ioctl (struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg); + +static struct packet_type pppoe_packet_type = +{ + __constant_htons(ETH_P_PPP_SES), + NULL, /* All devices */ + pppoe_rcv, + NULL, + NULL +}; + + +static struct tty_struct *pppox_table[N_SES]; +static struct termios *pppox_termios[N_SES]; +static struct termios *pppox_termios_locked[N_SES]; + +static struct tty_driver pppox_driver; +static int pppox_refcount; +static struct pppox_struct pppox_state[N_SES]; + +static int debug; + +/* +* Generic +*/ + +static void pppox_close(struct tty_struct * tty, struct file * filp) +{ + int line; + + if (!tty) + return; + + if (tty->count == 1) + tty->driver_data = 0; + + line = MINOR(tty->device) - tty->driver.minor_start; + if ((unsigned) line > N_SES) { + printk(KERN_DEBUG "pppox_close: bogus line %d", line); + return; + } + + if (--pppox_state[line].counter > 0) { + if (debug > 1) + printk(KERN_DEBUG "pppox_close: not really closing"); + MOD_DEC_USE_COUNT; + return; + } else if (pppox_state[line].counter < 0) { + printk(KERN_DEBUG "pppox_close: bogus counter %d", + pppox_state[line].counter); + return; + } + + if (pppox_state[line].tty == NULL) { + printk(KERN_DEBUG "pppox_close: device already closed"); + return; + } + + start_bh_atomic(); + pppox_state[line].tty=NULL; + pppox_state[line].state=CLOSED; + end_bh_atomic(); + + if (debug>2) + printk(KERN_DEBUG "pppox_close called"); + + MOD_DEC_USE_COUNT; +} + +/* +* Generic +*/ +static void pppox_unthrottle(struct tty_struct * tty) +{ + + if (!tty) + return; + + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + set_bit(TTY_THROTTLED, &tty->flags); +} + +/* +* Half Generic: +* +* The generic part just receives the buffer from PPP +* and passes it to the non-generic part (in this case +* PPPOE). +* +*/ +static int pppoe_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + struct device *etherdev; + struct sk_buff *skb; + int line,c=0; + int i; + int start=0; + + +/* is 0 the best value to return here ? */ + if (!tty || tty->stopped) + return 0; + + line = MINOR(tty->device) - tty->driver.minor_start; + +/* check for inconsistencies */ + if ((pppox_state[line].tty != tty) || (CLOSED == pppox_state[line].state)) { + if (debug > 0) + printk("pppox_write: inconsistent tty or closed tty"); + return -EIO; + } + + if (NULL == pppox_state[line].dev) { + if (debug > 0) + printk("pppox_write: NULL device"); + return -EIO; + } + +#if 0 +/* this is necessarily evil to allow for pppd invocation of pppoed in user +space. pppd passes its initial control data over user space opens ;-> +Later add capabilities stuff */ + if (from_user) { + printk("pppox_write: illegal %d chars from user space",count); + + /* swallow them ;-> */ + return count; + } else { + + c = MIN(count, tty->ldisc.receive_room(tty)); + + + } +#else + c = MIN(count, tty->ldisc.receive_room(tty)); +#endif + + if (c < PPP_HDRLEN) { + printk(" BAD PPP data! length %d",c); + goto printerror; + } + + + if (buf[0] == PPP_FLAG) { + if (buf[1]!=PPP_ALLSTATIONS) + start=1; + else + start=3; + } + + if (buf[0] == PPP_ALLSTATIONS) { + if (buf[1]!=PPP_UI) { + printk("bad data %x",buf[1]); + goto printerror; + } else + start=2; + } + + if (start == 0) + goto printerror; + +#undef PPPOX_DEB +#ifdef PPPOX_DEB + printk("Write START: %d bytes of data ",c); + for (i=0;i<c;i++) { + if (0 == i%8) + printk (" %d:",i); + printk(" %x ",*(buf+i)); + } + printk("Dump END: all data ....."); +#endif + +/* grab the etherdev from the table */ + etherdev=pppox_state[line].dev; + + skb=alloc_skb(PPPOE_HDR_LEN+c+etherdev->hard_header_len,GFP_ATOMIC); + if (skb == NULL) { + printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.", etherdev->name); + return c; + } + + skb->dev = etherdev; + /* for now */ + + skb->mac.raw=skb->data; + skb_reserve(skb,PPPOE_HDR_LEN+etherdev->hard_header_len); + + memcpy(skb_put(skb, c-start),buf+start,c-start); + +/* fix these two below at some point they are wrong */ + skb->priority = 1; + skb->nh.raw=skb->mac.raw+etherdev->hard_header_len; + + skb->protocol=htons(ETH_P_PPP_SES); + + pppox_state[line].x_pppoe_hdr.pppoe.length=htons(c-start); +/* +And finally shove the whole pppoe_hdr +*/ + memcpy(skb_push(skb,sizeof(struct PPPOETHER)),&pppox_state[line].x_pppoe_hdr,sizeof(struct PPPOETHER)); + + + dev_queue_xmit (skb); + + return c; +printerror: + + if (debug > 1) { + printk("Dump START: all data ....."); + for (i=0;i<c;i++) { + if (0 == i%8) + printk (" %d:",i); + printk(" %2x ",*(buf+i)); + } + printk("Dump END: all data ....."); + return c-1; + } + return -1; +} + +/* +* Generic +*/ +static int pppox_write_room(struct tty_struct *tty) +{ + + if (!tty || tty->stopped) + return 0; + + return tty->ldisc.receive_room(tty); +} + +/* +* Generic +*/ +static int pppox_chars_in_buffer(struct tty_struct *tty) +{ + int count; + + if (!tty || !tty->ldisc.chars_in_buffer) + return 0; + + /* The ldisc must report 0 if no characters available to be read */ + count = tty->ldisc.chars_in_buffer(tty); + + return count; +} + +/* +* Generic +*/ + +static void pppox_flush_buffer(struct tty_struct *tty) +{ + + if (!tty) + return; + + if (tty->ldisc.flush_buffer) + tty->ldisc.flush_buffer(tty); + + if (tty->packet) { + tty->ctrl_status |= TIOCPKT_FLUSHWRITE; + wake_up_interruptible(&tty->read_wait); + } +} + +/* +* specific +*/ +int init_PPPOE(int line) +{ + + pppox_state[line].counter = 1; + pppox_state[line].magic=PPPOE_TYPE; + pppox_state[line].x_pppoe_hdr.pppoe.version=1; + pppox_state[line].x_pppoe_hdr.pppoe.type=1; + pppox_state[line].x_pppoe_hdr.pppoe.code=0; + pppox_state[line].x_pppoe_hdr.ether.h_proto=htons(ETH_P_PPP_SES); +/* should be reset everytime we receive data from PPP */ + pppox_state[line].x_pppoe_hdr.pppoe.length=0; + + return 0; + + +} + +/* +* Half Generic +*/ +static int pppox_open(struct tty_struct *tty, struct file * filp) +{ + int retval; + int line; + struct pppox_struct *pppox; + + retval = -ENODEV; + if (!tty) + return retval; + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= N_SES)) + return retval; + + MOD_INC_USE_COUNT; + + if (pppox_state[line].tty) { + pppox_state[line].counter++; + if (debug > 1) + printk(KERN_INFO "pppox_open: line already occupied!"); + return 0; + } + + if (init_PPPOE(line) < 0) { + MOD_DEC_USE_COUNT; + return -EIO; + } + + pppox = (struct pppox_struct *)(tty->driver.driver_state) + line; + tty->driver_data = pppox; + + if (tty->count != 1) { + MOD_DEC_USE_COUNT; + return -EIO; + } + + clear_bit(TTY_OTHER_CLOSED, &tty->flags); + + + pppox_state[line].tty=tty; + pppox_state[line].state=OPENED; + set_bit(TTY_THROTTLED, &tty->flags); + + return 0; +} + +/* +* Generic +*/ +static void pppox_set_termios(struct tty_struct *tty, struct termios *old_termios) +{ + tty->termios->c_cflag &= ~(CSIZE | PARENB); + tty->termios->c_cflag |= (CS8 | CREAD); +} + +static int pox_netdev_notifier(struct notifier_block *this, + unsigned long event, + void *ptr) +{ + struct device *dev = ptr; + int i; + + /* XXX Probably races. */ + if (event != NETDEV_DOWN && event != NETDEV_REBOOT) + return NOTIFY_DONE; + for (i = 0; i < N_SES; i++) { + if (pppox_state[i].dev == dev) { + printk(KERN_INFO "pppoe:%d: device went away from under us", + i); + pppox_state[i].dev = NULL; + } + } + return NOTIFY_DONE; +} + +static struct notifier_block pppox_netdev_notifier = { + pox_netdev_notifier, + NULL, + 0 +}; + +int __init pppox_init(void) +{ + int i; + + memset(&pppox_driver, 0, sizeof(struct tty_driver)); + pppox_driver.magic = TTY_DRIVER_MAGIC; + pppox_driver.driver_name = "pppox"; + pppox_driver.name = "pppox"; + pppox_driver.major = PPPOX_MAJOR; + pppox_driver.minor_start = PPPOE_MINOR_START; + pppox_driver.num = N_SES; + +/* just like the ttyS* */ + + pppox_driver.type = TTY_DRIVER_TYPE_SERIAL; + pppox_driver.subtype = SERIAL_TYPE_NORMAL; + pppox_driver.init_termios = tty_std_termios; + pppox_driver.init_termios.c_iflag = 0; + pppox_driver.init_termios.c_oflag = 0; + pppox_driver.init_termios.c_cflag = CS8 | CREAD; + pppox_driver.init_termios.c_lflag = 0; + pppox_driver.flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW; + pppox_driver.refcount = &pppox_refcount; + pppox_driver.table = pppox_table; + pppox_driver.termios = pppox_termios; + pppox_driver.termios_locked = pppox_termios_locked; + pppox_driver.driver_state = pppox_state; + + pppox_driver.open = pppox_open; + pppox_driver.close = pppox_close; + pppox_driver.write = pppoe_write; + pppox_driver.write_room = pppox_write_room; + pppox_driver.flush_buffer = pppox_flush_buffer; + pppox_driver.chars_in_buffer = pppox_chars_in_buffer; + pppox_driver.unthrottle = pppox_unthrottle; + pppox_driver.set_termios = pppox_set_termios; + pppox_driver.ioctl = pox_ioctl; + + if (tty_register_driver(&pppox_driver)) { + printk(KERN_ERR "Couldn't register pppox driver"); + return -EINVAL; + } + + /* also register the SESSION Ether protocol */ + dev_add_pack(&pppoe_packet_type); + + for (i=0;i<N_SES;i++) { + pppox_state[i].tty=NULL; + } + + printk(KERN_INFO "Registering PPPoE driver"); + + register_netdevice_notifier(&pppox_netdev_notifier); + + return 0; +} + + +/* +* Half generic +*/ +int pppoe_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt) +{ + struct tty_struct *tty=NULL; + struct PPPOEHdr *pppoehdr; + + int i,found=0,length=0; + + pppoehdr=(struct PPPOEHdr *)skb->nh.raw; + + /* XXX: should use a hash table */ + for (i=0;i<N_SES;i++) { + if (pppox_state[i].tty) + if (pppox_state[i].x_pppoe_hdr.pppoe.SessionID == pppoehdr->SessionID) { + found=1; + tty=pppox_state[i].tty; + break; + } + } + + + if (!found || (NULL == tty)) { + /* if (net_ratelimit()) + printk(KERN_INFO "pppoe: discarding packet for session %d, no ppp device waiting", ntohs(pppoehdr->SessionID)); */ + goto error; + } + + length=htons(pppoehdr->length); + + if (length < PPPOE_HDR_LEN) { + goto error; + } + + /* remove the PPPOE headers */ + skb->data=skb_pull(skb,PPPOE_HDR_LEN); + + + tty->ldisc.receive_buf(tty, skb->data, 0, length); + + + kfree_skb(skb); + return 0; + +error: + kfree_skb(skb); + return 0; +} + +static int pox_getarg(struct poe_arg *poe, unsigned long arg) +{ + if (copy_from_user(poe,(void*)arg,sizeof(struct poe_arg))) + return -EFAULT; + if (poe->poe_version != POE_VERSION) { + if (debug > 1) + printk(KERN_DEBUG "pox_getarg: invalid pppoe version"); + return -EINVAL; + } + return 0; +} + +int +pox_ioctl (struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct poe_arg poe; + int err; + int line; + struct pppox_struct *ps; + + if (!tty) { + printk("pox_ioctl called with NULL tty!"); + return -EIO; + } + + switch (cmd) { + case PPPOEIOCSDEV: + case PPPOEIOCSID: + case PPPOEIOCDMAC: + break; + default: + return -ENOIOCTLCMD; + } + + line = MINOR(tty->device) - tty->driver.minor_start; + if (line > N_SES) + return -ENODEV; + + ps = &pppox_state[line]; + + err = pox_getarg(&poe, arg); + if (err) + return err; + +/* some more IOCTLs to add: + delete device, (set state to closed as well) +*/ + + err = 0; + switch (cmd) { + case PPPOEIOCSDEV: { /* Set ethernet device */ + struct device *dev; + + err = -ENODEV; + dev = dev_get_by_index(poe.poe_addr.sll_ifindex); + if (NULL == dev) + break; + start_bh_atomic(); + ps->dev = dev; + memcpy(ps->x_pppoe_hdr.ether.h_source,&dev->dev_addr,ETH_ALEN); + end_bh_atomic(); + err = 0; + break; + } + + case PPPOEIOCSID: + start_bh_atomic(); + ps->x_pppoe_hdr.pppoe.SessionID = poe.poe_session_id; + end_bh_atomic(); + break; + + case PPPOEIOCDMAC: + start_bh_atomic(); + memcpy(ps->x_pppoe_hdr.ether.h_dest, poe.poe_addr.sll_addr, ETH_ALEN); + end_bh_atomic(); + + break; + + default: + /* Should not happen */ + err = -ENOIOCTLCMD; + break; + } + + return err; +} + +MODULE_AUTHOR("Jamal Hadi Salim (hadi@cyberus.ca)"); +MODULE_DESCRIPTION("PPP over Ethernet driver"); +MODULE_PARM(debug, "i"); + +#ifdef MODULE + +int init_module(void) +{ + return pppox_init(); +} + +void cleanup_module(void) +{ + int err; + + printk(KERN_INFO "Removing PPPoE protocol"); + + dev_remove_pack(&pppoe_packet_type); + + printk(KERN_INFO "Removing PPPoE tty driver"); + + err = tty_unregister_driver(&pppox_driver); + if (err < 0) + printk(KERN_DEBUG "pppoe: tty_unregister_driver failed: %d", err); + + unregister_netdevice_notifier(&pppox_netdev_notifier); + + synchronize_bh(); +} +#endif --- 2216-orig/drivers/net/Config.in Tue Jan 4 13:12:17 2000 +++ 2216/drivers/net/Config.in Sat Jan 29 07:48:43 2000 @@ -29,6 +29,11 @@ tristate 'General Instruments Surfboard 1000' CONFIG_NET_SB1000 # +#PPP over X +# +tristate ' tty support for PPP over X ' CONFIG_PPPOX + +# # Ethernet # --- 2216-orig/drivers/net/Makefile Tue Jan 4 13:12:17 2000 +++ 2216/drivers/net/Makefile Sat Jan 29 07:48:43 2000 @@ -1318,6 +1318,17 @@ MOD_IN_SUB_DIRS += irda endif endif +# +#PPPOX +# +ifeq ($(CONFIG_PPPOX),y) +L_OBJS += pppox.o +else + ifeq ($(CONFIG_PPPOX),m) + M_OBJS += pppox.o + endif +endif + ifeq ($(CONFIG_NET_FC),y) SUB_DIRS += fc --- 2216-orig/drivers/char/tty_io.c Tue Jan 4 13:12:15 2000 +++ 2216/drivers/char/tty_io.c Sat Jan 29 07:48:43 2000 @@ -2238,5 +2238,10 @@ #ifdef CONFIG_VT vcs_init(); #endif + +#ifdef CONFIG_PPPOX + pppox_init(); +#endif + return 0; } --- /dev/null Tue May 5 16:32:27 1998 +++ 2216/include/linux/pppoe.h Sat Feb 19 17:10:58 2000 @@ -0,0 +1,67 @@ +#ifndef _LINUX_PPPOE_H +#define _LINUX_PPPOE_H 1 + +#include <linux/pppoe_ioctl.h> +#define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ +#define ETH_P_PPP_SES 0x8864 /* PPPoE session messages */ + +#define PPPOE_HDR_LEN sizeof(struct PPPOEHdr) +#define N_SES 16 + + +/* the session PPPOE header */ + +struct PPPOEHdr { +#if defined(__LITTLE_ENDIAN_BITFIELD) + __u16 version:4, + type:4, + code:8; +#elif defined(__BIG_ENDIAN_BITFIELD) + __u16 code:8, + type:4, + version:4; +#endif + __u16 SessionID; + __u16 length; +}__attribute__ ((packed)); + + +struct PPPOETHER { +struct ethhdr ether; +struct PPPOEHdr pppoe; +} __attribute__ ((packed)); + +#ifdef __KERNEL__ + +extern int pppoe_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt); + +#endif + + + +#define PPPOE_TYPE 1 +#define PPPOATM_TYPE 2 +/* L2TP */ +#define PPPOUDP_TYPE 3 + +#ifdef __KERNEL__ +#define CLOSED 0 +#define OPENED 1 + +struct pppox_struct { + int magic; + struct tty_struct *tty; + struct device *dev; + union { + struct PPPOETHER pppoe_hdr; + } pppox_hdr_ptr; + int state; + int counter; +}; + +#endif + +#define x_pppoe_hdr pppox_hdr_ptr.pppoe_hdr + + +#endif --- /dev/null Tue May 5 16:32:27 1998 +++ 2216/include/linux/pppoe_ioctl.h Sat Jan 29 07:48:43 2000 @@ -0,0 +1,25 @@ +#ifndef __PPPOE_IOCTL_H +#define __PPPOE_IOCTL_H 1 + +#include <linux/if_packet.h> +#include <asm/ioctl.h> + +#ifdef __KERNEL__ +extern int pppoe_ioctl(unsigned int cmd, void *arg); +#endif + +#define POE_VERSION 1 +struct poe_arg { + int poe_version; + int poe_session_id; + struct sockaddr_ll poe_addr; +}; + +/* could probably set most of these in one call */ +#define PPPOEIOCSID _IOW('t',128,struct poe_arg) /* set session ID */ +#define PPPOEIOGSID _IOW('t',129,struct poe_arg) /* get session ID */ +#define PPPOEIOCDMAC _IOW('t',130,struct poe_arg) /* set dst MAC */ +/* set the ethernet device index (in poe_addr.sll_ifindex) */ +#define PPPOEIOCSDEV _IOW('t',131,struct poe_arg) + +#endif --- 2216-orig/include/linux/tty.h Tue Jan 4 13:12:25 2000 +++ 2216/include/linux/tty.h Sat Jan 29 08:12:26 2000 @@ -349,6 +349,7 @@ extern int rs_init(void); extern int lp_init(void); extern int pty_init(void); +extern int pppox_init(void); extern int tty_init(void); extern int mxser_init(void); extern int moxa_init(void); ------------------------여기서 자르세요------------------------ : : 액셀리눅스 6.1 이상의 버전이나 미지리눅스 1.1을 사용해보세요 : : 이미 깔린 상태라면 kernel2.2.13+pppoed0.4 는 필요 없습니다. : : 6.1 버전이면 아마도 2.2.14+pppoed0.47 이 설치되어 있을것입니다. : : 커널이 2.2.13이하를 사용중이시라면 커널소스2.2.16을 받으시고 : : pppoed0.47을 받으셔서 패치하셔서 컴파일하셔야됩니다. : : : : 가장 먼저 자신의 현재 커널버전을 아시는 것이 중요하겠지요. : : 그럼 안녕히 : : : : : ifconfig 로 보면 eth0 가 올라와있는데 연결을 어떻게하죠.. : : : 자료를 뒤져보니 커널 2.2.13 과 pppoed0.4 를 다운받아서 컴파일을 : : : 해야한다고하던데....? : : : : : : 그냥 현상태에서 연결하는 방법좀 알려주세요........? : : : : : : 벌써 두달째.............! : : --------------------- : 문기현님 말씀도 맞지만 전 커널 버젼을 보니까 : 2.2.16커널 패치는 없더군요 : 그래서 해보면 전혀 안될겁니다 : 제말이 틀린지도 모르지만 : 전 ppp0.47tgz를 패치를 아무리 뒤져 보아도 2.2.16패치는 본적이 : 없어서요 : 제가 본 커널 패치는 2038-pppox, 2214-pppox, 2333-pppox : 이종류 입니다 : 그래서 님께서 말씀 하신 2.2.16 패치 화일을 좀 오려 주시면 : 좋겠군요`~ : 그럼
Copyleft
1999-2026 by
JSBoard Open Project
Theme Designed by
IDOO
All right reserved