Commit e1c5a2b33409b9795fa58bf389eac855981330a5

Authored by aliguori
1 parent 4dda4063

Redirect slirp traffic to/from qemu character device (Gleb Natapov)

Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6240 c046a42c-6fe2-441c-8c8c-71466251a162
slirp/libslirp.h
@@ -20,13 +20,16 @@ void slirp_output(const uint8_t *pkt, int pkt_len); @@ -20,13 +20,16 @@ void slirp_output(const uint8_t *pkt, int pkt_len);
20 20
21 int slirp_redir(int is_udp, int host_port, 21 int slirp_redir(int is_udp, int host_port,
22 struct in_addr guest_addr, int guest_port); 22 struct in_addr guest_addr, int guest_port);
23 -int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, 23 +int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
24 int guest_port); 24 int guest_port);
25 25
26 extern const char *tftp_prefix; 26 extern const char *tftp_prefix;
27 extern char slirp_hostname[33]; 27 extern char slirp_hostname[33];
28 28
29 void slirp_stats(void); 29 void slirp_stats(void);
  30 +void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
  31 + int size);
  32 +size_t slirp_socket_can_recv(int addr_low_byte, int guest_port);
30 33
31 #ifdef __cplusplus 34 #ifdef __cplusplus
32 } 35 }
slirp/main.h
@@ -51,3 +51,4 @@ extern uint8_t client_ethaddr[6]; @@ -51,3 +51,4 @@ extern uint8_t client_ethaddr[6];
51 #endif 51 #endif
52 52
53 void if_encap(const uint8_t *ip_data, int ip_data_len); 53 void if_encap(const uint8_t *ip_data, int ip_data_len);
  54 +ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags);
slirp/misc.c
@@ -169,7 +169,7 @@ add_exec(ex_ptr, do_pty, exec, addr, port) @@ -169,7 +169,7 @@ add_exec(ex_ptr, do_pty, exec, addr, port)
169 (*ex_ptr)->ex_fport = port; 169 (*ex_ptr)->ex_fport = port;
170 (*ex_ptr)->ex_addr = addr; 170 (*ex_ptr)->ex_addr = addr;
171 (*ex_ptr)->ex_pty = do_pty; 171 (*ex_ptr)->ex_pty = do_pty;
172 - (*ex_ptr)->ex_exec = strdup(exec); 172 + (*ex_ptr)->ex_exec = (do_pty == 3) ? exec : strdup(exec);
173 (*ex_ptr)->ex_next = tmp_ptr; 173 (*ex_ptr)->ex_next = tmp_ptr;
174 return 0; 174 return 0;
175 } 175 }
slirp/sbuf.c
@@ -108,7 +108,7 @@ sbappend(so, m) @@ -108,7 +108,7 @@ sbappend(so, m)
108 * ottherwise it'll arrive out of order, and hence corrupt 108 * ottherwise it'll arrive out of order, and hence corrupt
109 */ 109 */
110 if (!so->so_rcv.sb_cc) 110 if (!so->so_rcv.sb_cc)
111 - ret = send(so->s, m->m_data, m->m_len, 0); 111 + ret = slirp_send(so, m->m_data, m->m_len, 0);
112 112
113 if (ret <= 0) { 113 if (ret <= 0) {
114 /* 114 /*
slirp/slirp.c
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE. 22 * THE SOFTWARE.
23 */ 23 */
  24 +#include "qemu-common.h"
24 #include "slirp.h" 25 #include "slirp.h"
25 26
26 /* host address */ 27 /* host address */
@@ -736,9 +737,69 @@ int slirp_redir(int is_udp, int host_port, @@ -736,9 +737,69 @@ int slirp_redir(int is_udp, int host_port,
736 return 0; 737 return 0;
737 } 738 }
738 739
739 -int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, 740 +int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
740 int guest_port) 741 int guest_port)
741 { 742 {
742 return add_exec(&exec_list, do_pty, (char *)args, 743 return add_exec(&exec_list, do_pty, (char *)args,
743 addr_low_byte, htons(guest_port)); 744 addr_low_byte, htons(guest_port));
744 } 745 }
  746 +
  747 +ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
  748 +{
  749 + if (so->s == -1 && so->extra) {
  750 + qemu_chr_write(so->extra, buf, len);
  751 + return len;
  752 + }
  753 +
  754 + return send(so->s, buf, len, flags);
  755 +}
  756 +
  757 +static struct socket *slirp_find_ctl_socket(int addr_low_byte, int guest_port)
  758 +{
  759 + struct socket *so;
  760 +
  761 + for (so = tcb.so_next; so != &tcb; so = so->so_next) {
  762 + if ((so->so_faddr.s_addr & htonl(0xffffff00)) ==
  763 + special_addr.s_addr
  764 + && (ntohl(so->so_faddr.s_addr) & 0xff) ==
  765 + addr_low_byte
  766 + && htons(so->so_fport) == guest_port)
  767 + return so;
  768 + }
  769 +
  770 + return NULL;
  771 +}
  772 +
  773 +size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
  774 +{
  775 + struct iovec iov[2];
  776 + struct socket *so;
  777 +
  778 + if (!link_up)
  779 + return 0;
  780 +
  781 + so = slirp_find_ctl_socket(addr_low_byte, guest_port);
  782 +
  783 + if (!so || so->so_state & SS_NOFDREF)
  784 + return 0;
  785 +
  786 + if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
  787 + return 0;
  788 +
  789 + return sopreprbuf(so, iov, NULL);
  790 +}
  791 +
  792 +void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
  793 + int size)
  794 +{
  795 + int ret;
  796 + struct socket *so = slirp_find_ctl_socket(addr_low_byte, guest_port);
  797 +
  798 + if (!so)
  799 + return;
  800 +
  801 + ret = soreadbuf(so, buf, size);
  802 +
  803 + if (ret > 0)
  804 + tcp_output(sototcpcb(so));
  805 +}
