1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 4 */ 5 6 #include <unistd.h> 7 #include <errno.h> 8 #include <string.h> 9 #include <sys/wait.h> 10 #include <net_user.h> 11 #include <os.h> 12 #include "slirp.h" 13 14 static int slirp_user_init(void *data, void *dev) 15 { 16 struct slirp_data *pri = data; 17 18 pri->dev = dev; 19 return 0; 20 } 21 22 struct slirp_pre_exec_data { 23 int stdin_fd; 24 int stdout_fd; 25 }; 26 27 static void slirp_pre_exec(void *arg) 28 { 29 struct slirp_pre_exec_data *data = arg; 30 31 if (data->stdin_fd != -1) 32 dup2(data->stdin_fd, 0); 33 if (data->stdout_fd != -1) 34 dup2(data->stdout_fd, 1); 35 } 36 37 static int slirp_tramp(char **argv, int fd) 38 { 39 struct slirp_pre_exec_data pe_data; 40 int pid; 41 42 pe_data.stdin_fd = fd; 43 pe_data.stdout_fd = fd; 44 pid = run_helper(slirp_pre_exec, &pe_data, argv); 45 46 return pid; 47 } 48 49 static int slirp_open(void *data) 50 { 51 struct slirp_data *pri = data; 52 int fds[2], err; 53 54 err = os_pipe(fds, 1, 1); 55 if (err) 56 return err; 57 58 err = slirp_tramp(pri->argw.argv, fds[1]); 59 if (err < 0) { 60 printk(UM_KERN_ERR "slirp_tramp failed - errno = %d\n", -err); 61 goto out; 62 } 63 64 pri->slave = fds[1]; 65 pri->slip.pos = 0; 66 pri->slip.esc = 0; 67 pri->pid = err; 68 69 return fds[0]; 70 out: 71 close(fds[0]); 72 close(fds[1]); 73 return err; 74 } 75 76 static void slirp_close(int fd, void *data) 77 { 78 struct slirp_data *pri = data; 79 int err; 80 81 close(fd); 82 close(pri->slave); 83 84 pri->slave = -1; 85 86 if (pri->pid<1) { 87 printk(UM_KERN_ERR "slirp_close: no child process to shut " 88 "down\n"); 89 return; 90 } 91 92 #if 0 93 if (kill(pri->pid, SIGHUP)<0) { 94 printk(UM_KERN_ERR "slirp_close: sending hangup to %d failed " 95 "(%d)\n", pri->pid, errno); 96 } 97 #endif 98 err = helper_wait(pri->pid); 99 if (err < 0) 100 return; 101 102 pri->pid = -1; 103 } 104 105 int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri) 106 { 107 return slip_proto_read(fd, buf, len, &pri->slip); 108 } 109 110 int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri) 111 { 112 return slip_proto_write(fd, buf, len, &pri->slip); 113 } 114 115 const struct net_user_info slirp_user_info = { 116 .init = slirp_user_init, 117 .open = slirp_open, 118 .close = slirp_close, 119 .remove = NULL, 120 .add_address = NULL, 121 .delete_address = NULL, 122 .mtu = BUF_SIZE, 123 .max_packet = BUF_SIZE, 124 }; 125