root/arch/um/drivers/slip_user.c

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

DEFINITIONS

This source file includes following definitions.
  1. slip_user_init
  2. set_up_tty
  3. slip_pre_exec
  4. slip_tramp
  5. slip_open
  6. slip_close
  7. slip_user_read
  8. slip_user_write
  9. slip_add_addr
  10. slip_del_addr

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   4  */
   5 
   6 #include <stdio.h>
   7 #include <stdlib.h>
   8 #include <unistd.h>
   9 #include <errno.h>
  10 #include <fcntl.h>
  11 #include <string.h>
  12 #include <sys/termios.h>
  13 #include <sys/wait.h>
  14 #include <net_user.h>
  15 #include <os.h>
  16 #include "slip.h"
  17 #include <um_malloc.h>
  18 
  19 static int slip_user_init(void *data, void *dev)
  20 {
  21         struct slip_data *pri = data;
  22 
  23         pri->dev = dev;
  24         return 0;
  25 }
  26 
  27 static int set_up_tty(int fd)
  28 {
  29         int i;
  30         struct termios tios;
  31 
  32         if (tcgetattr(fd, &tios) < 0) {
  33                 printk(UM_KERN_ERR "could not get initial terminal "
  34                        "attributes\n");
  35                 return -1;
  36         }
  37 
  38         tios.c_cflag = CS8 | CREAD | HUPCL | CLOCAL;
  39         tios.c_iflag = IGNBRK | IGNPAR;
  40         tios.c_oflag = 0;
  41         tios.c_lflag = 0;
  42         for (i = 0; i < NCCS; i++)
  43                 tios.c_cc[i] = 0;
  44         tios.c_cc[VMIN] = 1;
  45         tios.c_cc[VTIME] = 0;
  46 
  47         cfsetospeed(&tios, B38400);
  48         cfsetispeed(&tios, B38400);
  49 
  50         if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
  51                 printk(UM_KERN_ERR "failed to set terminal attributes\n");
  52                 return -1;
  53         }
  54         return 0;
  55 }
  56 
  57 struct slip_pre_exec_data {
  58         int stdin_fd;
  59         int stdout_fd;
  60         int close_me;
  61 };
  62 
  63 static void slip_pre_exec(void *arg)
  64 {
  65         struct slip_pre_exec_data *data = arg;
  66 
  67         if (data->stdin_fd >= 0)
  68                 dup2(data->stdin_fd, 0);
  69         dup2(data->stdout_fd, 1);
  70         if (data->close_me >= 0)
  71                 close(data->close_me);
  72 }
  73 
  74 static int slip_tramp(char **argv, int fd)
  75 {
  76         struct slip_pre_exec_data pe_data;
  77         char *output;
  78         int pid, fds[2], err, output_len;
  79 
  80         err = os_pipe(fds, 1, 0);
  81         if (err < 0) {
  82                 printk(UM_KERN_ERR "slip_tramp : pipe failed, err = %d\n",
  83                        -err);
  84                 goto out;
  85         }
  86 
  87         err = 0;
  88         pe_data.stdin_fd = fd;
  89         pe_data.stdout_fd = fds[1];
  90         pe_data.close_me = fds[0];
  91         err = run_helper(slip_pre_exec, &pe_data, argv);
  92         if (err < 0)
  93                 goto out_close;
  94         pid = err;
  95 
  96         output_len = UM_KERN_PAGE_SIZE;
  97         output = uml_kmalloc(output_len, UM_GFP_KERNEL);
  98         if (output == NULL) {
  99                 printk(UM_KERN_ERR "slip_tramp : failed to allocate output "
 100                        "buffer\n");
 101                 os_kill_process(pid, 1);
 102                 err = -ENOMEM;
 103                 goto out_close;
 104         }
 105 
 106         close(fds[1]);
 107         read_output(fds[0], output, output_len);
 108         printk("%s", output);
 109 
 110         err = helper_wait(pid);
 111         close(fds[0]);
 112 
 113         kfree(output);
 114         return err;
 115 
 116 out_close:
 117         close(fds[0]);
 118         close(fds[1]);
 119 out:
 120         return err;
 121 }
 122 
 123 static int slip_open(void *data)
 124 {
 125         struct slip_data *pri = data;
 126         char version_buf[sizeof("nnnnn\0")];
 127         char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
 128         char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf,
 129                          NULL };
 130         int sfd, mfd, err;
 131 
 132         err = get_pty();
 133         if (err < 0) {
 134                 printk(UM_KERN_ERR "slip-open : Failed to open pty, err = %d\n",
 135                        -err);
 136                 goto out;
 137         }
 138         mfd = err;
 139 
 140         err = open(ptsname(mfd), O_RDWR, 0);
 141         if (err < 0) {
 142                 printk(UM_KERN_ERR "Couldn't open tty for slip line, "
 143                        "err = %d\n", -err);
 144                 goto out_close;
 145         }
 146         sfd = err;
 147 
 148         if (set_up_tty(sfd))
 149                 goto out_close2;
 150 
 151         pri->slave = sfd;
 152         pri->slip.pos = 0;
 153         pri->slip.esc = 0;
 154         if (pri->gate_addr != NULL) {
 155                 sprintf(version_buf, "%d", UML_NET_VERSION);
 156                 strcpy(gate_buf, pri->gate_addr);
 157 
 158                 err = slip_tramp(argv, sfd);
 159 
 160                 if (err < 0) {
 161                         printk(UM_KERN_ERR "slip_tramp failed - err = %d\n",
 162                                -err);
 163                         goto out_close2;
 164                 }
 165                 err = os_get_ifname(pri->slave, pri->name);
 166                 if (err < 0) {
 167                         printk(UM_KERN_ERR "get_ifname failed, err = %d\n",
 168                                -err);
 169                         goto out_close2;
 170                 }
 171                 iter_addresses(pri->dev, open_addr, pri->name);
 172         }
 173         else {
 174                 err = os_set_slip(sfd);
 175                 if (err < 0) {
 176                         printk(UM_KERN_ERR "Failed to set slip discipline "
 177                                "encapsulation - err = %d\n", -err);
 178                         goto out_close2;
 179                 }
 180         }
 181         return mfd;
 182 out_close2:
 183         close(sfd);
 184 out_close:
 185         close(mfd);
 186 out:
 187         return err;
 188 }
 189 
 190 static void slip_close(int fd, void *data)
 191 {
 192         struct slip_data *pri = data;
 193         char version_buf[sizeof("nnnnn\0")];
 194         char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name,
 195                          NULL };
 196         int err;
 197 
 198         if (pri->gate_addr != NULL)
 199                 iter_addresses(pri->dev, close_addr, pri->name);
 200 
 201         sprintf(version_buf, "%d", UML_NET_VERSION);
 202 
 203         err = slip_tramp(argv, pri->slave);
 204 
 205         if (err != 0)
 206                 printk(UM_KERN_ERR "slip_tramp failed - errno = %d\n", -err);
 207         close(fd);
 208         close(pri->slave);
 209         pri->slave = -1;
 210 }
 211 
 212 int slip_user_read(int fd, void *buf, int len, struct slip_data *pri)
 213 {
 214         return slip_proto_read(fd, buf, len, &pri->slip);
 215 }
 216 
 217 int slip_user_write(int fd, void *buf, int len, struct slip_data *pri)
 218 {
 219         return slip_proto_write(fd, buf, len, &pri->slip);
 220 }
 221 
 222 static void slip_add_addr(unsigned char *addr, unsigned char *netmask,
 223                           void *data)
 224 {
 225         struct slip_data *pri = data;
 226 
 227         if (pri->slave < 0)
 228                 return;
 229         open_addr(addr, netmask, pri->name);
 230 }
 231 
 232 static void slip_del_addr(unsigned char *addr, unsigned char *netmask,
 233                             void *data)
 234 {
 235         struct slip_data *pri = data;
 236 
 237         if (pri->slave < 0)
 238                 return;
 239         close_addr(addr, netmask, pri->name);
 240 }
 241 
 242 const struct net_user_info slip_user_info = {
 243         .init           = slip_user_init,
 244         .open           = slip_open,
 245         .close          = slip_close,
 246         .remove         = NULL,
 247         .add_address    = slip_add_addr,
 248         .delete_address = slip_del_addr,
 249         .mtu            = BUF_SIZE,
 250         .max_packet     = BUF_SIZE,
 251 };

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