slirp/socket.c
@@ -5,13 +5,13 @@ @@ -5,13 +5,13 @@
5 * terms and conditions of the copyright. 5 * terms and conditions of the copyright.
6 */ 6 */
7 7
  8 +#include "qemu-common.h"
8 #define WANT_SYS_IOCTL_H 9 #define WANT_SYS_IOCTL_H
9 #include <slirp.h> 10 #include <slirp.h>
10 #include "ip_icmp.h" 11 #include "ip_icmp.h"
11 #ifdef __sun__ 12 #ifdef __sun__
12 #include <sys/filio.h> 13 #include <sys/filio.h>
13 #endif 14 #endif
14 -#include "qemu-common.h"  
15 15
16 static void sofcantrcvmore(struct socket *so); 16 static void sofcantrcvmore(struct socket *so);
17 static void sofcantsendmore(struct socket *so); 17 static void sofcantsendmore(struct socket *so);
@@ -91,31 +91,21 @@ sofree(so) @@ -91,31 +91,21 @@ sofree(so)
91 free(so); 91 free(so);
92 } 92 }
93 93
94 -/*  
95 - * Read from so's socket into sb_snd, updating all relevant sbuf fields  
96 - * NOTE: This will only be called if it is select()ed for reading, so  
97 - * a read() of 0 (or less) means it's disconnected  
98 - */  
99 -int  
100 -soread(so)  
101 - struct socket *so; 94 +size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np)
102 { 95 {
103 - int n, nn, lss, total; 96 + int n, lss, total;
104 struct sbuf *sb = &so->so_snd; 97 struct sbuf *sb = &so->so_snd;
105 int len = sb->sb_datalen - sb->sb_cc; 98 int len = sb->sb_datalen - sb->sb_cc;
106 - struct iovec iov[2];  
107 int mss = so->so_tcpcb->t_maxseg; 99 int mss = so->so_tcpcb->t_maxseg;
108 100
109 - DEBUG_CALL("soread"); 101 + DEBUG_CALL("sopreprbuf");
110 DEBUG_ARG("so = %lx", (long )so); 102 DEBUG_ARG("so = %lx", (long )so);
111 103
112 - /*  
113 - * No need to check if there's enough room to read.  
114 - * soread wouldn't have been called if there weren't  
115 - */  
116 -  
117 len = sb->sb_datalen - sb->sb_cc; 104 len = sb->sb_datalen - sb->sb_cc;
118 105
  106 + if (len <= 0)
  107 + return 0;
  108 +
119 iov[0].iov_base = sb->sb_wptr; 109 iov[0].iov_base = sb->sb_wptr;
120 iov[1].iov_base = NULL; 110 iov[1].iov_base = NULL;
121 iov[1].iov_len = 0; 111 iov[1].iov_len = 0;
@@ -156,6 +146,33 @@ soread(so) @@ -156,6 +146,33 @@ soread(so)
156 n = 1; 146 n = 1;
157 } 147 }
158 } 148 }
  149 + if (np)
  150 + *np = n;
  151 +
  152 + return iov[0].iov_len + (n - 1) * iov[1].iov_len;
  153 +}
  154 +
  155 +/*
  156 + * Read from so's socket into sb_snd, updating all relevant sbuf fields
  157 + * NOTE: This will only be called if it is select()ed for reading, so
  158 + * a read() of 0 (or less) means it's disconnected
  159 + */
  160 +int
  161 +soread(so)
  162 + struct socket *so;
  163 +{
  164 + int n, nn;
  165 + struct sbuf *sb = &so->so_snd;
  166 + struct iovec iov[2];
  167 +
  168 + DEBUG_CALL("soread");
  169 + DEBUG_ARG("so = %lx", (long )so);
  170 +
  171 + /*
  172 + * No need to check if there's enough room to read.
  173 + * soread wouldn't have been called if there weren't
  174 + */
  175 + sopreprbuf(so, iov, &n);
159 176
160 #ifdef HAVE_READV 177 #ifdef HAVE_READV
161 nn = readv(so->s, (struct iovec *)iov, n); 178 nn = readv(so->s, (struct iovec *)iov, n);
@@ -202,6 +219,48 @@ soread(so) @@ -202,6 +219,48 @@ soread(so)
202 return nn; 219 return nn;
203 } 220 }
204 221
  222 +int soreadbuf(struct socket *so, const char *buf, int size)
  223 +{
  224 + int n, nn, copy = size;
  225 + struct sbuf *sb = &so->so_snd;
  226 + struct iovec iov[2];
  227 +
  228 + DEBUG_CALL("soreadbuf");
  229 + DEBUG_ARG("so = %lx", (long )so);
  230 +
  231 + /*
  232 + * No need to check if there's enough room to read.
  233 + * soread wouldn't have been called if there weren't
  234 + */
  235 + if (sopreprbuf(so, iov, &n) < size)
  236 + goto err;
  237 +
  238 + nn = MIN(iov[0].iov_len, copy);
  239 + memcpy(iov[0].iov_base, buf, nn);
  240 +
  241 + copy -= nn;
  242 + buf += nn;
  243 +
  244 + if (copy == 0)
  245 + goto done;
  246 +
  247 + memcpy(iov[1].iov_base, buf, copy);
  248 +
  249 +done:
  250 + /* Update fields */
  251 + sb->sb_cc += size;
  252 + sb->sb_wptr += size;
  253 + if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
  254 + sb->sb_wptr -= sb->sb_datalen;
  255 + return size;
  256 +err:
  257 +
  258 + sofcantrcvmore(so);
  259 + tcp_sockclosed(sototcpcb(so));
  260 + fprintf(stderr, "soreadbuf buffer to small");
  261 + return -1;
  262 +}
  263 +
