root / slirp / misc.c @ d8bcbabf
History | View | Annotate | Download (10.3 kB)
1 | f0cbd3ec | bellard | /*
|
---|---|---|---|
2 | f0cbd3ec | bellard | * Copyright (c) 1995 Danny Gasparovski.
|
3 | 5fafdf24 | ths | *
|
4 | f0cbd3ec | bellard | * Please read the file COPYRIGHT for the
|
5 | f0cbd3ec | bellard | * terms and conditions of the copyright.
|
6 | f0cbd3ec | bellard | */
|
7 | f0cbd3ec | bellard | |
8 | f0cbd3ec | bellard | #include <slirp.h> |
9 | 6dbe553f | Jan Kiszka | #include <libslirp.h> |
10 | 6dbe553f | Jan Kiszka | |
11 | 6dbe553f | Jan Kiszka | #include "monitor.h" |
12 | f0cbd3ec | bellard | |
13 | 9f349498 | Jan Kiszka | #ifdef DEBUG
|
14 | 9f349498 | Jan Kiszka | int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR;
|
15 | 9f349498 | Jan Kiszka | #endif
|
16 | 9f349498 | Jan Kiszka | |
17 | f0cbd3ec | bellard | struct quehead {
|
18 | f0cbd3ec | bellard | struct quehead *qh_link;
|
19 | f0cbd3ec | bellard | struct quehead *qh_rlink;
|
20 | f0cbd3ec | bellard | }; |
21 | f0cbd3ec | bellard | |
22 | f0cbd3ec | bellard | inline void |
23 | 511d2b14 | blueswir1 | insque(void *a, void *b) |
24 | f0cbd3ec | bellard | { |
25 | f0cbd3ec | bellard | register struct quehead *element = (struct quehead *) a; |
26 | f0cbd3ec | bellard | register struct quehead *head = (struct quehead *) b; |
27 | f0cbd3ec | bellard | element->qh_link = head->qh_link; |
28 | f0cbd3ec | bellard | head->qh_link = (struct quehead *)element;
|
29 | f0cbd3ec | bellard | element->qh_rlink = (struct quehead *)head;
|
30 | f0cbd3ec | bellard | ((struct quehead *)(element->qh_link))->qh_rlink
|
31 | f0cbd3ec | bellard | = (struct quehead *)element;
|
32 | f0cbd3ec | bellard | } |
33 | f0cbd3ec | bellard | |
34 | f0cbd3ec | bellard | inline void |
35 | 511d2b14 | blueswir1 | remque(void *a)
|
36 | f0cbd3ec | bellard | { |
37 | f0cbd3ec | bellard | register struct quehead *element = (struct quehead *) a; |
38 | f0cbd3ec | bellard | ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
|
39 | f0cbd3ec | bellard | ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link;
|
40 | f0cbd3ec | bellard | element->qh_rlink = NULL;
|
41 | f0cbd3ec | bellard | } |
42 | f0cbd3ec | bellard | |
43 | a13a4126 | Jan Kiszka | int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, |
44 | a13a4126 | Jan Kiszka | struct in_addr addr, int port) |
45 | f0cbd3ec | bellard | { |
46 | f0cbd3ec | bellard | struct ex_list *tmp_ptr;
|
47 | 5fafdf24 | ths | |
48 | f0cbd3ec | bellard | /* First, check if the port is "bound" */
|
49 | f0cbd3ec | bellard | for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
|
50 | a13a4126 | Jan Kiszka | if (port == tmp_ptr->ex_fport &&
|
51 | a13a4126 | Jan Kiszka | addr.s_addr == tmp_ptr->ex_addr.s_addr) |
52 | a13a4126 | Jan Kiszka | return -1; |
53 | f0cbd3ec | bellard | } |
54 | 5fafdf24 | ths | |
55 | f0cbd3ec | bellard | tmp_ptr = *ex_ptr; |
56 | f0cbd3ec | bellard | *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list)); |
57 | f0cbd3ec | bellard | (*ex_ptr)->ex_fport = port; |
58 | f0cbd3ec | bellard | (*ex_ptr)->ex_addr = addr; |
59 | f0cbd3ec | bellard | (*ex_ptr)->ex_pty = do_pty; |
60 | e1c5a2b3 | aliguori | (*ex_ptr)->ex_exec = (do_pty == 3) ? exec : strdup(exec);
|
61 | f0cbd3ec | bellard | (*ex_ptr)->ex_next = tmp_ptr; |
62 | f0cbd3ec | bellard | return 0; |
63 | f0cbd3ec | bellard | } |
64 | f0cbd3ec | bellard | |
65 | f0cbd3ec | bellard | #ifndef HAVE_STRERROR
|
66 | f0cbd3ec | bellard | |
67 | f0cbd3ec | bellard | /*
|
68 | f0cbd3ec | bellard | * For systems with no strerror
|
69 | f0cbd3ec | bellard | */
|
70 | f0cbd3ec | bellard | |
71 | f0cbd3ec | bellard | extern int sys_nerr; |
72 | f0cbd3ec | bellard | extern char *sys_errlist[]; |
73 | f0cbd3ec | bellard | |
74 | f0cbd3ec | bellard | char *
|
75 | f0cbd3ec | bellard | strerror(error) |
76 | f0cbd3ec | bellard | int error;
|
77 | f0cbd3ec | bellard | { |
78 | f0cbd3ec | bellard | if (error < sys_nerr)
|
79 | f0cbd3ec | bellard | return sys_errlist[error];
|
80 | f0cbd3ec | bellard | else
|
81 | f0cbd3ec | bellard | return "Unknown error."; |
82 | f0cbd3ec | bellard | } |
83 | f0cbd3ec | bellard | |
84 | f0cbd3ec | bellard | #endif
|
85 | f0cbd3ec | bellard | |
86 | f0cbd3ec | bellard | |
87 | a3d4af03 | bellard | #ifdef _WIN32
|
88 | a3d4af03 | bellard | |
89 | a3d4af03 | bellard | int
|
90 | 9634d903 | blueswir1 | fork_exec(struct socket *so, const char *ex, int do_pty) |
91 | a3d4af03 | bellard | { |
92 | a3d4af03 | bellard | /* not implemented */
|
93 | a3d4af03 | bellard | return 0; |
94 | a3d4af03 | bellard | } |
95 | a3d4af03 | bellard | |
96 | a3d4af03 | bellard | #else
|
97 | a3d4af03 | bellard | |
98 | f0cbd3ec | bellard | /*
|
99 | f0cbd3ec | bellard | * XXX This is ugly
|
100 | f0cbd3ec | bellard | * We create and bind a socket, then fork off to another
|
101 | f0cbd3ec | bellard | * process, which connects to this socket, after which we
|
102 | f0cbd3ec | bellard | * exec the wanted program. If something (strange) happens,
|
103 | f0cbd3ec | bellard | * the accept() call could block us forever.
|
104 | 5fafdf24 | ths | *
|
105 | f0cbd3ec | bellard | * do_pty = 0 Fork/exec inetd style
|
106 | f0cbd3ec | bellard | * do_pty = 1 Fork/exec using slirp.telnetd
|
107 | f0cbd3ec | bellard | * do_ptr = 2 Fork/exec using pty
|
108 | f0cbd3ec | bellard | */
|
109 | f0cbd3ec | bellard | int
|
110 | 9634d903 | blueswir1 | fork_exec(struct socket *so, const char *ex, int do_pty) |
111 | f0cbd3ec | bellard | { |
112 | f0cbd3ec | bellard | int s;
|
113 | f0cbd3ec | bellard | struct sockaddr_in addr;
|
114 | 242acf3a | balrog | socklen_t addrlen = sizeof(addr);
|
115 | f0cbd3ec | bellard | int opt;
|
116 | 9634d903 | blueswir1 | int master = -1; |
117 | 7ccfb2eb | blueswir1 | const char *argv[256]; |
118 | f0cbd3ec | bellard | /* don't want to clobber the original */
|
119 | f0cbd3ec | bellard | char *bptr;
|
120 | 9634d903 | blueswir1 | const char *curarg; |
121 | 7b91a172 | bellard | int c, i, ret;
|
122 | 5fafdf24 | ths | |
123 | f0cbd3ec | bellard | DEBUG_CALL("fork_exec");
|
124 | f0cbd3ec | bellard | DEBUG_ARG("so = %lx", (long)so); |
125 | f0cbd3ec | bellard | DEBUG_ARG("ex = %lx", (long)ex); |
126 | f0cbd3ec | bellard | DEBUG_ARG("do_pty = %lx", (long)do_pty); |
127 | 5fafdf24 | ths | |
128 | f0cbd3ec | bellard | if (do_pty == 2) { |
129 | 3f9b2b1f | balrog | return 0; |
130 | f0cbd3ec | bellard | } else {
|
131 | f0cbd3ec | bellard | addr.sin_family = AF_INET; |
132 | f0cbd3ec | bellard | addr.sin_port = 0;
|
133 | f0cbd3ec | bellard | addr.sin_addr.s_addr = INADDR_ANY; |
134 | 3b46e624 | ths | |
135 | 40ff6d7e | Kevin Wolf | if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 || |
136 | f0cbd3ec | bellard | bind(s, (struct sockaddr *)&addr, addrlen) < 0 || |
137 | f0cbd3ec | bellard | listen(s, 1) < 0) { |
138 | f0cbd3ec | bellard | lprint("Error: inet socket: %s\n", strerror(errno));
|
139 | 379ff53d | bellard | closesocket(s); |
140 | 3b46e624 | ths | |
141 | f0cbd3ec | bellard | return 0; |
142 | f0cbd3ec | bellard | } |
143 | f0cbd3ec | bellard | } |
144 | 5fafdf24 | ths | |
145 | f0cbd3ec | bellard | switch(fork()) {
|
146 | f0cbd3ec | bellard | case -1: |
147 | f0cbd3ec | bellard | lprint("Error: fork failed: %s\n", strerror(errno));
|
148 | f0cbd3ec | bellard | close(s); |
149 | f0cbd3ec | bellard | if (do_pty == 2) |
150 | f0cbd3ec | bellard | close(master); |
151 | f0cbd3ec | bellard | return 0; |
152 | 3b46e624 | ths | |
153 | f0cbd3ec | bellard | case 0: |
154 | f0cbd3ec | bellard | /* Set the DISPLAY */
|
155 | f0cbd3ec | bellard | if (do_pty == 2) { |
156 | f0cbd3ec | bellard | (void) close(master);
|
157 | f0cbd3ec | bellard | #ifdef TIOCSCTTY /* XXXXX */ |
158 | f0cbd3ec | bellard | (void) setsid();
|
159 | f0cbd3ec | bellard | ioctl(s, TIOCSCTTY, (char *)NULL); |
160 | f0cbd3ec | bellard | #endif
|
161 | f0cbd3ec | bellard | } else {
|
162 | f0cbd3ec | bellard | getsockname(s, (struct sockaddr *)&addr, &addrlen);
|
163 | f0cbd3ec | bellard | close(s); |
164 | f0cbd3ec | bellard | /*
|
165 | f0cbd3ec | bellard | * Connect to the socket
|
166 | f0cbd3ec | bellard | * XXX If any of these fail, we're in trouble!
|
167 | f0cbd3ec | bellard | */
|
168 | 40ff6d7e | Kevin Wolf | s = qemu_socket(AF_INET, SOCK_STREAM, 0);
|
169 | f0cbd3ec | bellard | addr.sin_addr = loopback_addr; |
170 | 7b91a172 | bellard | do {
|
171 | 7b91a172 | bellard | ret = connect(s, (struct sockaddr *)&addr, addrlen);
|
172 | 7b91a172 | bellard | } while (ret < 0 && errno == EINTR); |
173 | f0cbd3ec | bellard | } |
174 | 3b46e624 | ths | |
175 | f0cbd3ec | bellard | dup2(s, 0);
|
176 | f0cbd3ec | bellard | dup2(s, 1);
|
177 | f0cbd3ec | bellard | dup2(s, 2);
|
178 | 9634d903 | blueswir1 | for (s = getdtablesize() - 1; s >= 3; s--) |
179 | f0cbd3ec | bellard | close(s); |
180 | 3b46e624 | ths | |
181 | f0cbd3ec | bellard | i = 0;
|
182 | f0cbd3ec | bellard | bptr = strdup(ex); /* No need to free() this */
|
183 | f0cbd3ec | bellard | if (do_pty == 1) { |
184 | f0cbd3ec | bellard | /* Setup "slirp.telnetd -x" */
|
185 | f0cbd3ec | bellard | argv[i++] = "slirp.telnetd";
|
186 | f0cbd3ec | bellard | argv[i++] = "-x";
|
187 | f0cbd3ec | bellard | argv[i++] = bptr; |
188 | f0cbd3ec | bellard | } else
|
189 | f0cbd3ec | bellard | do {
|
190 | f0cbd3ec | bellard | /* Change the string into argv[] */
|
191 | f0cbd3ec | bellard | curarg = bptr; |
192 | f0cbd3ec | bellard | while (*bptr != ' ' && *bptr != (char)0) |
193 | f0cbd3ec | bellard | bptr++; |
194 | f0cbd3ec | bellard | c = *bptr; |
195 | f0cbd3ec | bellard | *bptr++ = (char)0; |
196 | f0cbd3ec | bellard | argv[i++] = strdup(curarg); |
197 | f0cbd3ec | bellard | } while (c);
|
198 | 3b46e624 | ths | |
199 | 511d2b14 | blueswir1 | argv[i] = NULL;
|
200 | 7ccfb2eb | blueswir1 | execvp(argv[0], (char **)argv); |
201 | 3b46e624 | ths | |
202 | f0cbd3ec | bellard | /* Ooops, failed, let's tell the user why */
|
203 | f0cbd3ec | bellard | { |
204 | f0cbd3ec | bellard | char buff[256]; |
205 | 3b46e624 | ths | |
206 | 363a37d5 | blueswir1 | snprintf(buff, sizeof(buff),
|
207 | 363a37d5 | blueswir1 | "Error: execvp of %s failed: %s\n",
|
208 | 363a37d5 | blueswir1 | argv[0], strerror(errno));
|
209 | f0cbd3ec | bellard | write(2, buff, strlen(buff)+1); |
210 | f0cbd3ec | bellard | } |
211 | f0cbd3ec | bellard | close(0); close(1); close(2); /* XXX */ |
212 | f0cbd3ec | bellard | exit(1);
|
213 | 3b46e624 | ths | |
214 | f0cbd3ec | bellard | default:
|
215 | f0cbd3ec | bellard | if (do_pty == 2) { |
216 | f0cbd3ec | bellard | close(s); |
217 | f0cbd3ec | bellard | so->s = master; |
218 | f0cbd3ec | bellard | } else {
|
219 | f0cbd3ec | bellard | /*
|
220 | f0cbd3ec | bellard | * XXX this could block us...
|
221 | f0cbd3ec | bellard | * XXX Should set a timer here, and if accept() doesn't
|
222 | f0cbd3ec | bellard | * return after X seconds, declare it a failure
|
223 | f0cbd3ec | bellard | * The only reason this will block forever is if socket()
|
224 | f0cbd3ec | bellard | * of connect() fail in the child process
|
225 | f0cbd3ec | bellard | */
|
226 | 7b91a172 | bellard | do {
|
227 | 7b91a172 | bellard | so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
|
228 | 7b91a172 | bellard | } while (so->s < 0 && errno == EINTR); |
229 | 7b91a172 | bellard | closesocket(s); |
230 | f0cbd3ec | bellard | opt = 1;
|
231 | f0cbd3ec | bellard | setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)); |
232 | f0cbd3ec | bellard | opt = 1;
|
233 | f0cbd3ec | bellard | setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); |
234 | f0cbd3ec | bellard | } |
235 | f0cbd3ec | bellard | fd_nonblock(so->s); |
236 | 3b46e624 | ths | |
237 | f0cbd3ec | bellard | /* Append the telnet options now */
|
238 | 511d2b14 | blueswir1 | if (so->so_m != NULL && do_pty == 1) { |
239 | f0cbd3ec | bellard | sbappend(so, so->so_m); |
240 | 511d2b14 | blueswir1 | so->so_m = NULL;
|
241 | f0cbd3ec | bellard | } |
242 | 3b46e624 | ths | |
243 | f0cbd3ec | bellard | return 1; |
244 | f0cbd3ec | bellard | } |
245 | f0cbd3ec | bellard | } |
246 | f0cbd3ec | bellard | #endif
|
247 | f0cbd3ec | bellard | |
248 | f0cbd3ec | bellard | #ifndef HAVE_STRDUP
|
249 | f0cbd3ec | bellard | char *
|
250 | f0cbd3ec | bellard | strdup(str) |
251 | f0cbd3ec | bellard | const char *str; |
252 | f0cbd3ec | bellard | { |
253 | f0cbd3ec | bellard | char *bptr;
|
254 | 5fafdf24 | ths | |
255 | f0cbd3ec | bellard | bptr = (char *)malloc(strlen(str)+1); |
256 | f0cbd3ec | bellard | strcpy(bptr, str); |
257 | 5fafdf24 | ths | |
258 | f0cbd3ec | bellard | return bptr;
|
259 | f0cbd3ec | bellard | } |
260 | f0cbd3ec | bellard | #endif
|
261 | f0cbd3ec | bellard | |
262 | 376253ec | aliguori | #include "monitor.h" |
263 | c9f10306 | ths | |
264 | 31a60e22 | blueswir1 | void lprint(const char *format, ...) |
265 | 31a60e22 | blueswir1 | { |
266 | 31a60e22 | blueswir1 | va_list args; |
267 | 31a60e22 | blueswir1 | |
268 | 31a60e22 | blueswir1 | va_start(args, format); |
269 | 376253ec | aliguori | monitor_vprintf(cur_mon, format, args); |
270 | 31a60e22 | blueswir1 | va_end(args); |
271 | 31a60e22 | blueswir1 | } |
272 | f0cbd3ec | bellard | |
273 | f0cbd3ec | bellard | #ifdef BAD_SPRINTF
|
274 | f0cbd3ec | bellard | |
275 | f0cbd3ec | bellard | #undef vsprintf
|
276 | f0cbd3ec | bellard | #undef sprintf
|
277 | f0cbd3ec | bellard | |
278 | f0cbd3ec | bellard | /*
|
279 | f0cbd3ec | bellard | * Some BSD-derived systems have a sprintf which returns char *
|
280 | f0cbd3ec | bellard | */
|
281 | f0cbd3ec | bellard | |
282 | f0cbd3ec | bellard | int
|
283 | f0cbd3ec | bellard | vsprintf_len(string, format, args) |
284 | f0cbd3ec | bellard | char *string;
|
285 | f0cbd3ec | bellard | const char *format; |
286 | f0cbd3ec | bellard | va_list args; |
287 | f0cbd3ec | bellard | { |
288 | f0cbd3ec | bellard | vsprintf(string, format, args); |
289 | f0cbd3ec | bellard | return strlen(string);
|
290 | f0cbd3ec | bellard | } |
291 | f0cbd3ec | bellard | |
292 | f0cbd3ec | bellard | int
|
293 | f0cbd3ec | bellard | #ifdef __STDC__
|
294 | f0cbd3ec | bellard | sprintf_len(char *string, const char *format, ...) |
295 | f0cbd3ec | bellard | #else
|
296 | f0cbd3ec | bellard | sprintf_len(va_alist) va_dcl |
297 | f0cbd3ec | bellard | #endif
|
298 | f0cbd3ec | bellard | { |
299 | f0cbd3ec | bellard | va_list args; |
300 | f0cbd3ec | bellard | #ifdef __STDC__
|
301 | f0cbd3ec | bellard | va_start(args, format); |
302 | f0cbd3ec | bellard | #else
|
303 | f0cbd3ec | bellard | char *string;
|
304 | f0cbd3ec | bellard | char *format;
|
305 | f0cbd3ec | bellard | va_start(args); |
306 | f0cbd3ec | bellard | string = va_arg(args, char *);
|
307 | f0cbd3ec | bellard | format = va_arg(args, char *);
|
308 | f0cbd3ec | bellard | #endif
|
309 | f0cbd3ec | bellard | vsprintf(string, format, args); |
310 | f0cbd3ec | bellard | return strlen(string);
|
311 | f0cbd3ec | bellard | } |
312 | f0cbd3ec | bellard | |
313 | f0cbd3ec | bellard | #endif
|
314 | f0cbd3ec | bellard | |
315 | f0cbd3ec | bellard | void
|
316 | 511d2b14 | blueswir1 | u_sleep(int usec)
|
317 | f0cbd3ec | bellard | { |
318 | f0cbd3ec | bellard | struct timeval t;
|
319 | f0cbd3ec | bellard | fd_set fdset; |
320 | 5fafdf24 | ths | |
321 | f0cbd3ec | bellard | FD_ZERO(&fdset); |
322 | 5fafdf24 | ths | |
323 | f0cbd3ec | bellard | t.tv_sec = 0;
|
324 | f0cbd3ec | bellard | t.tv_usec = usec * 1000;
|
325 | 5fafdf24 | ths | |
326 | f0cbd3ec | bellard | select(0, &fdset, &fdset, &fdset, &t);
|
327 | f0cbd3ec | bellard | } |
328 | f0cbd3ec | bellard | |
329 | f0cbd3ec | bellard | /*
|
330 | f0cbd3ec | bellard | * Set fd blocking and non-blocking
|
331 | f0cbd3ec | bellard | */
|
332 | f0cbd3ec | bellard | |
333 | f0cbd3ec | bellard | void
|
334 | 511d2b14 | blueswir1 | fd_nonblock(int fd)
|
335 | f0cbd3ec | bellard | { |
336 | f0cbd3ec | bellard | #ifdef FIONBIO
|
337 | b9e82a59 | blueswir1 | #ifdef _WIN32
|
338 | c5b76b38 | Blue Swirl | unsigned long opt = 1; |
339 | b9e82a59 | blueswir1 | #else
|
340 | b9e82a59 | blueswir1 | int opt = 1; |
341 | b9e82a59 | blueswir1 | #endif
|
342 | 5fafdf24 | ths | |
343 | 379ff53d | bellard | ioctlsocket(fd, FIONBIO, &opt); |
344 | f0cbd3ec | bellard | #else
|
345 | f0cbd3ec | bellard | int opt;
|
346 | 5fafdf24 | ths | |
347 | f0cbd3ec | bellard | opt = fcntl(fd, F_GETFL, 0);
|
348 | f0cbd3ec | bellard | opt |= O_NONBLOCK; |
349 | f0cbd3ec | bellard | fcntl(fd, F_SETFL, opt); |
350 | f0cbd3ec | bellard | #endif
|
351 | f0cbd3ec | bellard | } |
352 | f0cbd3ec | bellard | |
353 | f0cbd3ec | bellard | void
|
354 | 511d2b14 | blueswir1 | fd_block(int fd)
|
355 | f0cbd3ec | bellard | { |
356 | f0cbd3ec | bellard | #ifdef FIONBIO
|
357 | c5b76b38 | Blue Swirl | #ifdef _WIN32
|
358 | c5b76b38 | Blue Swirl | unsigned long opt = 0; |
359 | c5b76b38 | Blue Swirl | #else
|
360 | f0cbd3ec | bellard | int opt = 0; |
361 | c5b76b38 | Blue Swirl | #endif
|
362 | 5fafdf24 | ths | |
363 | 379ff53d | bellard | ioctlsocket(fd, FIONBIO, &opt); |
364 | f0cbd3ec | bellard | #else
|
365 | f0cbd3ec | bellard | int opt;
|
366 | 5fafdf24 | ths | |
367 | f0cbd3ec | bellard | opt = fcntl(fd, F_GETFL, 0);
|
368 | f0cbd3ec | bellard | opt &= ~O_NONBLOCK; |
369 | f0cbd3ec | bellard | fcntl(fd, F_SETFL, opt); |
370 | f0cbd3ec | bellard | #endif
|
371 | f0cbd3ec | bellard | } |
372 | f0cbd3ec | bellard | |
373 | 9f8bd042 | Jan Kiszka | void slirp_connection_info(Slirp *slirp, Monitor *mon)
|
374 | 6dbe553f | Jan Kiszka | { |
375 | 6dbe553f | Jan Kiszka | const char * const tcpstates[] = { |
376 | 6dbe553f | Jan Kiszka | [TCPS_CLOSED] = "CLOSED",
|
377 | 6dbe553f | Jan Kiszka | [TCPS_LISTEN] = "LISTEN",
|
378 | 6dbe553f | Jan Kiszka | [TCPS_SYN_SENT] = "SYN_SENT",
|
379 | 6dbe553f | Jan Kiszka | [TCPS_SYN_RECEIVED] = "SYN_RCVD",
|
380 | 6dbe553f | Jan Kiszka | [TCPS_ESTABLISHED] = "ESTABLISHED",
|
381 | 6dbe553f | Jan Kiszka | [TCPS_CLOSE_WAIT] = "CLOSE_WAIT",
|
382 | 6dbe553f | Jan Kiszka | [TCPS_FIN_WAIT_1] = "FIN_WAIT_1",
|
383 | 6dbe553f | Jan Kiszka | [TCPS_CLOSING] = "CLOSING",
|
384 | 6dbe553f | Jan Kiszka | [TCPS_LAST_ACK] = "LAST_ACK",
|
385 | 6dbe553f | Jan Kiszka | [TCPS_FIN_WAIT_2] = "FIN_WAIT_2",
|
386 | 6dbe553f | Jan Kiszka | [TCPS_TIME_WAIT] = "TIME_WAIT",
|
387 | 6dbe553f | Jan Kiszka | }; |
388 | 6dbe553f | Jan Kiszka | struct in_addr dst_addr;
|
389 | 6dbe553f | Jan Kiszka | struct sockaddr_in src;
|
390 | 6dbe553f | Jan Kiszka | socklen_t src_len; |
391 | 6dbe553f | Jan Kiszka | uint16_t dst_port; |
392 | 6dbe553f | Jan Kiszka | struct socket *so;
|
393 | 6dbe553f | Jan Kiszka | const char *state; |
394 | 6dbe553f | Jan Kiszka | char buf[20]; |
395 | 6dbe553f | Jan Kiszka | int n;
|
396 | 6dbe553f | Jan Kiszka | |
397 | 6dbe553f | Jan Kiszka | monitor_printf(mon, " Protocol[State] FD Source Address Port "
|
398 | 6dbe553f | Jan Kiszka | "Dest. Address Port RecvQ SendQ\n");
|
399 | 6dbe553f | Jan Kiszka | |
400 | 460fec67 | Jan Kiszka | for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
|
401 | 6dbe553f | Jan Kiszka | if (so->so_state & SS_HOSTFWD) {
|
402 | 6dbe553f | Jan Kiszka | state = "HOST_FORWARD";
|
403 | 6dbe553f | Jan Kiszka | } else if (so->so_tcpcb) { |
404 | 6dbe553f | Jan Kiszka | state = tcpstates[so->so_tcpcb->t_state]; |
405 | 6dbe553f | Jan Kiszka | } else {
|
406 | 6dbe553f | Jan Kiszka | state = "NONE";
|
407 | 6dbe553f | Jan Kiszka | } |
408 | 6dbe553f | Jan Kiszka | if (so->so_state & (SS_HOSTFWD | SS_INCOMING)) {
|
409 | 6dbe553f | Jan Kiszka | src_len = sizeof(src);
|
410 | 6dbe553f | Jan Kiszka | getsockname(so->s, (struct sockaddr *)&src, &src_len);
|
411 | 6dbe553f | Jan Kiszka | dst_addr = so->so_laddr; |
412 | 6dbe553f | Jan Kiszka | dst_port = so->so_lport; |
413 | 6dbe553f | Jan Kiszka | } else {
|
414 | 6dbe553f | Jan Kiszka | src.sin_addr = so->so_laddr; |
415 | 6dbe553f | Jan Kiszka | src.sin_port = so->so_lport; |
416 | 6dbe553f | Jan Kiszka | dst_addr = so->so_faddr; |
417 | 6dbe553f | Jan Kiszka | dst_port = so->so_fport; |
418 | 6dbe553f | Jan Kiszka | } |
419 | 6dbe553f | Jan Kiszka | n = snprintf(buf, sizeof(buf), " TCP[%s]", state); |
420 | 6dbe553f | Jan Kiszka | memset(&buf[n], ' ', 19 - n); |
421 | 6dbe553f | Jan Kiszka | buf[19] = 0; |
422 | 6dbe553f | Jan Kiszka | monitor_printf(mon, "%s %3d %15s %5d ", buf, so->s,
|
423 | 6dbe553f | Jan Kiszka | src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*",
|
424 | 6dbe553f | Jan Kiszka | ntohs(src.sin_port)); |
425 | 6dbe553f | Jan Kiszka | monitor_printf(mon, "%15s %5d %5d %5d\n",
|
426 | 6dbe553f | Jan Kiszka | inet_ntoa(dst_addr), ntohs(dst_port), |
427 | 6dbe553f | Jan Kiszka | so->so_rcv.sb_cc, so->so_snd.sb_cc); |
428 | 6dbe553f | Jan Kiszka | } |
429 | 6dbe553f | Jan Kiszka | |
430 | 460fec67 | Jan Kiszka | for (so = slirp->udb.so_next; so != &slirp->udb; so = so->so_next) {
|
431 | 6dbe553f | Jan Kiszka | if (so->so_state & SS_HOSTFWD) {
|
432 | 6dbe553f | Jan Kiszka | n = snprintf(buf, sizeof(buf), " UDP[HOST_FORWARD]"); |
433 | 6dbe553f | Jan Kiszka | src_len = sizeof(src);
|
434 | 6dbe553f | Jan Kiszka | getsockname(so->s, (struct sockaddr *)&src, &src_len);
|
435 | 6dbe553f | Jan Kiszka | dst_addr = so->so_laddr; |
436 | 6dbe553f | Jan Kiszka | dst_port = so->so_lport; |
437 | 6dbe553f | Jan Kiszka | } else {
|
438 | 6dbe553f | Jan Kiszka | n = snprintf(buf, sizeof(buf), " UDP[%d sec]", |
439 | 6dbe553f | Jan Kiszka | (so->so_expire - curtime) / 1000);
|
440 | 6dbe553f | Jan Kiszka | src.sin_addr = so->so_laddr; |
441 | 6dbe553f | Jan Kiszka | src.sin_port = so->so_lport; |
442 | 6dbe553f | Jan Kiszka | dst_addr = so->so_faddr; |
443 | 6dbe553f | Jan Kiszka | dst_port = so->so_fport; |
444 | 6dbe553f | Jan Kiszka | } |
445 | 6dbe553f | Jan Kiszka | memset(&buf[n], ' ', 19 - n); |
446 | 6dbe553f | Jan Kiszka | buf[19] = 0; |
447 | 6dbe553f | Jan Kiszka | monitor_printf(mon, "%s %3d %15s %5d ", buf, so->s,
|
448 | 6dbe553f | Jan Kiszka | src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*",
|
449 | 6dbe553f | Jan Kiszka | ntohs(src.sin_port)); |
450 | 6dbe553f | Jan Kiszka | monitor_printf(mon, "%15s %5d %5d %5d\n",
|
451 | 6dbe553f | Jan Kiszka | inet_ntoa(dst_addr), ntohs(dst_port), |
452 | 6dbe553f | Jan Kiszka | so->so_rcv.sb_cc, so->so_snd.sb_cc); |
453 | 6dbe553f | Jan Kiszka | } |
454 | 6dbe553f | Jan Kiszka | } |