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_util.h" 18 #include "user.h" 19 #include "os.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 = um_kmalloc(sizeof(struct sockaddr_un)); 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 printk("daemon_open : control socket failed, errno = %d\n", 59 errno); 60 return(-errno); 61 } 62 63 if(connect(pri->control, (struct sockaddr *) ctl_addr, 64 sizeof(*ctl_addr)) < 0){ 65 printk("daemon_open : control connect failed, errno = %d\n", 66 errno); 67 err = -errno; 68 goto out; 69 } 70 71 fd = socket(AF_UNIX, SOCK_DGRAM, 0); 72 if(fd < 0){ 73 printk("daemon_open : data socket failed, errno = %d\n", 74 errno); 75 err = -errno; 76 goto out; 77 } 78 if(bind(fd, (struct sockaddr *) local_addr, sizeof(*local_addr)) < 0){ 79 printk("daemon_open : data bind failed, errno = %d\n", 80 errno); 81 err = -errno; 82 goto out_close; 83 } 84 85 sun = um_kmalloc(sizeof(struct sockaddr_un)); 86 if(sun == NULL){ 87 printk("new_addr: allocation of sockaddr_un failed\n"); 88 err = -ENOMEM; 89 goto out_close; 90 } 91 92 req.magic = SWITCH_MAGIC; 93 req.version = SWITCH_VERSION; 94 req.type = REQ_NEW_CONTROL; 95 req.sock = *local_addr; 96 n = os_write_file(pri->control, &req, sizeof(req)); 97 if(n != sizeof(req)){ 98 printk("daemon_open : control setup request failed, err = %d\n", 99 -n); 100 err = -ENOTCONN; 101 goto out_free; 102 } 103 104 n = os_read_file(pri->control, sun, sizeof(*sun)); 105 if(n != sizeof(*sun)){ 106 printk("daemon_open : read of data socket failed, err = %d\n", 107 -n); 108 err = -ENOTCONN; 109 goto out_free; 110 } 111 112 pri->data_addr = sun; 113 return(fd); 114 115 out_free: 116 kfree(sun); 117 out_close: 118 os_close_file(fd); 119 out: 120 os_close_file(pri->control); 121 return(err); 122 } 123 124 static void daemon_user_init(void *data, void *dev) 125 { 126 struct daemon_data *pri = data; 127 struct timeval tv; 128 struct { 129 char zero; 130 int pid; 131 int usecs; 132 } name; 133 134 if(!strcmp(pri->sock_type, "unix")) 135 pri->ctl_addr = new_addr(pri->ctl_sock, 136 strlen(pri->ctl_sock) + 1); 137 name.zero = 0; 138 name.pid = os_getpid(); 139 gettimeofday(&tv, NULL); 140 name.usecs = tv.tv_usec; 141 pri->local_addr = new_addr(&name, sizeof(name)); 142 pri->dev = dev; 143 pri->fd = connect_to_switch(pri); 144 if(pri->fd < 0){ 145 kfree(pri->local_addr); 146 pri->local_addr = NULL; 147 } 148 } 149 150 static int daemon_open(void *data) 151 { 152 struct daemon_data *pri = data; 153 return(pri->fd); 154 } 155 156 static void daemon_remove(void *data) 157 { 158 struct daemon_data *pri = data; 159 160 os_close_file(pri->fd); 161 pri->fd = -1; 162 os_close_file(pri->control); 163 pri->control = -1; 164 165 kfree(pri->data_addr); 166 pri->data_addr = NULL; 167 kfree(pri->ctl_addr); 168 pri->ctl_addr = NULL; 169 kfree(pri->local_addr); 170 pri->local_addr = NULL; 171 } 172 173 int daemon_user_write(int fd, void *buf, int len, struct daemon_data *pri) 174 { 175 struct sockaddr_un *data_addr = pri->data_addr; 176 177 return(net_sendto(fd, buf, len, data_addr, sizeof(*data_addr))); 178 } 179 180 static int daemon_set_mtu(int mtu, void *data) 181 { 182 return(mtu); 183 } 184 185 struct net_user_info daemon_user_info = { 186 .init = daemon_user_init, 187 .open = daemon_open, 188 .close = NULL, 189 .remove = daemon_remove, 190 .set_mtu = daemon_set_mtu, 191 .add_address = NULL, 192 .delete_address = NULL, 193 .max_packet = MAX_PACKET - ETH_HEADER_OTHER 194 }; 195 196 /* 197 * Overrides for Emacs so that we follow Linus's tabbing style. 198 * Emacs will notice this stuff at the end of the file and automatically 199 * adjust the settings for this buffer only. This must remain at the end 200 * of the file. 201 * --------------------------------------------------------------------------- 202 * Local variables: 203 * c-file-style: "linux" 204 * End: 205 */ 206