205 /* 264 /*
206 * Get urgent data 265 * Get urgent data
207 * 266 *
@@ -255,7 +314,7 @@ sosendoob(so) @@ -255,7 +314,7 @@ sosendoob(so)
255 314
256 if (sb->sb_rptr < sb->sb_wptr) { 315 if (sb->sb_rptr < sb->sb_wptr) {
257 /* We can send it directly */ 316 /* We can send it directly */
258 - n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */ 317 + n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
259 so->so_urgc -= n; 318 so->so_urgc -= n;
260 319
261 DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); 320 DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
@@ -276,7 +335,7 @@ sosendoob(so) @@ -276,7 +335,7 @@ sosendoob(so)
276 so->so_urgc -= n; 335 so->so_urgc -= n;
277 len += n; 336 len += n;
278 } 337 }
279 - n = send(so->s, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ 338 + n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
280 #ifdef DEBUG 339 #ifdef DEBUG
281 if (n != len) 340 if (n != len)
282 DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); 341 DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
@@ -348,7 +407,7 @@ sowrite(so) @@ -348,7 +407,7 @@ sowrite(so)
348 407
349 DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); 408 DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
350 #else 409 #else
351 - nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0); 410 + nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0);
352 #endif 411 #endif
353 /* This should never happen, but people tell me it does *shrug* */ 412 /* This should never happen, but people tell me it does *shrug* */
354 if (nn < 0 && (errno == EAGAIN || errno == EINTR)) 413 if (nn < 0 && (errno == EAGAIN || errno == EINTR))
@@ -365,7 +424,7 @@ sowrite(so) @@ -365,7 +424,7 @@ sowrite(so)
365 #ifndef HAVE_READV 424 #ifndef HAVE_READV
366 if (n == 2 && nn == iov[0].iov_len) { 425 if (n == 2 && nn == iov[0].iov_len) {
367 int ret; 426 int ret;
368 - ret = send(so->s, iov[1].iov_base, iov[1].iov_len,0); 427 + ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0);
369 if (ret > 0) 428 if (ret > 0)
370 nn += ret; 429 nn += ret;
371 } 430 }
slirp/socket.h
@@ -87,5 +87,7 @@ void soisfconnecting _P((register struct socket *)); @@ -87,5 +87,7 @@ void soisfconnecting _P((register struct socket *));
87 void soisfconnected _P((register struct socket *)); 87 void soisfconnected _P((register struct socket *));
88 void soisfdisconnected _P((struct socket *)); 88 void soisfdisconnected _P((struct socket *));
89 void sofwdrain _P((struct socket *)); 89 void sofwdrain _P((struct socket *));
  90 +size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np);
  91 +int soreadbuf(struct socket *so, const char *buf, int size);
90 92
91 #endif /* _SOCKET_H_ */ 93 #endif /* _SOCKET_H_ */
slirp/tcp_subr.c
@@ -1281,6 +1281,11 @@ tcp_ctl(so) @@ -1281,6 +1281,11 @@ tcp_ctl(so)
1281 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { 1281 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
1282 if (ex_ptr->ex_fport == so->so_fport && 1282 if (ex_ptr->ex_fport == so->so_fport &&
1283 command == ex_ptr->ex_addr) { 1283 command == ex_ptr->ex_addr) {
  1284 + if (ex_ptr->ex_pty == 3) {
  1285 + so->s = -1;
  1286 + so->extra = ex_ptr->ex_exec;
  1287 + return 1;
  1288 + }
1284 do_pty = ex_ptr->ex_pty; 1289 do_pty = ex_ptr->ex_pty;
1285 goto do_exec; 1290 goto do_exec;
1286 } 1291 }