1 /* 2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and 3 * James Leu (jleu@mindspring.net). 4 * Copyright (C) 2001 by various other people who didn't put their name here. 5 * Licensed under the GPL. 6 */ 7 8 #include <errno.h> 9 #include <unistd.h> 10 #include <stdint.h> 11 #include <sys/socket.h> 12 #include <sys/un.h> 13 #include <sys/time.h> 14 #include "net_user.h" 15 #include "daemon.h" 16 #include "kern_util.h" 17 #include "user.h" 18 #include "os.h" 19 #include "um_malloc.h" 20 21 #define MAX_PACKET (ETH_MAX_PACKET + ETH_HEADER_OTHER) 22 23 enum request_type { REQ_NEW_CONTROL }; 24 25 #define SWITCH_MAGIC 0xfeedface 26 27 struct request_v3 { 28 uint32_t magic; 29 uint32_t version; 30 enum request_type type; 31 struct sockaddr_un sock; 32 }; 33 34 static struct sockaddr_un *new_addr(void *name, int len) 35 { 36 struct sockaddr_un *sun; 37 38 sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); 39 if(sun == NULL){ 40 printk("new_addr: allocation of sockaddr_un failed\n"); 41 return NULL; 42 } 43 sun->sun_family = AF_UNIX; 44 memcpy(sun->sun_path, name, len); 45 return sun; 46 } 47 48 static int connect_to_switch(struct daemon_data *pri) 49 { 50 struct sockaddr_un *ctl_addr = pri->ctl_addr; 51 struct sockaddr_un *local_addr = pri->local_addr; 52 struct sockaddr_un *sun; 53 struct request_v3 req; 54 int fd, n, err; 55 56 pri->control = socket(AF_UNIX, SOCK_STREAM, 0); 57 if(pri->control < 0){ 58 err = -errno; 59 printk("daemon_open : control socket failed, errno = %d\n", 60 -err); 61 return err; 62 } 63 64 if(connect(pri->control, (struct sockaddr *) ctl_addr, 65 sizeof(*ctl_addr)) < 0){ 66 err = -errno; 67 printk("daemon_open : control connect failed, errno = %d\n", 68 -err); 69 goto out; 70 } 71 72 fd = socket(AF_UNIX, SOCK_DGRAM, 0); 73 if(fd < 0){ 74 err = -errno; 75 printk("daemon_open : data socket failed, errno = %d\n", 76 -err); 77 goto out; 78 } 79 if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){ 80 err = -errno; 81 printk("daemon_open : data bind failed, errno = %d\n", 82 -err); 83 goto out_close; 84 } 85 86 sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); 87 if(sun == NULL){ 88 printk("new_addr: allocation of sockaddr_un failed\n"); 89 err = -ENOMEM; 90 goto out_close; 91 } 92 93 req.magic = SWITCH_MAGIC; 94 req.version = SWITCH_VERSION; 95 req.type = REQ_NEW_CONTROL; 96 req.sock = *local_addr; 97 n = os_write_file(pri->control, &req, sizeof(req)); 98 if(n != sizeof(req)){ 99 printk("daemon_open : control setup request failed, err = %d\n", 100 -n); 101 err = -ENOTCONN; 102 goto out_free; 103 } 104 105 n = os_read_file(pri->control, sun, sizeof(*sun)); 106 if(n != sizeof(*sun)){ 107 printk("daemon_open : read of data socket failed, err = %d\n", 108 -n); 109 err = -ENOTCONN; 110 goto out_free; 111 } 112 113 pri->data_addr = sun; 114 return fd; 115 116 out_free: 117 kfree(sun); 118 out_close: 119 os_close_file(fd); 120 out: 121 os_close_file(pri->control); 122 return err; 123 } 124 125 static int daemon_user_init(void *data, void *dev) 126 { 127 struct daemon_data *pri = data; 128 struct timeval tv; 129 struct { 130 char zero; 131 int pid; 132 int usecs; 133 } name; 134 135 if(!strcmp(pri->sock_type, "unix")) 136 pri->ctl_addr = new_addr(pri->ctl_sock, 137 strlen(pri->ctl_sock) + 1); 138 name.zero = 0; 139 name.pid = os_getpid(); 140 gettimeofday(&tv, NULL); 141 name.usecs = tv.tv_usec; 142 pri->local_addr = new_addr(&name, sizeof(name)); 143 pri->dev = dev; 144 pri->fd = connect_to_switch(pri); 145 if(pri->fd < 0){ 146 kfree(pri->local_addr); 147 pri->local_addr = NULL; 148 return pri->fd; 149 } 150 151 return 0; 152 } 153 154 static int daemon_open(void *data) 155 { 156 struct daemon_data *pri = data; 157 return pri->fd; 158 } 159 160 static void daemon_remove(void *data) 161 { 162 struct daemon_data *pri = data; 163 164 os_close_file(pri->fd); 165 pri->fd = -1; 166 os_close_file(pri->control); 167 pri->control = -1; 168 169 kfree(pri->data_addr); 170 pri->data_addr = NULL; 171 kfree(pri->ctl_addr); 172 pri->ctl_addr = NULL; 173 kfree(pri->local_addr); 174 pri->local_addr = NULL; 175 } 176 177 int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) 178 { 179 struct sockaddr_un *data_addr = pri->data_addr; 180 181 return net_sendto(fd, buf, len, data_addr, sizeof(*data_addr)); 182 } 183 184 static int daemon_set_mtu(int mtu, void *data) 185 { 186 return mtu; 187 } 188 189 const struct net_user_info daemon_user_info = { 190 .init = daemon_user_init, 191 .open = daemon_open, 192 .close = NULL, 193 .remove = daemon_remove, 194 .set_mtu = daemon_set_mtu, 195 .add_address = NULL, 196 .delete_address = NULL, 197 .max_packet = MAX_PACKET - ETH_HEADER_OTHER 198 }; 199