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 14static 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 22struct slirp_pre_exec_data { 23 int stdin_fd; 24 int stdout_fd; 25}; 26 27static 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 37static 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 49static 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]; 71out: 72 close(fds[0]); 73 close(fds[1]); 74 return err; 75} 76 77static 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 106int 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 111int 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 116const 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