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 "kern_constants.h" 11 #include "net_user.h" 12 #include "os.h" 13 #include "slirp.h" 14 #include "user.h" 15 16 static int slirp_user_init(void *data, void *dev) 17 { 18 struct slirp_data *pri = data; 19 20 pri->dev = dev; 21 return 0; 22 } 23 24 struct slirp_pre_exec_data { 25 int stdin; 26 int stdout; 27 }; 28 29 static void slirp_pre_exec(void *arg) 30 { 31 struct slirp_pre_exec_data *data = arg; 32 33 if (data->stdin != -1) 34 dup2(data->stdin, 0); 35 if (data->stdout != -1) 36 dup2(data->stdout, 1); 37 } 38 39 static int slirp_tramp(char **argv, int fd) 40 { 41 struct slirp_pre_exec_data pe_data; 42 int pid; 43 44 pe_data.stdin = fd; 45 pe_data.stdout = fd; 46 pid = run_helper(slirp_pre_exec, &pe_data, argv); 47 48 return pid; 49 } 50 51 static int slirp_open(void *data) 52 { 53 struct slirp_data *pri = data; 54 int fds[2], pid, err; 55 56 err = os_pipe(fds, 1, 1); 57 if (err) 58 return err; 59 60 err = slirp_tramp(pri->argw.argv, fds[1]); 61 if (err < 0) { 62 printk(UM_KERN_ERR "slirp_tramp failed - errno = %d\n", -err); 63 goto out; 64 } 65 pid = err; 66 67 pri->slave = fds[1]; 68 pri->slip.pos = 0; 69 pri->slip.esc = 0; 70 pri->pid = err; 71 72 return fds[0]; 73 out: 74 close(fds[0]); 75 close(fds[1]); 76 return err; 77 } 78 79 static void slirp_close(int fd, void *data) 80 { 81 struct slirp_data *pri = data; 82 int status,err; 83 84 close(fd); 85 close(pri->slave); 86 87 pri->slave = -1; 88 89 if (pri->pid<1) { 90 printk(UM_KERN_ERR "slirp_close: no child process to shut " 91 "down\n"); 92 return; 93 } 94 95 #if 0 96 if (kill(pri->pid, SIGHUP)<0) { 97 printk(UM_KERN_ERR "slirp_close: sending hangup to %d failed " 98 "(%d)\n", pri->pid, errno); 99 } 100 #endif 101 102 CATCH_EINTR(err = waitpid(pri->pid, &status, WNOHANG)); 103 if (err < 0) { 104 printk(UM_KERN_ERR "slirp_close: waitpid returned %d\n", errno); 105 return; 106 } 107 108 if (err == 0) { 109 printk(UM_KERN_ERR "slirp_close: process %d has not exited\n", 110 pri->pid); 111 return; 112 } 113 114 pri->pid = -1; 115 } 116 117 int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri) 118 { 119 return slip_proto_read(fd, buf, len, &pri->slip); 120 } 121 122 int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri) 123 { 124 return slip_proto_write(fd, buf, len, &pri->slip); 125 } 126 127 const struct net_user_info slirp_user_info = { 128 .init = slirp_user_init, 129 .open = slirp_open, 130 .close = slirp_close, 131 .remove = NULL, 132 .add_address = NULL, 133 .delete_address = NULL, 134 .mtu = BUF_SIZE, 135 .max_packet = BUF_SIZE, 136 }; 137