diff -Naur -X exclude-files ac_cur/Documentation/Configure.help ac/Documentation/Configure.help --- ac_cur/Documentation/Configure.help Sat Sep 15 15:56:05 2001 +++ ac/Documentation/Configure.help Sat Sep 15 20:29:05 2001 @@ -13191,6 +13191,16 @@ more than one without conflict. If you don't need UML networking, say N. +TUN/TAP transport +CONFIG_UML_NET_TUNTAP + The UML TUN/TAP network transport allows a UML instance to exchange + packets with the host over a TUN/TAP device. This option will only + work with a 2.4 host, unless you've applied the TUN/TAP patch to + your 2.2 host kernel. + + To use this transport, your host kernel must have support for TUN/TAP + devices, either built-in or as a module. + Multicast transport CONFIG_UML_NET_MCAST This Multicast User-Mode Linux network transport allows multiple diff -Naur -X exclude-files ac_cur/arch/um/config.in ac/arch/um/config.in --- ac_cur/arch/um/config.in Sat Sep 15 19:20:55 2001 +++ ac/arch/um/config.in Sat Sep 15 20:29:05 2001 @@ -85,6 +85,7 @@ bool ' Virtual network device' CONFIG_UML_NET if [ "$CONFIG_UML_NET" != "n" ]; then bool ' Ethertap transport' CONFIG_UML_NET_ETHERTAP + bool ' TUN/TAP transport' CONFIG_UML_NET_TUNTAP bool ' SLIP transport' CONFIG_UML_NET_SLIP bool ' Daemon transport' CONFIG_UML_NET_DAEMON bool ' Multicast transport' CONFIG_UML_NET_MCAST diff -Naur -X exclude-files ac_cur/arch/um/defconfig ac/arch/um/defconfig --- ac_cur/arch/um/defconfig Sat Sep 15 19:20:55 2001 +++ ac/arch/um/defconfig Sat Sep 15 20:29:05 2001 @@ -161,6 +161,7 @@ CONFIG_NETDEVICES=y CONFIG_UML_NET=y CONFIG_UML_NET_ETHERTAP=y +CONFIG_UML_NET_TUNTAP=y CONFIG_UML_NET_SLIP=y CONFIG_UML_NET_DAEMON=y CONFIG_UML_NET_MCAST=y diff -Naur -X exclude-files ac_cur/arch/um/drivers/Makefile ac/arch/um/drivers/Makefile --- ac_cur/arch/um/drivers/Makefile Sat Sep 15 16:46:07 2001 +++ ac/arch/um/drivers/Makefile Sat Sep 15 20:29:05 2001 @@ -19,9 +19,12 @@ CFLAGS_slip_user.o := $(USER_CFLAGS) CFLAGS_ethertap_kern.o := $(CFLAGS) CFLAGS_ethertap_user.o := $(USER_CFLAGS) +CFLAGS_tuntap_kern.o := $(CFLAGS) +CFLAGS_tuntap_user.o := $(USER_CFLAGS) CFLAGS_daemon_kern.o := $(CFLAGS) CFLAGS_daemon_user.o := $(USER_CFLAGS) CFLAGS_net_kern.o := $(CFLAGS) +CFLAGS_net_user.o := $(USER_CFLAGS) CFLAGS_mcast_user.o := $(USER_CFLAGS) CFLAGS_mcast_kern.o := $(CFLAGS) CFLAGS_mconsole_kern.o := $(CFLAGS) @@ -33,9 +36,10 @@ obj-$(CONFIG_SSL) += chan_user.o chan_kern.o obj-$(CONFIG_STDIO_CONSOLE) += chan_user.o chan_kern.o obj-$(CONFIG_BLK_DEV_UBD) += ubd.o ubd_user.o -obj-$(CONFIG_UML_NET) += net_kern.o +obj-$(CONFIG_UML_NET) += net_kern.o net_user.o obj-$(CONFIG_UML_NET_SLIP) += slip_user.o slip_kern.o obj-$(CONFIG_UML_NET_ETHERTAP) += ethertap_user.o ethertap_kern.o +obj-$(CONFIG_UML_NET_TUNTAP) += tuntap_user.o tuntap_kern.o obj-$(CONFIG_UML_NET_DAEMON) += daemon_kern.o daemon_user.o obj-$(CONFIG_UML_NET_MCAST) += mcast_user.o mcast_kern.o obj-$(CONFIG_MCONSOLE) += mconsole_kern.o mconsole_user.o diff -Naur -X exclude-files ac_cur/arch/um/drivers/daemon_kern.c ac/arch/um/drivers/daemon_kern.c --- ac_cur/arch/um/drivers/daemon_kern.c Sat Sep 15 15:56:11 2001 +++ ac/arch/um/drivers/daemon_kern.c Sat Sep 15 20:29:05 2001 @@ -71,10 +71,10 @@ (struct daemon_data *) &lp->user)); } -static int daemon_write(int fd, struct sk_buff *skb, +static int daemon_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) { - return(daemon_user_write(fd, skb->data, skb->len, + return(daemon_user_write(fd, (*skb)->data, (*skb)->len, (struct daemon_data *) &lp->user)); } diff -Naur -X exclude-files ac_cur/arch/um/drivers/etap_kern.h ac/arch/um/drivers/etap_kern.h --- ac_cur/arch/um/drivers/etap_kern.h Sat Sep 15 20:23:31 2001 +++ ac/arch/um/drivers/etap_kern.h Sat Sep 15 20:39:52 2001 @@ -1,3 +1,8 @@ +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + #ifndef __UM_ETHERTAP_KERN_H #define __UM_ETHERTAP_KERN_H @@ -6,3 +11,14 @@ extern void ethertap_setup(char *arg, struct uml_net *dev); #endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Naur -X exclude-files ac_cur/arch/um/drivers/ethertap_kern.c ac/arch/um/drivers/ethertap_kern.c --- ac_cur/arch/um/drivers/ethertap_kern.c Sat Sep 15 15:56:11 2001 +++ ac/arch/um/drivers/ethertap_kern.c Sat Sep 15 20:31:21 2001 @@ -21,17 +21,11 @@ }; struct ethertap_setup ethertap_priv[MAX_UML_NETDEV] = { - { - dev_name: "tap0", - hw_addr: { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - hw_setup: 0, - gate_addr: NULL, - }, - [ 1 ... MAX_UML_NETDEV - 1 ] = + [ 0 ... MAX_UML_NETDEV - 1 ] = { dev_name: NULL, hw_addr: { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - hw_setup: 1, + hw_setup: 0, gate_addr: NULL, } }; @@ -51,7 +45,7 @@ memcpy(dev->dev_addr, ethertap_priv[index].hw_addr, ETH_ALEN); memcpy(epri->hw_addr, ethertap_priv[index].hw_addr, sizeof(epri->hw_addr)); - printk("TAP backend - %s", epri->dev_name); + printk("ethertap backend - %s", epri->dev_name); if(epri->gate_addr != NULL) printk(", IP = %s", epri->gate_addr); epri->hw_setup = ethertap_priv[index].hw_setup; if(epri->hw_setup) @@ -94,18 +88,18 @@ return(len); } -static int etap_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) +static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) { - if(skb_headroom(skb) < 2){ + if(skb_headroom(*skb) < 2){ struct sk_buff *skb2; - skb2 = skb_realloc_headroom(skb, 2); - dev_kfree_skb(skb); + skb2 = skb_realloc_headroom(*skb, 2); + dev_kfree_skb(*skb); if (skb2 == NULL) return(-ENOMEM); - skb = skb2; + *skb = skb2; } - skb_push(skb, 2); - return(etap_user_write(fd, skb->data, skb->len, + skb_push(*skb, 2); + return(etap_user_write(fd, (*skb)->data, (*skb)->len, (struct ethertap_data *) &lp->user)); } @@ -121,29 +115,15 @@ void ethertap_setup(char *str, struct uml_net *dev) { - int err, n = ethertap_count; + struct ethertap_setup *pri; dev->user = ðertap_user_info; dev->kern = ðertap_kern_info; dev->private_size = sizeof(struct ethertap_data); + pri = ðertap_priv[ethertap_count]; dev->transport_index = ethertap_count++; - if(*str != ','){ - printk("ethertap_setup: expected ',' after 'ethertap'\n"); - return; - } - str++; - if(*str != ',') ethertap_priv[n].dev_name = str; - str = strchr(str, ','); - if(str == NULL) return; - *str++ = '\0'; - if(*str != ','){ - err = setup_etheraddr(str, ethertap_priv[n].hw_addr); - if(!err) ethertap_priv[n].hw_setup = 1; - } - str = strchr(str, ','); - if(str == NULL) return; - *str++ = '\0'; - if(*str != '\0') ethertap_priv[n].gate_addr = str; + tap_setup_common(str, "ethertap", &pri->dev_name, pri->hw_addr, + &pri->hw_setup, &pri->gate_addr); } /* diff -Naur -X exclude-files ac_cur/arch/um/drivers/ethertap_user.c ac/arch/um/drivers/ethertap_user.c --- ac_cur/arch/um/drivers/ethertap_user.c Sat Sep 15 15:56:11 2001 +++ ac/arch/um/drivers/ethertap_user.c Sat Sep 15 20:29:05 2001 @@ -14,6 +14,7 @@ #include #include #include +#include #include "user.h" #include "kern_util.h" #include "net_user.h" @@ -31,7 +32,6 @@ struct etap_open_data { char *name; char *gate; - char *addr; int data_remote; int data_me; int control_remote; @@ -39,18 +39,45 @@ int err; }; -void etap_tramp(void *arg) +struct addr_change { + enum { ADD_ADDR, DEL_ADDR } what; + unsigned char addr[4]; +}; + +static void etap_open_addr(unsigned char *addr, void *arg) +{ + int fd = *((int *) arg); + struct addr_change change; + + change.what = ADD_ADDR; + memcpy(change.addr, addr, sizeof(change.addr)); + if(write(fd, &change, sizeof(change)) != sizeof(change)) + printk("etap_add_addr - request failed, errno = %d\n", + errno); +} + +static void etap_close_addr(unsigned char *addr, void *arg) +{ + int fd = *((int *) arg); + struct addr_change change; + + change.what = DEL_ADDR; + memcpy(change.addr, addr, sizeof(change.addr)); + if(write(fd, &change, sizeof(change)) != sizeof(change)) + printk("etap_close_addr - request failed, errno = %d\n", + errno); +} + +static void etap_tramp(void *arg) { struct etap_open_data *data = arg; int pid, status, n; char version_buf[sizeof("nnnnn\0")]; char data_fd_buf[sizeof("nnnnnn\0")]; char control_fd_buf[sizeof("nnnnnn\0")]; - char addr_buf[sizeof("nnn.nnn.nnn.nnn\0")]; char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")], c; char *setup_args[] = { "uml_net", version_buf, "ethertap", data->name, - data_fd_buf, control_fd_buf, gate_buf, - addr_buf, NULL }; + data_fd_buf, control_fd_buf, gate_buf, NULL }; char *nosetup_args[] = { "uml_net", version_buf, "ethertap", data->name, data_fd_buf, control_fd_buf, NULL }; @@ -60,14 +87,13 @@ sprintf(control_fd_buf, "%d", data->control_remote); sprintf(version_buf, "%d", UML_NET_VERSION); if(data->gate != NULL){ - strcpy(addr_buf, data->addr); strcpy(gate_buf, data->gate); args = setup_args; } else args = nosetup_args; data->err = 0; if((pid = fork()) == 0){ - char zero = 0; + char zero = 0; /* XXX Not necessary */ close(data->data_me); close(data->control_me); @@ -77,6 +103,8 @@ exit(errno); } else if(pid < 0) data->err = errno; + close(data->data_remote); + close(data->control_remote); n = read(data->control_me, &c, sizeof(c)); if(n != sizeof(c)){ printk("etap_open - failed to read response from helper : " @@ -91,78 +119,15 @@ else if(c != 1) data->err = EINVAL; } -struct addr_change { - enum { ADD_ADDR, DEL_ADDR } what; - unsigned char addr[4]; -}; - -static void etap_open_addr(unsigned char *addr, void *arg) -{ - int fd = *((int *) arg); - struct addr_change change; - - change.what = ADD_ADDR; - memcpy(change.addr, addr, sizeof(change.addr)); - if(write(fd, &change, sizeof(change)) != sizeof(change)) - printk("etap_add_addr - request failed, errno = %d\n", - errno); -} - -static void etap_close_addr(unsigned char *addr, void *arg) -{ - int fd = *((int *) arg); - struct addr_change change; - - change.what = DEL_ADDR; - memcpy(change.addr, addr, sizeof(change.addr)); - if(write(fd, &change, sizeof(change)) != sizeof(change)) - printk("etap_close_addr - request failed, errno = %d\n", - errno); -} - static int etap_open(void *data) { struct ethertap_data *pri = data; struct etap_open_data tap_data; - int data_fds[2], control_fds[2]; - char addr[sizeof("255.255.255.255\0")], ether[6]; + int data_fds[2], control_fds[2], err; + + err = tap_open_common(pri->dev, pri->hw_setup, pri->gate_addr); + if(err) return(err); - if((pri->gate_addr != NULL) || !pri->hw_setup){ - ether[0] = 0xfe; - ether[1] = 0xfd; - ether[2] = 0x0; - ether[3] = 0x0; - ether[4] = 0x0; - ether[5] = 0x0; - dev_ip_addr(pri->dev, addr, ðer[2]); - } - if(pri->gate_addr != NULL){ - int uml_addr[4], tap_addr[4]; - if(sscanf(addr, "%d.%d.%d.%d", ¨_addr[0], ¨_addr[1], - ¨_addr[2], ¨_addr[3]) != 4){ - printk("Invalid UML IP address - '%s'\n", addr); - return(-EINVAL); - } - if(sscanf(pri->gate_addr, "%d.%d.%d.%d", &tap_addr[0], - &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){ - printk("Invalid tap IP address - '%s'\n", - pri->gate_addr); - return(-EINVAL); - } - if((uml_addr[0] == tap_addr[0]) && - (uml_addr[1] == tap_addr[1]) && - (uml_addr[2] == tap_addr[2]) && - (uml_addr[3] == tap_addr[3])){ - printk("The tap IP address and the UML eth IP address" - " must be different\n"); - return(-EINVAL); - } - } - if(!pri->hw_setup){ - ether[0] = 0xfe; - ether[1] = 0xfd; - set_ether_mac(pri->dev, ether); - } tap_data.name = pri->dev_name; if(socketpair(PF_UNIX, SOCK_DGRAM, 0, data_fds) < 0){ @@ -180,7 +145,6 @@ tap_data.control_me = control_fds[0]; tap_data.gate = pri->gate_addr; - tap_data.addr = addr; tracing_cb(etap_tramp, &tap_data); if(tap_data.err != 0){ printk("etap_tramp failed - errno = %d\n", tap_data.err); @@ -209,10 +173,8 @@ while(((n = recvfrom(fd, buf, len, 0, NULL, NULL)) < 0) && (errno == EINTR)) ; - if(n < 0){ - if(errno == EAGAIN) return(0); - return(-errno); - } + if(errno == EAGAIN) return(0); + if(n < 0) return(-errno); return(n); } diff -Naur -X exclude-files ac_cur/arch/um/drivers/mcast_kern.c ac/arch/um/drivers/mcast_kern.c --- ac_cur/arch/um/drivers/mcast_kern.c Sat Sep 15 15:56:11 2001 +++ ac/arch/um/drivers/mcast_kern.c Sat Sep 15 20:29:05 2001 @@ -83,10 +83,10 @@ (struct mcast_data *) &lp->user); } -static int mcast_write(int fd, struct sk_buff *skb, +static int mcast_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) { - return mcast_user_write(fd, skb->data, skb->len, + return mcast_user_write(fd, (*skb)->data, (*skb)->len, (struct mcast_data *) &lp->user); } diff -Naur -X exclude-files ac_cur/arch/um/drivers/net_kern.c ac/arch/um/drivers/net_kern.c --- ac_cur/arch/um/drivers/net_kern.c Sat Sep 15 15:56:11 2001 +++ ac/arch/um/drivers/net_kern.c Sat Sep 15 20:29:05 2001 @@ -24,6 +24,8 @@ #include "slip_kern.h" #include "etap.h" #include "etap_kern.h" +#include "tuntap.h" +#include "tuntap_kern.h" #include "daemon.h" #include "daemon_kern.h" #include "mcast.h" @@ -74,6 +76,12 @@ return(0); } #endif +#ifdef CONFIG_UML_NET_TUNTAP + if(!strncmp(str, "tuntap", strlen("tuntap"))){ + tuntap_setup(&str[strlen("tuntap")], &devices[n]); + return(0); + } +#endif #ifdef CONFIG_UML_NET_DAEMON if(!strncmp(str, "daemon", strlen("daemon"))){ daemon_setup(&str[strlen("daemon")], &devices[n]); @@ -221,7 +229,7 @@ spin_lock_irqsave(&lp->lock, flags); - len = (*lp->write)(lp->fd, skb, lp); + len = (*lp->write)(lp->fd, &skb, lp); if(len == skb->len) { lp->stats.tx_packets++; @@ -567,6 +575,45 @@ } } +void *get_output_buffer(int *len_out) +{ + void *ret; + + ret = (void *) __get_free_pages(GFP_KERNEL, 0); + if(ret) *len_out = PAGE_SIZE; + else *len_out = 0; + return(ret); +} + +void free_output_buffer(void *buffer) +{ + free_pages((unsigned long) buffer, 0); +} + +void tap_setup_common(char *str, char *type, char **dev_name, char *hw_addr, + int *hw_setup, char **gate_addr) +{ + int err; + + if(*str != ','){ + printk(KERN_ERR + "ethertap_setup: expected ',' after '%s'\n", type); + return; + } + str++; + if(*str != ',') *dev_name = str; + str = strchr(str, ','); + if(str == NULL) return; + *str++ = '\0'; + if(*str != ','){ + err = setup_etheraddr(str, hw_addr); + if(!err) *hw_setup = 1; + } + str = strchr(str, ','); + if(str == NULL) return; + *str++ = '\0'; + if(*str != '\0') *gate_addr = str; +} /* * Overrides for Emacs so that we follow Linus's tabbing style. diff -Naur -X exclude-files ac_cur/arch/um/drivers/net_kern.h ac/arch/um/drivers/net_kern.h --- ac_cur/arch/um/drivers/net_kern.h Sat Sep 15 20:23:31 2001 +++ ac/arch/um/drivers/net_kern.h Sat Sep 15 20:39:52 2001 @@ -28,7 +28,7 @@ int (*open)(void *); void (*close)(int, void *); int (*read)(int, struct sk_buff **skb, struct uml_net_private *); - int (*write)(int, struct sk_buff *skb, struct uml_net_private *); + int (*write)(int, struct sk_buff **skb, struct uml_net_private *); void (*add_address)(unsigned char *, void *); void (*delete_address)(unsigned char *, void *); @@ -41,7 +41,7 @@ unsigned short (*protocol)(struct sk_buff *); int (*set_mac)(struct sockaddr *hwaddr, void *); int (*read)(int, struct sk_buff **skb, struct uml_net_private *); - int (*write)(int, struct sk_buff *skb, struct uml_net_private *); + int (*write)(int, struct sk_buff **skb, struct uml_net_private *); }; extern struct net_device *ether_init(int); @@ -49,6 +49,8 @@ extern int ether_set_mac(struct sockaddr *hwaddr, void *); extern int setup_etheraddr(char *str, unsigned char *addr); extern struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra); +extern void tap_setup_common(char *str, char *type, char **dev_name, + char *hw_addr, int *hw_setup, char **gate_addr); #endif diff -Naur -X exclude-files ac_cur/arch/um/drivers/net_user.c ac/arch/um/drivers/net_user.c --- ac_cur/arch/um/drivers/net_user.c Wed Dec 31 19:00:00 1969 +++ ac/arch/um/drivers/net_user.c Sat Sep 15 20:29:05 2001 @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include "user.h" +#include "net_user.h" + +int tap_open_common(void *dev, int hw_setup, char *gate_addr) +{ + char addr[sizeof("255.255.255.255\0")]; + char ether[ETH_ADDR_LEN]; + + if((gate_addr != NULL) || !hw_setup){ + ether[0] = 0xfe; + ether[1] = 0xfd; + ether[2] = 0x0; + ether[3] = 0x0; + ether[4] = 0x0; + ether[5] = 0x0; + dev_ip_addr(dev, addr, ðer[2]); + } + if(gate_addr != NULL){ + int uml_addr[4], tap_addr[4]; + if(sscanf(addr, "%d.%d.%d.%d", ¨_addr[0], ¨_addr[1], + ¨_addr[2], ¨_addr[3]) != 4){ + printk("Invalid UML IP address - '%s'\n", addr); + return(-EINVAL); + } + if(sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0], + &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4){ + printk("Invalid tap IP address - '%s'\n", + gate_addr); + return(-EINVAL); + } + if((uml_addr[0] == tap_addr[0]) && + (uml_addr[1] == tap_addr[1]) && + (uml_addr[2] == tap_addr[2]) && + (uml_addr[3] == tap_addr[3])){ + printk("The tap IP address and the UML eth IP address" + " must be different\n"); + return(-EINVAL); + } + } + if(!hw_setup){ + ether[0] = 0xfe; + ether[1] = 0xfd; + set_ether_mac(dev, ether); + } + return(0); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Naur -X exclude-files ac_cur/arch/um/drivers/net_user.h ac/arch/um/drivers/net_user.h --- ac_cur/arch/um/drivers/net_user.h Sat Sep 15 15:56:11 2001 +++ ac/arch/um/drivers/net_user.h Sat Sep 15 20:29:05 2001 @@ -6,7 +6,7 @@ #define ETH_HEADER_OTHER (14) #define ETH_MAX_PACKET (1500) -#define UML_NET_VERSION (1) +#define UML_NET_VERSION (2) struct net_user_info { void (*init)(void *, void *); @@ -23,6 +23,11 @@ extern void set_ether_mac(void *d, unsigned char *addr); extern void iter_addresses(void *d, void (*cb)(unsigned char *, void *), void *arg); + +extern void *get_output_buffer(int *len_out); +extern void free_output_buffer(void *buffer); + +extern int tap_open_common(void *dev, int hw_setup, char *gate_addr); #endif diff -Naur -X exclude-files ac_cur/arch/um/drivers/slip_kern.c ac/arch/um/drivers/slip_kern.c --- ac_cur/arch/um/drivers/slip_kern.c Sat Sep 15 15:56:11 2001 +++ ac/arch/um/drivers/slip_kern.c Sat Sep 15 20:29:05 2001 @@ -63,10 +63,10 @@ (struct slip_data *) &lp->user)); } -static int slip_write(int fd, struct sk_buff *skb, +static int slip_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) { - return(slip_user_write(fd, skb->data, skb->len, + return(slip_user_write(fd, (*skb)->data, (*skb)->len, (struct slip_data *) &lp->user)); } diff -Naur -X exclude-files ac_cur/arch/um/drivers/tuntap.h ac/arch/um/drivers/tuntap.h --- ac_cur/arch/um/drivers/tuntap.h Wed Dec 31 19:00:00 1969 +++ ac/arch/um/drivers/tuntap.h Sat Sep 15 20:29:05 2001 @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __UM_TUNTAP_H +#define __UM_TUNTAP_H + +#include "net_user.h" + +struct tuntap_data { + char *dev_name; + char *gate_addr; + int fd; + void *dev; + unsigned char hw_addr[ETH_ADDR_LEN]; + int hw_setup; +}; + +extern struct net_user_info tuntap_user_info; + +extern int tuntap_user_write(int fd, void *buf, int len, + struct tuntap_data *pri); +extern int tuntap_user_read(int fd, void *buf, int len, + struct tuntap_data *pri); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Naur -X exclude-files ac_cur/arch/um/drivers/tuntap_kern.c ac/arch/um/drivers/tuntap_kern.c --- ac_cur/arch/um/drivers/tuntap_kern.c Wed Dec 31 19:00:00 1969 +++ ac/arch/um/drivers/tuntap_kern.c Sat Sep 15 20:29:05 2001 @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/stddef.h" +#include "linux/netdevice.h" +#include "linux/etherdevice.h" +#include "linux/skbuff.h" +#include "asm/errno.h" +#include "net_kern.h" +#include "net_user.h" +#include "tuntap.h" + +struct tuntap_setup { + char *dev_name; + unsigned char hw_addr[ETH_ALEN]; + int hw_setup; + char *gate_addr; +}; + +struct tuntap_setup tuntap_priv[MAX_UML_NETDEV] = { + [ 0 ... MAX_UML_NETDEV - 1 ] = + { + dev_name: NULL, + hw_addr: { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + hw_setup: 0, + gate_addr: NULL, + } +}; + +struct net_device *tuntap_init(int private_size, int index) +{ + struct net_device *dev; + struct uml_net_private *pri; + struct tuntap_data *tpri; + + dev = init_etherdev(NULL, private_size); + if(dev == NULL) return(NULL); + pri = dev->priv; + tpri = (struct tuntap_data *) pri->user; + tpri->dev_name = tuntap_priv[index].dev_name; + tpri->gate_addr = tuntap_priv[index].gate_addr; + memcpy(dev->dev_addr, tuntap_priv[index].hw_addr, ETH_ALEN); + memcpy(tpri->hw_addr, tuntap_priv[index].hw_addr, + sizeof(tpri->hw_addr)); + printk("TUN/TAP backend - "); + if(tpri->gate_addr != NULL) + printk("IP = %s", tpri->gate_addr); + tpri->hw_setup = tuntap_priv[index].hw_setup; + if(tpri->hw_setup) + printk(" ether = %x:%x:%x:%x:%x:%x", + tpri->hw_addr[0], tpri->hw_addr[1], tpri->hw_addr[2], + tpri->hw_addr[3], tpri->hw_addr[4], tpri->hw_addr[5]); + printk("\n"); + tpri->fd = -1; + return(dev); +} + +static unsigned short tuntap_protocol(struct sk_buff *skb) +{ + return(eth_type_trans(skb, skb->dev)); +} + +static int tuntap_set_mac(struct sockaddr *addr, void *data) +{ + struct tuntap_data *pri = data; + struct sockaddr *hwaddr = addr; + + memcpy(pri->hw_addr, hwaddr->sa_data, ETH_ALEN); + + return 0; +} + +static int tuntap_read(int fd, struct sk_buff **skb, + struct uml_net_private *lp) +{ + int len; + + *skb = ether_adjust_skb(*skb, ETH_HEADER_OTHER); + if(*skb == NULL) return(-ENOMEM); + len = tuntap_user_read(fd, (*skb)->mac.raw, + (*skb)->dev->mtu + ETH_HEADER_OTHER, + (struct tuntap_data *) &lp->user); + if(len <= 0) return(len); + return(len); +} + +static int tuntap_write(int fd, struct sk_buff **skb, + struct uml_net_private *lp) +{ + return(tuntap_user_write(fd, (*skb)->data, (*skb)->len, + (struct tuntap_data *) &lp->user)); +} + +struct net_kern_info tuntap_kern_info = { + init: tuntap_init, + protocol: tuntap_protocol, + set_mac: tuntap_set_mac, + read: tuntap_read, + write: tuntap_write, +}; + +static int tuntap_count = 0; + +void tuntap_setup(char *str, struct uml_net *dev) +{ + struct tuntap_setup *pri; + + dev->user = &tuntap_user_info; + dev->kern = &tuntap_kern_info; + dev->user = &tuntap_user_info; + dev->kern = &tuntap_kern_info; + dev->private_size = sizeof(struct tuntap_data); + pri = &tuntap_priv[tuntap_count]; + dev->transport_index = tuntap_count++; + tap_setup_common(str, "tuntap", &pri->dev_name, pri->hw_addr, + &pri->hw_setup, &pri->gate_addr); +} + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Naur -X exclude-files ac_cur/arch/um/drivers/tuntap_kern.h ac/arch/um/drivers/tuntap_kern.h --- ac_cur/arch/um/drivers/tuntap_kern.h Wed Dec 31 19:00:00 1969 +++ ac/arch/um/drivers/tuntap_kern.h Sat Sep 15 20:39:52 2001 @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __UM_TUNTAP_KERN_H +#define __UM_TUNTAP_KERN_H + +#include "net_kern.h" + +extern void tuntap_setup(char *arg, struct uml_net *dev); + +#endif + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Naur -X exclude-files ac_cur/arch/um/drivers/tuntap_user.c ac/arch/um/drivers/tuntap_user.c --- ac_cur/arch/um/drivers/tuntap_user.c Wed Dec 31 19:00:00 1969 +++ ac/arch/um/drivers/tuntap_user.c Sat Sep 15 20:29:05 2001 @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "net_user.h" +#include "tuntap.h" +#include "user.h" +#include "kern_util.h" + +#define MAX_PACKET ETH_MAX_PACKET + +void tuntap_user_init(void *data, void *dev) +{ + struct tuntap_data *pri = data; + + pri->dev = dev; +} + +struct tuntap_open_data { + char *name; + char *gate; + int data_fd; + int remote; + int me; + int err; + char *buffer; + int len; + int used; +}; + +static void tuntap_open_tramp(void *arg) +{ + struct tuntap_open_data *data = arg; + char version_buf[sizeof("nnnnn\0")]; + char fd_buf[sizeof("nnnnnn\0")]; + char *args[] = { "uml_net", version_buf, "tuntap", "up", "", fd_buf, + data->gate, NULL }; + char buf[CMSG_SPACE(sizeof(data->data_fd))]; + struct msghdr msg; + struct cmsghdr *cmsg; + struct iovec iov; + int pid, n; + + sprintf(version_buf, "%d", UML_NET_VERSION); + sprintf(fd_buf, "%d", data->remote); + data->err = 0; + if((pid = fork()) == 0){ + close(data->me); + execvp(args[0], args); + printk("Exec of '%s' failed - errno = %d\n", args[0], errno); + exit(1); + } + else if(pid < 0) data->err = errno; + close(data->remote); + + msg.msg_name = NULL; + msg.msg_namelen = 0; + if(data->buffer != NULL){ + iov = ((struct iovec) { data->buffer, data->len }); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + } + else { + msg.msg_iov = NULL; + msg.msg_iovlen = 0; + } + msg.msg_control = buf; + msg.msg_controllen = sizeof(buf); + msg.msg_flags = 0; + n = recvmsg(data->me, &msg, 0); + data->used = n; + if(n < 0){ + printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", + errno); + data->err = errno; + return; + } + waitpid(pid, NULL, 0); + + cmsg = CMSG_FIRSTHDR(&msg); + if(cmsg == NULL){ + printk("tuntap_open_tramp : didn't receive a message\n"); + data->err = EINVAL; + return; + } + if((cmsg->cmsg_level != SOL_SOCKET) || + (cmsg->cmsg_type != SCM_RIGHTS)){ + printk("tuntap_open_tramp : didn't receive a descriptor\n"); + data->err = EINVAL; + return; + } + data->data_fd = ((int *) CMSG_DATA(cmsg))[0]; +} + +struct tuntap_change_data { + char *dev; + char *what; + char *address; +}; + +static void tuntap_change_tramp(void *arg) +{ + int pid; + struct tuntap_change_data *data = arg; + char version[sizeof("nnnnn\0")]; + char *argv[] = { "uml_net", version, "tuntap", data->what, data->dev, + data->address, NULL }; + + sprintf(version, "%d", UML_NET_VERSION); + if((pid = fork()) == 0){ + execvp(argv[0], argv); + printk("Exec of '%s' failed - errno = %d\n", argv[0], errno); + exit(1); + } + waitpid(pid, NULL, 0); +} + +static void tuntap_change(char *dev, char *what, unsigned char *addr) +{ + char addr_buf[sizeof("255.255.255.255\0")]; + struct tuntap_change_data data; + + data.dev = dev; + data.what = what; + sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); + data.address = addr_buf; + tracing_cb(tuntap_change_tramp, &data); +} + +static void tuntap_open_addr(unsigned char *addr, void *arg) +{ + char *dev = arg; + + tuntap_change(dev, "add", addr); +} + +static void tuntap_close_addr(unsigned char *addr, void *arg) +{ + char *dev = arg; + + tuntap_change(dev, "del", addr); +} + +static void tuntap_add_addr(unsigned char *addr, void *data) +{ + struct tuntap_data *pri = data; + + if(pri->fd == -1) return; + tuntap_open_addr(addr, pri->dev_name); +} + +static void tuntap_del_addr(unsigned char *addr, void *data) +{ + struct tuntap_data *pri = data; + + if(pri->fd == -1) return; + tuntap_close_addr(addr, pri->dev_name); +} + +static int tuntap_open(void *data) +{ + struct tuntap_data *pri = data; + struct tuntap_open_data tap_data; + int err, fds[2]; + + err = tap_open_common(pri->dev, pri->hw_setup, pri->gate_addr); + if(err) return(err); + + if(socketpair(PF_UNIX, SOCK_DGRAM, 0, fds) < 0){ + printk("data socketpair failed - errno = %d\n", errno); + return(-errno); + } + + tap_data.me = fds[0]; + tap_data.remote = fds[1]; + tap_data.data_fd = -1; + tap_data.gate = pri->gate_addr; + tap_data.buffer = get_output_buffer(&tap_data.len); + if(tap_data.buffer != NULL) tap_data.len--; + tap_data.used = 0; + + tracing_cb(tuntap_open_tramp, &tap_data); + if(tap_data.buffer != NULL){ + pri->dev_name = uml_strdup(tap_data.buffer); + tap_data.buffer[tap_data.used] = '\0'; + printk(tap_data.buffer + IFNAMSIZ); + free_output_buffer(tap_data.buffer); + } + if(tap_data.err != 0){ + printk("tuntap_open_tramp failed - errno = %d\n", + tap_data.err); + return(-tap_data.err); + } + close(fds[0]); + + pri->fd = tap_data.data_fd; + iter_addresses(pri->dev, tuntap_open_addr, pri->dev_name); + return(tap_data.data_fd); +} + +static void tuntap_close(int fd, void *data) +{ + struct tuntap_data *pri = data; + + iter_addresses(pri->dev, tuntap_close_addr, pri->dev_name); + close(fd); +} + +int tuntap_user_read(int fd, void *buf, int len, struct tuntap_data *pri) +{ + int n; + + while(((n = read(fd, buf, len)) < 0) && (errno == EINTR)) ; + if(errno == EAGAIN) return(0); + if(n < 0) return(-errno); + return(n); +} + +int tuntap_user_write(int fd, void *buf, int len, struct tuntap_data *pri) +{ + int n; + + while(((n = write(fd, buf, len)) < 0) && (errno == EINTR)) ; + if(errno == EAGAIN) n = 0; + if(n < 0) return(-errno); + return(n); +} + +static int tuntap_set_mtu(int mtu, void *data) +{ + return(mtu); +} + +struct net_user_info tuntap_user_info = { + init: tuntap_user_init, + open: tuntap_open, + close: tuntap_close, + set_mtu: tuntap_set_mtu, + add_address: tuntap_add_addr, + delete_address: tuntap_del_addr, + max_packet: MAX_PACKET +}; + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ diff -Naur -X exclude-files ac_cur/arch/um/kernel/smp.c ac/arch/um/kernel/smp.c --- ac_cur/arch/um/kernel/smp.c Sat Sep 15 15:56:11 2001 +++ ac/arch/um/kernel/smp.c Sat Sep 15 20:41:23 2001 @@ -3,10 +3,12 @@ * Licensed under the GPL */ +#ifdef CONFIG_SMP + #include "linux/config.h" #include "linux/sched.h" #include "linux/threads.h" -#include "asm/smp.h" +#include "linux/smp.h" #include "asm/processor.h" #include "asm/spinlock.h" #include "asm/softirq.h" @@ -15,8 +17,6 @@ #include "kern_util.h" #include "kern.h" -#ifdef CONFIG_SMP - /* Total count of live CPUs */ int smp_num_cpus = 0; @@ -108,8 +108,6 @@ return(0); } -#endif - int inited_cpus = 1; int pid_to_processor_id(int pid) @@ -123,7 +121,6 @@ return(-1); } -#ifdef CONFIG_SMP int hard_smp_processor_id(void) { return(pid_to_processor_id(getpid())); diff -Naur -X exclude-files ac_cur/include/asm-um/hardirq.h ac/include/asm-um/hardirq.h --- ac_cur/include/asm-um/hardirq.h Sat Sep 15 20:32:55 2001 +++ ac/include/asm-um/hardirq.h Sat Sep 15 20:35:46 2001 @@ -2,7 +2,6 @@ #define __UM_HARDIRQ_H #include "linux/spinlock.h" -#include "asm/smp.h" #include "asm/arch/hardirq.h" #endif