2 * Copyright (c) 1995 Danny Gasparovski.
4 * Please read the file COPYRIGHT for the
5 * terms and conditions of the copyright.
8 #include "qemu/osdep.h"
11 #include "qemu/error-report.h"
12 #include "qemu/main-loop.h"
15 int slirp_debug
= DBG_CALL
|DBG_MISC
|DBG_ERROR
;
19 insque(void *a
, void *b
)
21 register struct quehead
*element
= (struct quehead
*) a
;
22 register struct quehead
*head
= (struct quehead
*) b
;
23 element
->qh_link
= head
->qh_link
;
24 head
->qh_link
= (struct quehead
*)element
;
25 element
->qh_rlink
= (struct quehead
*)head
;
26 ((struct quehead
*)(element
->qh_link
))->qh_rlink
27 = (struct quehead
*)element
;
33 register struct quehead
*element
= (struct quehead
*) a
;
34 ((struct quehead
*)(element
->qh_link
))->qh_rlink
= element
->qh_rlink
;
35 ((struct quehead
*)(element
->qh_rlink
))->qh_link
= element
->qh_link
;
36 element
->qh_rlink
= NULL
;
39 int add_exec(struct ex_list
**ex_ptr
, void *chardev
, const char *cmdline
,
40 struct in_addr addr
, int port
)
42 struct ex_list
*tmp_ptr
;
44 /* First, check if the port is "bound" */
45 for (tmp_ptr
= *ex_ptr
; tmp_ptr
; tmp_ptr
= tmp_ptr
->ex_next
) {
46 if (port
== tmp_ptr
->ex_fport
&&
47 addr
.s_addr
== tmp_ptr
->ex_addr
.s_addr
)
52 *ex_ptr
= g_new0(struct ex_list
, 1);
53 (*ex_ptr
)->ex_fport
= port
;
54 (*ex_ptr
)->ex_addr
= addr
;
56 (*ex_ptr
)->ex_chardev
= chardev
;
58 (*ex_ptr
)->ex_exec
= g_strdup(cmdline
);
60 (*ex_ptr
)->ex_next
= tmp_ptr
;
68 fork_exec(struct socket
*so
, const char *ex
)
77 slirp_socketpair_with_oob(int sv
[2])
79 struct sockaddr_in addr
= {
80 .sin_family
= AF_INET
,
82 .sin_addr
.s_addr
= INADDR_ANY
,
84 socklen_t addrlen
= sizeof(addr
);
88 s
= qemu_socket(AF_INET
, SOCK_STREAM
, 0);
89 if (s
< 0 || bind(s
, (struct sockaddr
*)&addr
, addrlen
) < 0 ||
91 getsockname(s
, (struct sockaddr
*)&addr
, &addrlen
) < 0) {
95 sv
[1] = qemu_socket(AF_INET
, SOCK_STREAM
, 0);
100 * This connect won't block because we've already listen()ed on
101 * the server end (even though we won't accept() the connection
105 ret
= connect(sv
[1], (struct sockaddr
*)&addr
, addrlen
);
106 } while (ret
< 0 && errno
== EINTR
);
112 sv
[0] = accept(s
, (struct sockaddr
*)&addr
, &addrlen
);
113 } while (sv
[0] < 0 && errno
== EINTR
);
122 error_report("Error: slirp_socketpair(): %s", strerror(errno
));
133 fork_exec(struct socket
*so
, const char *ex
)
139 DEBUG_CALL("fork_exec");
140 DEBUG_ARG("so = %p", so
);
141 DEBUG_ARG("ex = %p", ex
);
143 if (slirp_socketpair_with_oob(sp
) < 0) {
150 error_report("Error: fork failed: %s", strerror(errno
));
160 for (c
= getdtablesize() - 1; c
>= 3; c
--)
163 argv
= g_strsplit(ex
, " ", -1);
164 execvp(argv
[0], (char **)argv
);
166 /* Ooops, failed, let's tell the user why */
167 fprintf(stderr
, "Error: execvp of %s failed: %s\n",
168 argv
[0], strerror(errno
));
169 close(0); close(1); close(2); /* XXX */
175 qemu_add_child_watch(pid
);
176 socket_set_fast_reuse(so
->s
);
178 qemu_setsockopt(so
->s
, SOL_SOCKET
, SO_OOBINLINE
, &opt
, sizeof(int));
179 qemu_set_nonblock(so
->s
);
185 char *slirp_connection_info(Slirp
*slirp
)
187 GString
*str
= g_string_new(NULL
);
188 const char * const tcpstates
[] = {
189 [TCPS_CLOSED
] = "CLOSED",
190 [TCPS_LISTEN
] = "LISTEN",
191 [TCPS_SYN_SENT
] = "SYN_SENT",
192 [TCPS_SYN_RECEIVED
] = "SYN_RCVD",
193 [TCPS_ESTABLISHED
] = "ESTABLISHED",
194 [TCPS_CLOSE_WAIT
] = "CLOSE_WAIT",
195 [TCPS_FIN_WAIT_1
] = "FIN_WAIT_1",
196 [TCPS_CLOSING
] = "CLOSING",
197 [TCPS_LAST_ACK
] = "LAST_ACK",
198 [TCPS_FIN_WAIT_2
] = "FIN_WAIT_2",
199 [TCPS_TIME_WAIT
] = "TIME_WAIT",
201 struct in_addr dst_addr
;
202 struct sockaddr_in src
;
209 g_string_append_printf(str
,
210 " Protocol[State] FD Source Address Port "
211 "Dest. Address Port RecvQ SendQ\n");
213 for (so
= slirp
->tcb
.so_next
; so
!= &slirp
->tcb
; so
= so
->so_next
) {
214 if (so
->so_state
& SS_HOSTFWD
) {
215 state
= "HOST_FORWARD";
216 } else if (so
->so_tcpcb
) {
217 state
= tcpstates
[so
->so_tcpcb
->t_state
];
221 if (so
->so_state
& (SS_HOSTFWD
| SS_INCOMING
)) {
222 src_len
= sizeof(src
);
223 getsockname(so
->s
, (struct sockaddr
*)&src
, &src_len
);
224 dst_addr
= so
->so_laddr
;
225 dst_port
= so
->so_lport
;
227 src
.sin_addr
= so
->so_laddr
;
228 src
.sin_port
= so
->so_lport
;
229 dst_addr
= so
->so_faddr
;
230 dst_port
= so
->so_fport
;
232 snprintf(buf
, sizeof(buf
), " TCP[%s]", state
);
233 g_string_append_printf(str
, "%-19s %3d %15s %5d ", buf
, so
->s
,
234 src
.sin_addr
.s_addr
? inet_ntoa(src
.sin_addr
) : "*",
235 ntohs(src
.sin_port
));
236 g_string_append_printf(str
, "%15s %5d %5d %5d\n",
237 inet_ntoa(dst_addr
), ntohs(dst_port
),
238 so
->so_rcv
.sb_cc
, so
->so_snd
.sb_cc
);
241 for (so
= slirp
->udb
.so_next
; so
!= &slirp
->udb
; so
= so
->so_next
) {
242 if (so
->so_state
& SS_HOSTFWD
) {
243 snprintf(buf
, sizeof(buf
), " UDP[HOST_FORWARD]");
244 src_len
= sizeof(src
);
245 getsockname(so
->s
, (struct sockaddr
*)&src
, &src_len
);
246 dst_addr
= so
->so_laddr
;
247 dst_port
= so
->so_lport
;
249 snprintf(buf
, sizeof(buf
), " UDP[%d sec]",
250 (so
->so_expire
- curtime
) / 1000);
251 src
.sin_addr
= so
->so_laddr
;
252 src
.sin_port
= so
->so_lport
;
253 dst_addr
= so
->so_faddr
;
254 dst_port
= so
->so_fport
;
256 g_string_append_printf(str
, "%-19s %3d %15s %5d ", buf
, so
->s
,
257 src
.sin_addr
.s_addr
? inet_ntoa(src
.sin_addr
) : "*",
258 ntohs(src
.sin_port
));
259 g_string_append_printf(str
, "%15s %5d %5d %5d\n",
260 inet_ntoa(dst_addr
), ntohs(dst_port
),
261 so
->so_rcv
.sb_cc
, so
->so_snd
.sb_cc
);
264 for (so
= slirp
->icmp
.so_next
; so
!= &slirp
->icmp
; so
= so
->so_next
) {
265 snprintf(buf
, sizeof(buf
), " ICMP[%d sec]",
266 (so
->so_expire
- curtime
) / 1000);
267 src
.sin_addr
= so
->so_laddr
;
268 dst_addr
= so
->so_faddr
;
269 g_string_append_printf(str
, "%-19s %3d %15s - ", buf
, so
->s
,
270 src
.sin_addr
.s_addr
? inet_ntoa(src
.sin_addr
) : "*");
271 g_string_append_printf(str
, "%15s - %5d %5d\n", inet_ntoa(dst_addr
),
272 so
->so_rcv
.sb_cc
, so
->so_snd
.sb_cc
);
275 return g_string_free(str
, FALSE
);