1 /* 2 * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3 * Licensed under the GPL. 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; 24 int stdout; 25 }; 26 27 static void slirp_pre_exec(void *arg) 28 { 29 struct slirp_pre_exec_data *data = arg; 30 31 if (data->stdin != -1) 32 dup2(data->stdin, 0); 33 if (data->stdout != -1) 34 dup2(data->stdout, 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; 43 pe_data.stdout = 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], pid, 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 pid = err; 64 65 pri->slave = fds[1]; 66 pri->slip.pos = 0; 67 pri->slip.esc = 0; 68 pri->pid = err; 69 70 return fds[0]; 71 out: 72 close(fds[0]); 73 close(fds[1]); 74 return err; 75 } 76 77 static void slirp_close(int fd, void *data) 78 { 79 struct slirp_data *pri = data; 80 int err; 81 82 close(fd); 83 close(pri->slave); 84 85 pri->slave = -1; 86 87 if (pri->pid<1) { 88 printk(UM_KERN_ERR "slirp_close: no child process to shut " 89 "down\n"); 90 return; 91 } 92 93 #if 0 94 if (kill(pri->pid, SIGHUP)<0) { 95 printk(UM_KERN_ERR "slirp_close: sending hangup to %d failed " 96 "(%d)\n", pri->pid, errno); 97 } 98 #endif 99 err = helper_wait(pri->pid); 100 if (err < 0) 101 return; 102 103 pri->pid = -1; 104 } 105 106 int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri) 107 { 108 return slip_proto_read(fd, buf, len, &pri->slip); 109 } 110 111 int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri) 112 { 113 return slip_proto_write(fd, buf, len, &pri->slip); 114 } 115 116 const struct net_user_info slirp_user_info = { 117 .init = slirp_user_init, 118 .open = slirp_open, 119 .close = slirp_close, 120 .remove = NULL, 121 .add_address = NULL, 122 .delete_address = NULL, 123 .mtu = BUF_SIZE, 124 .max_packet = BUF_SIZE, 125 }; 126