Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stddef.h> #include <sched.h> #include <string.h> #include <sys/fcntl.h> #include <sys/errno.h> #include <sys/wait.h> #include <sys/signal.h> #include "user_util.h" #include "kern_util.h" #include "user.h" #include "net_user.h" #include "slirp.h" #include "slip_proto.h" #include "helper.h" #include "os.h" void slirp_user_init(void *data, void *dev) { struct slirp_data *pri = data; pri->dev = dev; } struct slirp_pre_exec_data { int stdin; int stdout; }; static void slirp_pre_exec(void *arg) { struct slirp_pre_exec_data *data = arg; if(data->stdin != -1) dup2(data->stdin, 0); if(data->stdout != -1) dup2(data->stdout, 1); } static int slirp_tramp(char **argv, int fd) { struct slirp_pre_exec_data pe_data; int pid; pe_data.stdin = fd; pe_data.stdout = fd; pid = run_helper(slirp_pre_exec, &pe_data, argv, NULL); return(pid); } static int slirp_datachan(int *mfd, int *sfd) { int fds[2], err; err = os_pipe(fds, 1, 1); if(err){ printk("slirp_datachan: Failed to open pipe, errno = %d\n", -err); return(err); } *mfd = fds[0]; *sfd = fds[1]; return(0); } static int slirp_open(void *data) { struct slirp_data *pri = data; int sfd, mfd, pid, err; err = slirp_datachan(&mfd, &sfd); if(err) return(err); pid = slirp_tramp(pri->argw.argv, sfd); if(pid < 0){ printk("slirp_tramp failed - errno = %d\n", pid); os_close_file(sfd); os_close_file(mfd); return(pid); } pri->slave = sfd; pri->pos = 0; pri->esc = 0; pri->pid = pid; return(mfd); } static void slirp_close(int fd, void *data) { struct slirp_data *pri = data; int status,err; close(fd); close(pri->slave); pri->slave = -1; if(pri->pid<1) { printk("slirp_close: no child process to shut down\n"); return; } #if 0 if(kill(pri->pid, SIGHUP)<0) { printk("slirp_close: sending hangup to %d failed (%d)\n", pri->pid, errno); } #endif err = waitpid(pri->pid, &status, WNOHANG); if(err<0) { printk("slirp_close: waitpid returned %d\n", errno); return; } if(err==0) { printk("slirp_close: process %d has not exited\n"); return; } pri->pid = -1; } int slirp_user_read(int fd, void *buf, int len, struct slirp_data *pri) { int i, n, size, start; if(pri->more>0) { i = 0; while(i < pri->more) { size = slip_unesc(pri->ibuf[i++], pri->ibuf,&pri->pos,&pri->esc); if(size){ memcpy(buf, pri->ibuf, size); memmove(pri->ibuf, &pri->ibuf[i], pri->more-i); pri->more=pri->more-i; return(size); } } pri->more=0; } n = net_read(fd, &pri->ibuf[pri->pos], sizeof(pri->ibuf) - pri->pos); if(n <= 0) return(n); start = pri->pos; for(i = 0; i < n; i++){ size = slip_unesc(pri->ibuf[start + i], pri->ibuf,&pri->pos,&pri->esc); if(size){ memcpy(buf, pri->ibuf, size); memmove(pri->ibuf, &pri->ibuf[start+i+1], n-(i+1)); pri->more=n-(i+1); return(size); } } return(0); } int slirp_user_write(int fd, void *buf, int len, struct slirp_data *pri) { int actual, n; actual = slip_esc(buf, pri->obuf, len); n = net_write(fd, pri->obuf, actual); if(n < 0) return(n); else return(len); } static int slirp_set_mtu(int mtu, void *data) { return(mtu); } struct net_user_info slirp_user_info = { .init = slirp_user_init, .open = slirp_open, .close = slirp_close, .remove = NULL, .set_mtu = slirp_set_mtu, .add_address = NULL, .delete_address = NULL, .max_packet = BUF_SIZE }; /* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only. This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-file-style: "linux" * End: */ |