Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.20-rc7 228 lines 5.1 kB view raw
1/* 2 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) 3 * Licensed under the GPL 4 */ 5 6#include <stdio.h> 7#include <stddef.h> 8#include <stdlib.h> 9#include <unistd.h> 10#include <errno.h> 11#include <sys/wait.h> 12#include <sys/socket.h> 13#include <sys/un.h> 14#include <sys/uio.h> 15#include <sys/ioctl.h> 16#include <net/if.h> 17#include <linux/if_tun.h> 18#include "net_user.h" 19#include "tuntap.h" 20#include "kern_util.h" 21#include "user_util.h" 22#include "user.h" 23#include "os.h" 24 25#define MAX_PACKET ETH_MAX_PACKET 26 27void tuntap_user_init(void *data, void *dev) 28{ 29 struct tuntap_data *pri = data; 30 31 pri->dev = dev; 32} 33 34static void tuntap_add_addr(unsigned char *addr, unsigned char *netmask, 35 void *data) 36{ 37 struct tuntap_data *pri = data; 38 39 tap_check_ips(pri->gate_addr, addr); 40 if((pri->fd == -1) || pri->fixed_config) return; 41 open_addr(addr, netmask, pri->dev_name); 42} 43 44static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask, 45 void *data) 46{ 47 struct tuntap_data *pri = data; 48 49 if((pri->fd == -1) || pri->fixed_config) return; 50 close_addr(addr, netmask, pri->dev_name); 51} 52 53struct tuntap_pre_exec_data { 54 int stdout; 55 int close_me; 56}; 57 58static void tuntap_pre_exec(void *arg) 59{ 60 struct tuntap_pre_exec_data *data = arg; 61 62 dup2(data->stdout, 1); 63 os_close_file(data->close_me); 64} 65 66static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, 67 char *buffer, int buffer_len, int *used_out) 68{ 69 struct tuntap_pre_exec_data data; 70 char version_buf[sizeof("nnnnn\0")]; 71 char *argv[] = { "uml_net", version_buf, "tuntap", "up", gate, 72 NULL }; 73 char buf[CMSG_SPACE(sizeof(*fd_out))]; 74 struct msghdr msg; 75 struct cmsghdr *cmsg; 76 struct iovec iov; 77 int pid, n, err; 78 79 sprintf(version_buf, "%d", UML_NET_VERSION); 80 81 data.stdout = remote; 82 data.close_me = me; 83 84 pid = run_helper(tuntap_pre_exec, &data, argv, NULL); 85 86 if(pid < 0) return(-pid); 87 88 os_close_file(remote); 89 90 msg.msg_name = NULL; 91 msg.msg_namelen = 0; 92 if(buffer != NULL){ 93 iov = ((struct iovec) { buffer, buffer_len }); 94 msg.msg_iov = &iov; 95 msg.msg_iovlen = 1; 96 } 97 else { 98 msg.msg_iov = NULL; 99 msg.msg_iovlen = 0; 100 } 101 msg.msg_control = buf; 102 msg.msg_controllen = sizeof(buf); 103 msg.msg_flags = 0; 104 n = recvmsg(me, &msg, 0); 105 *used_out = n; 106 if(n < 0){ 107 err = -errno; 108 printk("tuntap_open_tramp : recvmsg failed - errno = %d\n", 109 errno); 110 return err; 111 } 112 CATCH_EINTR(waitpid(pid, NULL, 0)); 113 114 cmsg = CMSG_FIRSTHDR(&msg); 115 if(cmsg == NULL){ 116 printk("tuntap_open_tramp : didn't receive a message\n"); 117 return(-EINVAL); 118 } 119 if((cmsg->cmsg_level != SOL_SOCKET) || 120 (cmsg->cmsg_type != SCM_RIGHTS)){ 121 printk("tuntap_open_tramp : didn't receive a descriptor\n"); 122 return(-EINVAL); 123 } 124 *fd_out = ((int *) CMSG_DATA(cmsg))[0]; 125 os_set_exec_close(*fd_out, 1); 126 return(0); 127} 128 129static int tuntap_open(void *data) 130{ 131 struct ifreq ifr; 132 struct tuntap_data *pri = data; 133 char *output, *buffer; 134 int err, fds[2], len, used; 135 136 err = tap_open_common(pri->dev, pri->gate_addr); 137 if(err < 0) 138 return(err); 139 140 if(pri->fixed_config){ 141 pri->fd = os_open_file("/dev/net/tun", 142 of_cloexec(of_rdwr(OPENFLAGS())), 0); 143 if(pri->fd < 0){ 144 printk("Failed to open /dev/net/tun, err = %d\n", 145 -pri->fd); 146 return(pri->fd); 147 } 148 memset(&ifr, 0, sizeof(ifr)); 149 ifr.ifr_flags = IFF_TAP | IFF_NO_PI; 150 strlcpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name)); 151 if(ioctl(pri->fd, TUNSETIFF, (void *) &ifr) < 0){ 152 err = -errno; 153 printk("TUNSETIFF failed, errno = %d\n", errno); 154 os_close_file(pri->fd); 155 return err; 156 } 157 } 158 else { 159 err = os_pipe(fds, 0, 0); 160 if(err < 0){ 161 printk("tuntap_open : os_pipe failed - err = %d\n", 162 -err); 163 return(err); 164 } 165 166 buffer = get_output_buffer(&len); 167 if(buffer != NULL) len--; 168 used = 0; 169 170 err = tuntap_open_tramp(pri->gate_addr, &pri->fd, fds[0], 171 fds[1], buffer, len, &used); 172 173 output = buffer; 174 if(err < 0) { 175 printk("%s", output); 176 free_output_buffer(buffer); 177 printk("tuntap_open_tramp failed - err = %d\n", -err); 178 return(err); 179 } 180 181 pri->dev_name = uml_strdup(buffer); 182 output += IFNAMSIZ; 183 printk("%s", output); 184 free_output_buffer(buffer); 185 186 os_close_file(fds[0]); 187 iter_addresses(pri->dev, open_addr, pri->dev_name); 188 } 189 190 return(pri->fd); 191} 192 193static void tuntap_close(int fd, void *data) 194{ 195 struct tuntap_data *pri = data; 196 197 if(!pri->fixed_config) 198 iter_addresses(pri->dev, close_addr, pri->dev_name); 199 os_close_file(fd); 200 pri->fd = -1; 201} 202 203static int tuntap_set_mtu(int mtu, void *data) 204{ 205 return(mtu); 206} 207 208const struct net_user_info tuntap_user_info = { 209 .init = tuntap_user_init, 210 .open = tuntap_open, 211 .close = tuntap_close, 212 .remove = NULL, 213 .set_mtu = tuntap_set_mtu, 214 .add_address = tuntap_add_addr, 215 .delete_address = tuntap_del_addr, 216 .max_packet = MAX_PACKET 217}; 218 219/* 220 * Overrides for Emacs so that we follow Linus's tabbing style. 221 * Emacs will notice this stuff at the end of the file and automatically 222 * adjust the settings for this buffer only. This must remain at the end 223 * of the file. 224 * --------------------------------------------------------------------------- 225 * Local variables: 226 * c-file-style: "linux" 227 * End: 228 */