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 insque(void *a
, void *b
)
17 register struct quehead
*element
= (struct quehead
*) a
;
18 register struct quehead
*head
= (struct quehead
*) b
;
19 element
->qh_link
= head
->qh_link
;
20 head
->qh_link
= (struct quehead
*)element
;
21 element
->qh_rlink
= (struct quehead
*)head
;
22 ((struct quehead
*)(element
->qh_link
))->qh_rlink
23 = (struct quehead
*)element
;
29 register struct quehead
*element
= (struct quehead
*) a
;
30 ((struct quehead
*)(element
->qh_link
))->qh_rlink
= element
->qh_rlink
;
31 ((struct quehead
*)(element
->qh_rlink
))->qh_link
= element
->qh_link
;
32 element
->qh_rlink
= NULL
;
35 int add_exec(struct gfwd_list
**ex_ptr
, void *chardev
, const char *cmdline
,
36 struct in_addr addr
, int port
)
38 struct gfwd_list
*tmp_ptr
;
41 *ex_ptr
= g_new0(struct gfwd_list
, 1);
42 (*ex_ptr
)->ex_fport
= port
;
43 (*ex_ptr
)->ex_addr
= addr
;
45 (*ex_ptr
)->ex_chardev
= chardev
;
47 (*ex_ptr
)->ex_exec
= g_strdup(cmdline
);
49 (*ex_ptr
)->ex_next
= tmp_ptr
;
55 slirp_socketpair_with_oob(int sv
[2])
57 struct sockaddr_in addr
= {
58 .sin_family
= AF_INET
,
60 .sin_addr
.s_addr
= INADDR_ANY
,
62 socklen_t addrlen
= sizeof(addr
);
66 s
= qemu_socket(AF_INET
, SOCK_STREAM
, 0);
67 if (s
< 0 || bind(s
, (struct sockaddr
*)&addr
, addrlen
) < 0 ||
69 getsockname(s
, (struct sockaddr
*)&addr
, &addrlen
) < 0) {
73 sv
[1] = qemu_socket(AF_INET
, SOCK_STREAM
, 0);
78 * This connect won't block because we've already listen()ed on
79 * the server end (even though we won't accept() the connection
83 ret
= connect(sv
[1], (struct sockaddr
*)&addr
, addrlen
);
84 } while (ret
< 0 && errno
== EINTR
);
90 sv
[0] = accept(s
, (struct sockaddr
*)&addr
, &addrlen
);
91 } while (sv
[0] < 0 && errno
== EINTR
);
100 g_critical("slirp_socketpair(): %s", strerror(errno
));
111 fork_exec_child_setup(gpointer data
)
119 fork_exec(struct socket
*so
, const char *ex
)
125 DEBUG_CALL("fork_exec");
126 DEBUG_ARG("so = %p", so
);
127 DEBUG_ARG("ex = %p", ex
);
129 if (slirp_socketpair_with_oob(sp
) < 0) {
133 argv
= g_strsplit(ex
, " ", -1);
134 g_spawn_async_with_fds(NULL
/* cwd */,
138 fork_exec_child_setup
, NULL
/* data */,
139 NULL
/* child_pid */,
145 g_critical("fork_exec: %s", err
->message
);
154 socket_set_fast_reuse(so
->s
);
156 qemu_setsockopt(so
->s
, SOL_SOCKET
, SO_OOBINLINE
, &opt
, sizeof(int));
157 qemu_set_nonblock(so
->s
);
161 char *slirp_connection_info(Slirp
*slirp
)
163 GString
*str
= g_string_new(NULL
);
164 const char * const tcpstates
[] = {
165 [TCPS_CLOSED
] = "CLOSED",
166 [TCPS_LISTEN
] = "LISTEN",
167 [TCPS_SYN_SENT
] = "SYN_SENT",
168 [TCPS_SYN_RECEIVED
] = "SYN_RCVD",
169 [TCPS_ESTABLISHED
] = "ESTABLISHED",
170 [TCPS_CLOSE_WAIT
] = "CLOSE_WAIT",
171 [TCPS_FIN_WAIT_1
] = "FIN_WAIT_1",
172 [TCPS_CLOSING
] = "CLOSING",
173 [TCPS_LAST_ACK
] = "LAST_ACK",
174 [TCPS_FIN_WAIT_2
] = "FIN_WAIT_2",
175 [TCPS_TIME_WAIT
] = "TIME_WAIT",
177 struct in_addr dst_addr
;
178 struct sockaddr_in src
;
185 g_string_append_printf(str
,
186 " Protocol[State] FD Source Address Port "
187 "Dest. Address Port RecvQ SendQ\n");
189 for (so
= slirp
->tcb
.so_next
; so
!= &slirp
->tcb
; so
= so
->so_next
) {
190 if (so
->so_state
& SS_HOSTFWD
) {
191 state
= "HOST_FORWARD";
192 } else if (so
->so_tcpcb
) {
193 state
= tcpstates
[so
->so_tcpcb
->t_state
];
197 if (so
->so_state
& (SS_HOSTFWD
| SS_INCOMING
)) {
198 src_len
= sizeof(src
);
199 getsockname(so
->s
, (struct sockaddr
*)&src
, &src_len
);
200 dst_addr
= so
->so_laddr
;
201 dst_port
= so
->so_lport
;
203 src
.sin_addr
= so
->so_laddr
;
204 src
.sin_port
= so
->so_lport
;
205 dst_addr
= so
->so_faddr
;
206 dst_port
= so
->so_fport
;
208 snprintf(buf
, sizeof(buf
), " TCP[%s]", state
);
209 g_string_append_printf(str
, "%-19s %3d %15s %5d ", buf
, so
->s
,
210 src
.sin_addr
.s_addr
? inet_ntoa(src
.sin_addr
) : "*",
211 ntohs(src
.sin_port
));
212 g_string_append_printf(str
, "%15s %5d %5d %5d\n",
213 inet_ntoa(dst_addr
), ntohs(dst_port
),
214 so
->so_rcv
.sb_cc
, so
->so_snd
.sb_cc
);
217 for (so
= slirp
->udb
.so_next
; so
!= &slirp
->udb
; so
= so
->so_next
) {
218 if (so
->so_state
& SS_HOSTFWD
) {
219 snprintf(buf
, sizeof(buf
), " UDP[HOST_FORWARD]");
220 src_len
= sizeof(src
);
221 getsockname(so
->s
, (struct sockaddr
*)&src
, &src_len
);
222 dst_addr
= so
->so_laddr
;
223 dst_port
= so
->so_lport
;
225 snprintf(buf
, sizeof(buf
), " UDP[%d sec]",
226 (so
->so_expire
- curtime
) / 1000);
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 g_string_append_printf(str
, "%-19s %3d %15s %5d ", buf
, so
->s
,
233 src
.sin_addr
.s_addr
? inet_ntoa(src
.sin_addr
) : "*",
234 ntohs(src
.sin_port
));
235 g_string_append_printf(str
, "%15s %5d %5d %5d\n",
236 inet_ntoa(dst_addr
), ntohs(dst_port
),
237 so
->so_rcv
.sb_cc
, so
->so_snd
.sb_cc
);
240 for (so
= slirp
->icmp
.so_next
; so
!= &slirp
->icmp
; so
= so
->so_next
) {
241 snprintf(buf
, sizeof(buf
), " ICMP[%d sec]",
242 (so
->so_expire
- curtime
) / 1000);
243 src
.sin_addr
= so
->so_laddr
;
244 dst_addr
= so
->so_faddr
;
245 g_string_append_printf(str
, "%-19s %3d %15s - ", buf
, so
->s
,
246 src
.sin_addr
.s_addr
? inet_ntoa(src
.sin_addr
) : "*");
247 g_string_append_printf(str
, "%15s - %5d %5d\n", inet_ntoa(dst_addr
),
248 so
->so_rcv
.sb_cc
, so
->so_snd
.sb_cc
);
251 return g_string_free(str
, FALSE
);