s390: avoid potential null dereference in s390_pcihost_unplug()
[qemu/ar7.git] / slirp / misc.c
blobeae9596a55d3e92dfac81cac1ef9e65214de269c
1 /*
2 * Copyright (c) 1995 Danny Gasparovski.
4 * Please read the file COPYRIGHT for the
5 * terms and conditions of the copyright.
6 */
8 #include "qemu/osdep.h"
9 #include "slirp.h"
10 #include "libslirp.h"
11 #include "qemu/error-report.h"
12 #include "qemu/main-loop.h"
14 inline void
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;
26 inline void
27 remque(void *a)
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;
40 tmp_ptr = *ex_ptr;
41 *ex_ptr = g_new0(struct gfwd_list, 1);
42 (*ex_ptr)->ex_fport = port;
43 (*ex_ptr)->ex_addr = addr;
44 if (chardev) {
45 (*ex_ptr)->ex_chardev = chardev;
46 } else {
47 (*ex_ptr)->ex_exec = g_strdup(cmdline);
49 (*ex_ptr)->ex_next = tmp_ptr;
50 return 0;
54 static int
55 slirp_socketpair_with_oob(int sv[2])
57 struct sockaddr_in addr = {
58 .sin_family = AF_INET,
59 .sin_port = 0,
60 .sin_addr.s_addr = INADDR_ANY,
62 socklen_t addrlen = sizeof(addr);
63 int ret, s;
65 sv[1] = -1;
66 s = qemu_socket(AF_INET, SOCK_STREAM, 0);
67 if (s < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
68 listen(s, 1) < 0 ||
69 getsockname(s, (struct sockaddr *)&addr, &addrlen) < 0) {
70 goto err;
73 sv[1] = qemu_socket(AF_INET, SOCK_STREAM, 0);
74 if (sv[1] < 0) {
75 goto err;
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
80 * until later on).
82 do {
83 ret = connect(sv[1], (struct sockaddr *)&addr, addrlen);
84 } while (ret < 0 && errno == EINTR);
85 if (ret < 0) {
86 goto err;
89 do {
90 sv[0] = accept(s, (struct sockaddr *)&addr, &addrlen);
91 } while (sv[0] < 0 && errno == EINTR);
92 if (sv[0] < 0) {
93 goto err;
96 closesocket(s);
97 return 0;
99 err:
100 g_critical("slirp_socketpair(): %s", strerror(errno));
101 if (s >= 0) {
102 closesocket(s);
104 if (sv[1] >= 0) {
105 closesocket(sv[1]);
107 return -1;
110 static void
111 fork_exec_child_setup(gpointer data)
113 #ifndef _WIN32
114 setsid();
115 #endif
119 fork_exec(struct socket *so, const char *ex)
121 GError *err = NULL;
122 char **argv;
123 int opt, sp[2];
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) {
130 return 0;
133 argv = g_strsplit(ex, " ", -1);
134 g_spawn_async_with_fds(NULL /* cwd */,
135 argv,
136 NULL /* env */,
137 G_SPAWN_SEARCH_PATH,
138 fork_exec_child_setup, NULL /* data */,
139 NULL /* child_pid */,
140 sp[1], sp[1], sp[1],
141 &err);
142 g_strfreev(argv);
144 if (err) {
145 g_critical("fork_exec: %s", err->message);
146 g_error_free(err);
147 closesocket(sp[0]);
148 closesocket(sp[1]);
149 return 0;
152 so->s = sp[0];
153 closesocket(sp[1]);
154 socket_set_fast_reuse(so->s);
155 opt = 1;
156 qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
157 qemu_set_nonblock(so->s);
158 return 1;
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;
179 socklen_t src_len;
180 uint16_t dst_port;
181 struct socket *so;
182 const char *state;
183 char buf[20];
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];
194 } else {
195 state = "NONE";
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;
202 } else {
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;
224 } else {
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);