slirp: replace error_report() with g_critical()
[qemu/ar7.git] / slirp / misc.c
blobee3492a2aed3e4033192f592d099b4f7dfb8cde5
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 #ifdef DEBUG
15 int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR;
16 #endif
18 inline void
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;
30 inline void
31 remque(void *a)
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)
48 return -1;
51 tmp_ptr = *ex_ptr;
52 *ex_ptr = g_new0(struct ex_list, 1);
53 (*ex_ptr)->ex_fport = port;
54 (*ex_ptr)->ex_addr = addr;
55 if (chardev) {
56 (*ex_ptr)->ex_chardev = chardev;
57 } else {
58 (*ex_ptr)->ex_exec = g_strdup(cmdline);
60 (*ex_ptr)->ex_next = tmp_ptr;
61 return 0;
65 #ifdef _WIN32
67 int
68 fork_exec(struct socket *so, const char *ex)
70 /* not implemented */
71 return 0;
74 #else
76 static int
77 slirp_socketpair_with_oob(int sv[2])
79 struct sockaddr_in addr = {
80 .sin_family = AF_INET,
81 .sin_port = 0,
82 .sin_addr.s_addr = INADDR_ANY,
84 socklen_t addrlen = sizeof(addr);
85 int ret, s;
87 sv[1] = -1;
88 s = qemu_socket(AF_INET, SOCK_STREAM, 0);
89 if (s < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
90 listen(s, 1) < 0 ||
91 getsockname(s, (struct sockaddr *)&addr, &addrlen) < 0) {
92 goto err;
95 sv[1] = qemu_socket(AF_INET, SOCK_STREAM, 0);
96 if (sv[1] < 0) {
97 goto err;
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
102 * until later on).
104 do {
105 ret = connect(sv[1], (struct sockaddr *)&addr, addrlen);
106 } while (ret < 0 && errno == EINTR);
107 if (ret < 0) {
108 goto err;
111 do {
112 sv[0] = accept(s, (struct sockaddr *)&addr, &addrlen);
113 } while (sv[0] < 0 && errno == EINTR);
114 if (sv[0] < 0) {
115 goto err;
118 closesocket(s);
119 return 0;
121 err:
122 g_critical("slirp_socketpair(): %s", strerror(errno));
123 if (s >= 0) {
124 closesocket(s);
126 if (sv[1] >= 0) {
127 closesocket(sv[1]);
129 return -1;
133 fork_exec(struct socket *so, const char *ex)
135 char **argv;
136 int opt, c, sp[2];
137 pid_t pid;
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) {
144 return 0;
147 pid = fork();
148 switch(pid) {
149 case -1:
150 error_report("Error: fork failed: %s", strerror(errno));
151 closesocket(sp[0]);
152 closesocket(sp[1]);
153 return 0;
155 case 0:
156 setsid();
157 dup2(sp[1], 0);
158 dup2(sp[1], 1);
159 dup2(sp[1], 2);
160 for (c = getdtablesize() - 1; c >= 3; c--)
161 close(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 */
170 exit(1);
172 default:
173 so->s = sp[0];
174 closesocket(sp[1]);
175 qemu_add_child_watch(pid);
176 socket_set_fast_reuse(so->s);
177 opt = 1;
178 qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
179 qemu_set_nonblock(so->s);
180 return 1;
183 #endif
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;
203 socklen_t src_len;
204 uint16_t dst_port;
205 struct socket *so;
206 const char *state;
207 char buf[20];
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];
218 } else {
219 state = "NONE";
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;
226 } else {
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;
248 } else {
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);