]>
git.proxmox.com Git - mirror_qemu.git/blob - slirp/misc.c
4ee20a10e44b8c8493d675126b1c7121a48bc743
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
;
36 add_guestfwd(struct gfwd_list
**ex_ptr
,
37 SlirpWriteCb write_cb
, void *opaque
,
38 struct in_addr addr
, int port
)
40 struct gfwd_list
*f
= g_new0(struct gfwd_list
, 1);
42 f
->write_cb
= write_cb
;
53 add_exec(struct gfwd_list
**ex_ptr
, const char *cmdline
,
54 struct in_addr addr
, int port
)
56 struct gfwd_list
*f
= add_guestfwd(ex_ptr
, NULL
, NULL
, addr
, port
);
58 f
->ex_exec
= g_strdup(cmdline
);
64 slirp_socketpair_with_oob(int sv
[2])
66 struct sockaddr_in addr
= {
67 .sin_family
= AF_INET
,
69 .sin_addr
.s_addr
= INADDR_ANY
,
71 socklen_t addrlen
= sizeof(addr
);
75 s
= slirp_socket(AF_INET
, SOCK_STREAM
, 0);
76 if (s
< 0 || bind(s
, (struct sockaddr
*)&addr
, addrlen
) < 0 ||
78 getsockname(s
, (struct sockaddr
*)&addr
, &addrlen
) < 0) {
82 sv
[1] = slirp_socket(AF_INET
, SOCK_STREAM
, 0);
87 * This connect won't block because we've already listen()ed on
88 * the server end (even though we won't accept() the connection
92 ret
= connect(sv
[1], (struct sockaddr
*)&addr
, addrlen
);
93 } while (ret
< 0 && errno
== EINTR
);
99 sv
[0] = accept(s
, (struct sockaddr
*)&addr
, &addrlen
);
100 } while (sv
[0] < 0 && errno
== EINTR
);
105 slirp_closesocket(s
);
109 g_critical("slirp_socketpair(): %s", strerror(errno
));
111 slirp_closesocket(s
);
114 slirp_closesocket(sv
[1]);
120 fork_exec_child_setup(gpointer data
)
128 fork_exec(struct socket
*so
, const char *ex
)
134 DEBUG_CALL("fork_exec");
135 DEBUG_ARG("so = %p", so
);
136 DEBUG_ARG("ex = %p", ex
);
138 if (slirp_socketpair_with_oob(sp
) < 0) {
142 argv
= g_strsplit(ex
, " ", -1);
143 g_spawn_async_with_fds(NULL
/* cwd */,
147 fork_exec_child_setup
, NULL
/* data */,
148 NULL
/* child_pid */,
154 g_critical("fork_exec: %s", err
->message
);
156 slirp_closesocket(sp
[0]);
157 slirp_closesocket(sp
[1]);
162 slirp_closesocket(sp
[1]);
163 slirp_socket_set_fast_reuse(so
->s
);
165 slirp_setsockopt(so
->s
, SOL_SOCKET
, SO_OOBINLINE
, &opt
, sizeof(int));
166 slirp_set_nonblock(so
->s
);
167 so
->slirp
->cb
->register_poll_fd(so
->s
);
171 char *slirp_connection_info(Slirp
*slirp
)
173 GString
*str
= g_string_new(NULL
);
174 const char * const tcpstates
[] = {
175 [TCPS_CLOSED
] = "CLOSED",
176 [TCPS_LISTEN
] = "LISTEN",
177 [TCPS_SYN_SENT
] = "SYN_SENT",
178 [TCPS_SYN_RECEIVED
] = "SYN_RCVD",
179 [TCPS_ESTABLISHED
] = "ESTABLISHED",
180 [TCPS_CLOSE_WAIT
] = "CLOSE_WAIT",
181 [TCPS_FIN_WAIT_1
] = "FIN_WAIT_1",
182 [TCPS_CLOSING
] = "CLOSING",
183 [TCPS_LAST_ACK
] = "LAST_ACK",
184 [TCPS_FIN_WAIT_2
] = "FIN_WAIT_2",
185 [TCPS_TIME_WAIT
] = "TIME_WAIT",
187 struct in_addr dst_addr
;
188 struct sockaddr_in src
;
195 g_string_append_printf(str
,
196 " Protocol[State] FD Source Address Port "
197 "Dest. Address Port RecvQ SendQ\n");
199 for (so
= slirp
->tcb
.so_next
; so
!= &slirp
->tcb
; so
= so
->so_next
) {
200 if (so
->so_state
& SS_HOSTFWD
) {
201 state
= "HOST_FORWARD";
202 } else if (so
->so_tcpcb
) {
203 state
= tcpstates
[so
->so_tcpcb
->t_state
];
207 if (so
->so_state
& (SS_HOSTFWD
| SS_INCOMING
)) {
208 src_len
= sizeof(src
);
209 getsockname(so
->s
, (struct sockaddr
*)&src
, &src_len
);
210 dst_addr
= so
->so_laddr
;
211 dst_port
= so
->so_lport
;
213 src
.sin_addr
= so
->so_laddr
;
214 src
.sin_port
= so
->so_lport
;
215 dst_addr
= so
->so_faddr
;
216 dst_port
= so
->so_fport
;
218 snprintf(buf
, sizeof(buf
), " TCP[%s]", state
);
219 g_string_append_printf(str
, "%-19s %3d %15s %5d ", buf
, so
->s
,
220 src
.sin_addr
.s_addr
? inet_ntoa(src
.sin_addr
) : "*",
221 ntohs(src
.sin_port
));
222 g_string_append_printf(str
, "%15s %5d %5d %5d\n",
223 inet_ntoa(dst_addr
), ntohs(dst_port
),
224 so
->so_rcv
.sb_cc
, so
->so_snd
.sb_cc
);
227 for (so
= slirp
->udb
.so_next
; so
!= &slirp
->udb
; so
= so
->so_next
) {
228 if (so
->so_state
& SS_HOSTFWD
) {
229 snprintf(buf
, sizeof(buf
), " UDP[HOST_FORWARD]");
230 src_len
= sizeof(src
);
231 getsockname(so
->s
, (struct sockaddr
*)&src
, &src_len
);
232 dst_addr
= so
->so_laddr
;
233 dst_port
= so
->so_lport
;
235 snprintf(buf
, sizeof(buf
), " UDP[%d sec]",
236 (so
->so_expire
- curtime
) / 1000);
237 src
.sin_addr
= so
->so_laddr
;
238 src
.sin_port
= so
->so_lport
;
239 dst_addr
= so
->so_faddr
;
240 dst_port
= so
->so_fport
;
242 g_string_append_printf(str
, "%-19s %3d %15s %5d ", buf
, so
->s
,
243 src
.sin_addr
.s_addr
? inet_ntoa(src
.sin_addr
) : "*",
244 ntohs(src
.sin_port
));
245 g_string_append_printf(str
, "%15s %5d %5d %5d\n",
246 inet_ntoa(dst_addr
), ntohs(dst_port
),
247 so
->so_rcv
.sb_cc
, so
->so_snd
.sb_cc
);
250 for (so
= slirp
->icmp
.so_next
; so
!= &slirp
->icmp
; so
= so
->so_next
) {
251 snprintf(buf
, sizeof(buf
), " ICMP[%d sec]",
252 (so
->so_expire
- curtime
) / 1000);
253 src
.sin_addr
= so
->so_laddr
;
254 dst_addr
= so
->so_faddr
;
255 g_string_append_printf(str
, "%-19s %3d %15s - ", buf
, so
->s
,
256 src
.sin_addr
.s_addr
? inet_ntoa(src
.sin_addr
) : "*");
257 g_string_append_printf(str
, "%15s - %5d %5d\n", inet_ntoa(dst_addr
),
258 so
->so_rcv
.sb_cc
, so
->so_snd
.sb_cc
);
261 return g_string_free(str
, FALSE
);