bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 1995 Danny Gasparovski. |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 3 | * |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 4 | * Please read the file COPYRIGHT for the |
| 5 | * terms and conditions of the copyright. |
| 6 | */ |
| 7 | |
Peter Maydell | 7df7482 | 2016-01-29 17:49:59 +0000 | [diff] [blame] | 8 | #include "qemu/osdep.h" |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 9 | #include <slirp.h> |
Jan Kiszka | 6dbe553 | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 10 | #include <libslirp.h> |
| 11 | |
Paolo Bonzini | 83c9089 | 2012-12-17 18:19:49 +0100 | [diff] [blame] | 12 | #include "monitor/monitor.h" |
Markus Armbruster | d49b683 | 2015-03-17 18:29:20 +0100 | [diff] [blame] | 13 | #include "qemu/error-report.h" |
Alex Bligh | 6a1751b | 2013-08-21 16:02:47 +0100 | [diff] [blame] | 14 | #include "qemu/main-loop.h" |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 15 | |
Jan Kiszka | 9f34949 | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 16 | #ifdef DEBUG |
| 17 | int slirp_debug = DBG_CALL|DBG_MISC|DBG_ERROR; |
| 18 | #endif |
| 19 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 20 | inline void |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 21 | insque(void *a, void *b) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 22 | { |
| 23 | register struct quehead *element = (struct quehead *) a; |
| 24 | register struct quehead *head = (struct quehead *) b; |
| 25 | element->qh_link = head->qh_link; |
| 26 | head->qh_link = (struct quehead *)element; |
| 27 | element->qh_rlink = (struct quehead *)head; |
| 28 | ((struct quehead *)(element->qh_link))->qh_rlink |
| 29 | = (struct quehead *)element; |
| 30 | } |
| 31 | |
| 32 | inline void |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 33 | remque(void *a) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 34 | { |
| 35 | register struct quehead *element = (struct quehead *) a; |
| 36 | ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; |
| 37 | ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link; |
| 38 | element->qh_rlink = NULL; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 39 | } |
| 40 | |
Jan Kiszka | a13a412 | 2009-06-24 14:42:28 +0200 | [diff] [blame] | 41 | int add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, |
| 42 | struct in_addr addr, int port) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 43 | { |
| 44 | struct ex_list *tmp_ptr; |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 45 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 46 | /* First, check if the port is "bound" */ |
| 47 | for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) { |
Jan Kiszka | a13a412 | 2009-06-24 14:42:28 +0200 | [diff] [blame] | 48 | if (port == tmp_ptr->ex_fport && |
| 49 | addr.s_addr == tmp_ptr->ex_addr.s_addr) |
| 50 | return -1; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 51 | } |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 52 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 53 | tmp_ptr = *ex_ptr; |
zhanghailiang | 2fd5d86 | 2014-08-19 16:30:17 +0800 | [diff] [blame] | 54 | *ex_ptr = g_new(struct ex_list, 1); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 55 | (*ex_ptr)->ex_fport = port; |
| 56 | (*ex_ptr)->ex_addr = addr; |
| 57 | (*ex_ptr)->ex_pty = do_pty; |
zhanghailiang | 2fd5d86 | 2014-08-19 16:30:17 +0800 | [diff] [blame] | 58 | (*ex_ptr)->ex_exec = (do_pty == 3) ? exec : g_strdup(exec); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 59 | (*ex_ptr)->ex_next = tmp_ptr; |
| 60 | return 0; |
| 61 | } |
| 62 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 63 | |
bellard | a3d4af0 | 2004-09-05 23:10:26 +0000 | [diff] [blame] | 64 | #ifdef _WIN32 |
| 65 | |
| 66 | int |
blueswir1 | 9634d90 | 2007-10-26 19:01:16 +0000 | [diff] [blame] | 67 | fork_exec(struct socket *so, const char *ex, int do_pty) |
bellard | a3d4af0 | 2004-09-05 23:10:26 +0000 | [diff] [blame] | 68 | { |
| 69 | /* not implemented */ |
| 70 | return 0; |
| 71 | } |
| 72 | |
| 73 | #else |
| 74 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 75 | /* |
| 76 | * XXX This is ugly |
| 77 | * We create and bind a socket, then fork off to another |
| 78 | * process, which connects to this socket, after which we |
| 79 | * exec the wanted program. If something (strange) happens, |
| 80 | * the accept() call could block us forever. |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 81 | * |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 82 | * do_pty = 0 Fork/exec inetd style |
| 83 | * do_pty = 1 Fork/exec using slirp.telnetd |
| 84 | * do_ptr = 2 Fork/exec using pty |
| 85 | */ |
| 86 | int |
blueswir1 | 9634d90 | 2007-10-26 19:01:16 +0000 | [diff] [blame] | 87 | fork_exec(struct socket *so, const char *ex, int do_pty) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 88 | { |
| 89 | int s; |
| 90 | struct sockaddr_in addr; |
balrog | 242acf3 | 2008-05-10 01:49:53 +0000 | [diff] [blame] | 91 | socklen_t addrlen = sizeof(addr); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 92 | int opt; |
blueswir1 | 7ccfb2e | 2008-09-14 06:45:34 +0000 | [diff] [blame] | 93 | const char *argv[256]; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 94 | /* don't want to clobber the original */ |
| 95 | char *bptr; |
blueswir1 | 9634d90 | 2007-10-26 19:01:16 +0000 | [diff] [blame] | 96 | const char *curarg; |
bellard | 7b91a17 | 2004-12-12 11:45:10 +0000 | [diff] [blame] | 97 | int c, i, ret; |
Paolo Bonzini | 4d54ec7 | 2011-03-09 18:21:10 +0100 | [diff] [blame] | 98 | pid_t pid; |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 99 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 100 | DEBUG_CALL("fork_exec"); |
Stefan Weil | ecc804c | 2015-08-29 09:12:35 +0200 | [diff] [blame] | 101 | DEBUG_ARG("so = %p", so); |
| 102 | DEBUG_ARG("ex = %p", ex); |
| 103 | DEBUG_ARG("do_pty = %x", do_pty); |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 104 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 105 | if (do_pty == 2) { |
balrog | 3f9b2b1 | 2007-11-13 01:56:12 +0000 | [diff] [blame] | 106 | return 0; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 107 | } else { |
| 108 | addr.sin_family = AF_INET; |
| 109 | addr.sin_port = 0; |
| 110 | addr.sin_addr.s_addr = INADDR_ANY; |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 111 | |
Kevin Wolf | 40ff6d7 | 2009-12-02 12:24:42 +0100 | [diff] [blame] | 112 | if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) < 0 || |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 113 | bind(s, (struct sockaddr *)&addr, addrlen) < 0 || |
| 114 | listen(s, 1) < 0) { |
Cole Robinson | 02d1608 | 2014-03-21 19:42:20 -0400 | [diff] [blame] | 115 | error_report("Error: inet socket: %s", strerror(errno)); |
bellard | 379ff53 | 2004-07-12 22:33:07 +0000 | [diff] [blame] | 116 | closesocket(s); |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 117 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 118 | return 0; |
| 119 | } |
| 120 | } |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 121 | |
Paolo Bonzini | 4d54ec7 | 2011-03-09 18:21:10 +0100 | [diff] [blame] | 122 | pid = fork(); |
| 123 | switch(pid) { |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 124 | case -1: |
Cole Robinson | 02d1608 | 2014-03-21 19:42:20 -0400 | [diff] [blame] | 125 | error_report("Error: fork failed: %s", strerror(errno)); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 126 | close(s); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 127 | return 0; |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 128 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 129 | case 0: |
Jan Kiszka | 565465f | 2011-07-20 12:20:17 +0200 | [diff] [blame] | 130 | setsid(); |
| 131 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 132 | /* Set the DISPLAY */ |
Stefan Weil | 9f1134d | 2012-01-05 14:18:45 +0100 | [diff] [blame] | 133 | getsockname(s, (struct sockaddr *)&addr, &addrlen); |
| 134 | close(s); |
| 135 | /* |
| 136 | * Connect to the socket |
| 137 | * XXX If any of these fail, we're in trouble! |
| 138 | */ |
| 139 | s = qemu_socket(AF_INET, SOCK_STREAM, 0); |
| 140 | addr.sin_addr = loopback_addr; |
| 141 | do { |
| 142 | ret = connect(s, (struct sockaddr *)&addr, addrlen); |
| 143 | } while (ret < 0 && errno == EINTR); |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 144 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 145 | dup2(s, 0); |
| 146 | dup2(s, 1); |
| 147 | dup2(s, 2); |
blueswir1 | 9634d90 | 2007-10-26 19:01:16 +0000 | [diff] [blame] | 148 | for (s = getdtablesize() - 1; s >= 3; s--) |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 149 | close(s); |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 150 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 151 | i = 0; |
Anthony Liguori | 7267c09 | 2011-08-20 22:09:37 -0500 | [diff] [blame] | 152 | bptr = g_strdup(ex); /* No need to free() this */ |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 153 | if (do_pty == 1) { |
| 154 | /* Setup "slirp.telnetd -x" */ |
| 155 | argv[i++] = "slirp.telnetd"; |
| 156 | argv[i++] = "-x"; |
| 157 | argv[i++] = bptr; |
| 158 | } else |
| 159 | do { |
| 160 | /* Change the string into argv[] */ |
| 161 | curarg = bptr; |
| 162 | while (*bptr != ' ' && *bptr != (char)0) |
| 163 | bptr++; |
| 164 | c = *bptr; |
| 165 | *bptr++ = (char)0; |
zhanghailiang | 2fd5d86 | 2014-08-19 16:30:17 +0800 | [diff] [blame] | 166 | argv[i++] = g_strdup(curarg); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 167 | } while (c); |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 168 | |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 169 | argv[i] = NULL; |
blueswir1 | 7ccfb2e | 2008-09-14 06:45:34 +0000 | [diff] [blame] | 170 | execvp(argv[0], (char **)argv); |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 171 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 172 | /* Ooops, failed, let's tell the user why */ |
Kirill A. Shutemov | f0d98b0 | 2009-12-25 18:19:18 +0000 | [diff] [blame] | 173 | fprintf(stderr, "Error: execvp of %s failed: %s\n", |
| 174 | argv[0], strerror(errno)); |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 175 | close(0); close(1); close(2); /* XXX */ |
| 176 | exit(1); |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 177 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 178 | default: |
Paolo Bonzini | 4d54ec7 | 2011-03-09 18:21:10 +0100 | [diff] [blame] | 179 | qemu_add_child_watch(pid); |
Stefan Weil | 9f1134d | 2012-01-05 14:18:45 +0100 | [diff] [blame] | 180 | /* |
| 181 | * XXX this could block us... |
| 182 | * XXX Should set a timer here, and if accept() doesn't |
| 183 | * return after X seconds, declare it a failure |
| 184 | * The only reason this will block forever is if socket() |
| 185 | * of connect() fail in the child process |
| 186 | */ |
| 187 | do { |
| 188 | so->s = accept(s, (struct sockaddr *)&addr, &addrlen); |
| 189 | } while (so->s < 0 && errno == EINTR); |
| 190 | closesocket(s); |
Sebastian Ottlik | aad1239 | 2013-10-02 12:23:15 +0200 | [diff] [blame] | 191 | socket_set_fast_reuse(so->s); |
Stefan Weil | 9f1134d | 2012-01-05 14:18:45 +0100 | [diff] [blame] | 192 | opt = 1; |
Stefan Weil | 9957fc7 | 2013-03-08 19:58:32 +0100 | [diff] [blame] | 193 | qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); |
Stefan Hajnoczi | f9e8cac | 2013-03-27 10:10:43 +0100 | [diff] [blame] | 194 | qemu_set_nonblock(so->s); |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 195 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 196 | /* Append the telnet options now */ |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 197 | if (so->so_m != NULL && do_pty == 1) { |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 198 | sbappend(so, so->so_m); |
blueswir1 | 511d2b1 | 2009-03-07 15:32:56 +0000 | [diff] [blame] | 199 | so->so_m = NULL; |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 200 | } |
ths | 3b46e62 | 2007-09-17 08:09:54 +0000 | [diff] [blame] | 201 | |
bellard | f0cbd3e | 2004-04-22 00:10:48 +0000 | [diff] [blame] | 202 | return 1; |
| 203 | } |
| 204 | } |
| 205 | #endif |
| 206 | |
Jan Kiszka | 9f8bd04 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 207 | void slirp_connection_info(Slirp *slirp, Monitor *mon) |
Jan Kiszka | 6dbe553 | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 208 | { |
| 209 | const char * const tcpstates[] = { |
| 210 | [TCPS_CLOSED] = "CLOSED", |
| 211 | [TCPS_LISTEN] = "LISTEN", |
| 212 | [TCPS_SYN_SENT] = "SYN_SENT", |
| 213 | [TCPS_SYN_RECEIVED] = "SYN_RCVD", |
| 214 | [TCPS_ESTABLISHED] = "ESTABLISHED", |
| 215 | [TCPS_CLOSE_WAIT] = "CLOSE_WAIT", |
| 216 | [TCPS_FIN_WAIT_1] = "FIN_WAIT_1", |
| 217 | [TCPS_CLOSING] = "CLOSING", |
| 218 | [TCPS_LAST_ACK] = "LAST_ACK", |
| 219 | [TCPS_FIN_WAIT_2] = "FIN_WAIT_2", |
| 220 | [TCPS_TIME_WAIT] = "TIME_WAIT", |
| 221 | }; |
| 222 | struct in_addr dst_addr; |
| 223 | struct sockaddr_in src; |
| 224 | socklen_t src_len; |
| 225 | uint16_t dst_port; |
| 226 | struct socket *so; |
| 227 | const char *state; |
| 228 | char buf[20]; |
Jan Kiszka | 6dbe553 | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 229 | |
| 230 | monitor_printf(mon, " Protocol[State] FD Source Address Port " |
| 231 | "Dest. Address Port RecvQ SendQ\n"); |
| 232 | |
Jan Kiszka | 460fec6 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 233 | for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) { |
Jan Kiszka | 6dbe553 | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 234 | if (so->so_state & SS_HOSTFWD) { |
| 235 | state = "HOST_FORWARD"; |
| 236 | } else if (so->so_tcpcb) { |
| 237 | state = tcpstates[so->so_tcpcb->t_state]; |
| 238 | } else { |
| 239 | state = "NONE"; |
| 240 | } |
| 241 | if (so->so_state & (SS_HOSTFWD | SS_INCOMING)) { |
| 242 | src_len = sizeof(src); |
| 243 | getsockname(so->s, (struct sockaddr *)&src, &src_len); |
| 244 | dst_addr = so->so_laddr; |
| 245 | dst_port = so->so_lport; |
| 246 | } else { |
| 247 | src.sin_addr = so->so_laddr; |
| 248 | src.sin_port = so->so_lport; |
| 249 | dst_addr = so->so_faddr; |
| 250 | dst_port = so->so_fport; |
| 251 | } |
Alon Levy | f293d8b | 2012-02-24 13:33:49 +0200 | [diff] [blame] | 252 | snprintf(buf, sizeof(buf), " TCP[%s]", state); |
| 253 | monitor_printf(mon, "%-19s %3d %15s %5d ", buf, so->s, |
Jan Kiszka | 6dbe553 | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 254 | src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*", |
| 255 | ntohs(src.sin_port)); |
| 256 | monitor_printf(mon, "%15s %5d %5d %5d\n", |
| 257 | inet_ntoa(dst_addr), ntohs(dst_port), |
| 258 | so->so_rcv.sb_cc, so->so_snd.sb_cc); |
| 259 | } |
| 260 | |
Jan Kiszka | 460fec6 | 2009-06-24 14:42:31 +0200 | [diff] [blame] | 261 | for (so = slirp->udb.so_next; so != &slirp->udb; so = so->so_next) { |
Jan Kiszka | 6dbe553 | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 262 | if (so->so_state & SS_HOSTFWD) { |
Alon Levy | f293d8b | 2012-02-24 13:33:49 +0200 | [diff] [blame] | 263 | snprintf(buf, sizeof(buf), " UDP[HOST_FORWARD]"); |
Jan Kiszka | 6dbe553 | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 264 | src_len = sizeof(src); |
| 265 | getsockname(so->s, (struct sockaddr *)&src, &src_len); |
| 266 | dst_addr = so->so_laddr; |
| 267 | dst_port = so->so_lport; |
| 268 | } else { |
Alon Levy | f293d8b | 2012-02-24 13:33:49 +0200 | [diff] [blame] | 269 | snprintf(buf, sizeof(buf), " UDP[%d sec]", |
Jan Kiszka | 6dbe553 | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 270 | (so->so_expire - curtime) / 1000); |
| 271 | src.sin_addr = so->so_laddr; |
| 272 | src.sin_port = so->so_lport; |
| 273 | dst_addr = so->so_faddr; |
| 274 | dst_port = so->so_fport; |
| 275 | } |
Alon Levy | f293d8b | 2012-02-24 13:33:49 +0200 | [diff] [blame] | 276 | monitor_printf(mon, "%-19s %3d %15s %5d ", buf, so->s, |
Jan Kiszka | 6dbe553 | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 277 | src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*", |
| 278 | ntohs(src.sin_port)); |
| 279 | monitor_printf(mon, "%15s %5d %5d %5d\n", |
| 280 | inet_ntoa(dst_addr), ntohs(dst_port), |
| 281 | so->so_rcv.sb_cc, so->so_snd.sb_cc); |
| 282 | } |
Jan Kiszka | e6d43cf | 2011-07-20 12:20:18 +0200 | [diff] [blame] | 283 | |
| 284 | for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so->so_next) { |
Alon Levy | f293d8b | 2012-02-24 13:33:49 +0200 | [diff] [blame] | 285 | snprintf(buf, sizeof(buf), " ICMP[%d sec]", |
Jan Kiszka | e6d43cf | 2011-07-20 12:20:18 +0200 | [diff] [blame] | 286 | (so->so_expire - curtime) / 1000); |
| 287 | src.sin_addr = so->so_laddr; |
| 288 | dst_addr = so->so_faddr; |
Alon Levy | f293d8b | 2012-02-24 13:33:49 +0200 | [diff] [blame] | 289 | monitor_printf(mon, "%-19s %3d %15s - ", buf, so->s, |
Jan Kiszka | e6d43cf | 2011-07-20 12:20:18 +0200 | [diff] [blame] | 290 | src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*"); |
| 291 | monitor_printf(mon, "%15s - %5d %5d\n", inet_ntoa(dst_addr), |
| 292 | so->so_rcv.sb_cc, so->so_snd.sb_cc); |
| 293 | } |
Jan Kiszka | 6dbe553 | 2009-06-24 14:42:29 +0200 | [diff] [blame] | 294 | } |