1 /* 2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and 4 * James Leu (jleu@mindspring.net). 5 * Copyright (C) 2001 by various other people who didn't put their name here. 6 * Licensed under the GPL. 7 */ 8 9 #include <stdint.h> 10 #include <unistd.h> 11 #include <errno.h> 12 #include <sys/types.h> 13 #include <sys/socket.h> 14 #include <sys/time.h> 15 #include <sys/un.h> 16 #include "daemon.h" 17 #include <net_user.h> 18 #include <os.h> 19 #include <um_malloc.h> 20 21 enum request_type { REQ_NEW_CONTROL }; 22 23 #define SWITCH_MAGIC 0xfeedface 24 25 struct request_v3 { 26 uint32_t magic; 27 uint32_t version; 28 enum request_type type; 29 struct sockaddr_un sock; 30 }; 31 32 static struct sockaddr_un *new_addr(void *name, int len) 33 { 34 struct sockaddr_un *sun; 35 36 sun = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); 37 if (sun == NULL) { 38 printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un " 39 "failed\n"); 40 return NULL; 41 } 42 sun->sun_family = AF_UNIX; 43 memcpy(sun->sun_path, name, len); 44 return sun; 45 } 46 47 static int connect_to_switch(struct daemon_data *pri) 48 { 49 struct sockaddr_un *ctl_addr = pri->ctl_addr; 50 struct sockaddr_un *local_addr = pri->local_addr; 51 struct sockaddr_un *sun; 52 struct request_v3 req; 53 int fd, n, err; 54 55 pri->control = socket(AF_UNIX, SOCK_STREAM, 0); 56 if (pri->control < 0) { 57 err = -errno; 58 printk(UM_KERN_ERR "daemon_open : control socket failed, " 59 "errno = %d\n", -err); 60 return err; 61 } 62 63 if (connect(pri->control, (struct sockaddr *) ctl_addr, 64 sizeof(*ctl_addr)) < 0) { 65 err = -errno; 66 printk(UM_KERN_ERR "daemon_open : control connect failed, " 67 "errno = %d\n", -err); 68 goto out; 69 } 70 71 fd = socket(AF_UNIX, SOCK_DGRAM, 0); 72 if (fd < 0) { 73 err = -errno; 74 printk(UM_KERN_ERR "daemon_open : data socket failed, " 75 "errno = %d\n", -err); 76 goto out; 77 } 78 if (bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0) { 79 err = -errno; 80 printk(UM_KERN_ERR "daemon_open : data bind failed, " 81 "errno = %d\n", -err); 82 goto out_close; 83 } 84 85 sun = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); 86 if (sun == NULL) { 87 printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un " 88 "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 = write(pri->control, &req, sizeof(req)); 98 if (n != sizeof(req)) { 99 printk(UM_KERN_ERR "daemon_open : control setup request " 100 "failed, err = %d\n", -errno); 101 err = -ENOTCONN; 102 goto out_free; 103 } 104 105 n = read(pri->control, sun, sizeof(*sun)); 106 if (n != sizeof(*sun)) { 107 printk(UM_KERN_ERR "daemon_open : read of data socket failed, " 108 "err = %d\n", -errno); 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 close(fd); 120 out: 121 close(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 close(pri->fd); 165 pri->fd = -1; 166 close(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 const struct net_user_info daemon_user_info = { 185 .init = daemon_user_init, 186 .open = daemon_open, 187 .close = NULL, 188 .remove = daemon_remove, 189 .add_address = NULL, 190 .delete_address = NULL, 191 .mtu = ETH_MAX_PACKET, 192 .max_packet = ETH_MAX_PACKET + ETH_HEADER_OTHER, 193 }; 194