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