root/arch/um/drivers/daemon_user.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. new_addr
  2. connect_to_switch
  3. daemon_user_init
  4. daemon_open
  5. daemon_remove
  6. daemon_user_write

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   4  * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and
   5  * James Leu (jleu@mindspring.net).
   6  * Copyright (C) 2001 by various other people who didn't put their name here.
   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 };

/* [<][>][^][v][top][bottom][index][help] */