Revision 0bab00f3 vl.c
b/vl.c | ||
---|---|---|
2130 | 2130 |
} |
2131 | 2131 |
#endif |
2132 | 2132 |
|
2133 |
/***********************************************************/ |
|
2134 |
/* UDP Net console */ |
|
2135 |
|
|
2136 |
typedef struct { |
|
2137 |
IOCanRWHandler *fd_can_read; |
|
2138 |
IOReadHandler *fd_read; |
|
2139 |
void *fd_opaque; |
|
2140 |
int fd; |
|
2141 |
struct sockaddr_in daddr; |
|
2142 |
char buf[1024]; |
|
2143 |
int bufcnt; |
|
2144 |
int bufptr; |
|
2145 |
int max_size; |
|
2146 |
} NetCharDriver; |
|
2147 |
|
|
2148 |
static int udp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) |
|
2149 |
{ |
|
2150 |
NetCharDriver *s = chr->opaque; |
|
2151 |
|
|
2152 |
return sendto(s->fd, buf, len, 0, |
|
2153 |
(struct sockaddr *)&s->daddr, sizeof(struct sockaddr_in)); |
|
2154 |
} |
|
2155 |
|
|
2156 |
static int udp_chr_read_poll(void *opaque) |
|
2157 |
{ |
|
2158 |
CharDriverState *chr = opaque; |
|
2159 |
NetCharDriver *s = chr->opaque; |
|
2160 |
|
|
2161 |
s->max_size = s->fd_can_read(s->fd_opaque); |
|
2162 |
|
|
2163 |
/* If there were any stray characters in the queue process them |
|
2164 |
* first |
|
2165 |
*/ |
|
2166 |
while (s->max_size > 0 && s->bufptr < s->bufcnt) { |
|
2167 |
s->fd_read(s->fd_opaque, &s->buf[s->bufptr], 1); |
|
2168 |
s->bufptr++; |
|
2169 |
s->max_size = s->fd_can_read(s->fd_opaque); |
|
2170 |
} |
|
2171 |
return s->max_size; |
|
2172 |
} |
|
2173 |
|
|
2174 |
static void udp_chr_read(void *opaque) |
|
2175 |
{ |
|
2176 |
CharDriverState *chr = opaque; |
|
2177 |
NetCharDriver *s = chr->opaque; |
|
2178 |
|
|
2179 |
if (s->max_size == 0) |
|
2180 |
return; |
|
2181 |
s->bufcnt = recv(s->fd, s->buf, sizeof(s->buf), 0); |
|
2182 |
s->bufptr = s->bufcnt; |
|
2183 |
if (s->bufcnt <= 0) |
|
2184 |
return; |
|
2185 |
|
|
2186 |
s->bufptr = 0; |
|
2187 |
while (s->max_size > 0 && s->bufptr < s->bufcnt) { |
|
2188 |
s->fd_read(s->fd_opaque, &s->buf[s->bufptr], 1); |
|
2189 |
s->bufptr++; |
|
2190 |
s->max_size = s->fd_can_read(s->fd_opaque); |
|
2191 |
} |
|
2192 |
} |
|
2193 |
|
|
2194 |
static void udp_chr_add_read_handler(CharDriverState *chr, |
|
2195 |
IOCanRWHandler *fd_can_read, |
|
2196 |
IOReadHandler *fd_read, void *opaque) |
|
2197 |
{ |
|
2198 |
NetCharDriver *s = chr->opaque; |
|
2199 |
|
|
2200 |
if (s->fd >= 0) { |
|
2201 |
s->fd_can_read = fd_can_read; |
|
2202 |
s->fd_read = fd_read; |
|
2203 |
s->fd_opaque = opaque; |
|
2204 |
qemu_set_fd_handler2(s->fd, udp_chr_read_poll, |
|
2205 |
udp_chr_read, NULL, chr); |
|
2206 |
} |
|
2207 |
} |
|
2208 |
|
|
2209 |
int parse_host_port(struct sockaddr_in *saddr, const char *str); |
|
2210 |
|
|
2211 |
CharDriverState *qemu_chr_open_udp(const char *def) |
|
2212 |
{ |
|
2213 |
CharDriverState *chr = NULL; |
|
2214 |
NetCharDriver *s = NULL; |
|
2215 |
int fd = -1; |
|
2216 |
int con_type; |
|
2217 |
struct sockaddr_in addr; |
|
2218 |
const char *p, *r; |
|
2219 |
int port; |
|
2220 |
|
|
2221 |
chr = qemu_mallocz(sizeof(CharDriverState)); |
|
2222 |
if (!chr) |
|
2223 |
goto return_err; |
|
2224 |
s = qemu_mallocz(sizeof(NetCharDriver)); |
|
2225 |
if (!s) |
|
2226 |
goto return_err; |
|
2227 |
|
|
2228 |
fd = socket(PF_INET, SOCK_DGRAM, 0); |
|
2229 |
if (fd < 0) { |
|
2230 |
perror("socket(PF_INET, SOCK_DGRAM)"); |
|
2231 |
goto return_err; |
|
2232 |
} |
|
2233 |
|
|
2234 |
/* There are three types of port definitions |
|
2235 |
* 1) udp:remote_port |
|
2236 |
* Juse use 0.0.0.0 for the IP and send to remote |
|
2237 |
* 2) udp:remote_host:port |
|
2238 |
* Use a IP and send traffic to remote |
|
2239 |
* 3) udp:local_port:remote_host:remote_port |
|
2240 |
* Use local_port as the originator + #2 |
|
2241 |
*/ |
|
2242 |
con_type = 0; |
|
2243 |
p = def; |
|
2244 |
while ((p = strchr(p, ':'))) { |
|
2245 |
p++; |
|
2246 |
con_type++; |
|
2247 |
} |
|
2248 |
|
|
2249 |
p = def; |
|
2250 |
memset(&addr,0,sizeof(addr)); |
|
2251 |
addr.sin_family = AF_INET; |
|
2252 |
addr.sin_addr.s_addr = htonl(INADDR_ANY); |
|
2253 |
s->daddr.sin_family = AF_INET; |
|
2254 |
s->daddr.sin_addr.s_addr = htonl(INADDR_ANY); |
|
2255 |
|
|
2256 |
switch (con_type) { |
|
2257 |
case 0: |
|
2258 |
port = strtol(p, (char **)&r, 0); |
|
2259 |
if (r == p) { |
|
2260 |
fprintf(stderr, "Error parsing port number\n"); |
|
2261 |
goto return_err; |
|
2262 |
} |
|
2263 |
s->daddr.sin_port = htons((short)port); |
|
2264 |
break; |
|
2265 |
case 2: |
|
2266 |
port = strtol(p, (char **)&r, 0); |
|
2267 |
if (r == p) { |
|
2268 |
fprintf(stderr, "Error parsing port number\n"); |
|
2269 |
goto return_err; |
|
2270 |
} |
|
2271 |
addr.sin_port = htons((short)port); |
|
2272 |
p = r + 1; |
|
2273 |
/* Fall through to case 1 now that we have the local port */ |
|
2274 |
case 1: |
|
2275 |
if (parse_host_port(&s->daddr, p) < 0) { |
|
2276 |
fprintf(stderr, "Error parsing host name and port\n"); |
|
2277 |
goto return_err; |
|
2278 |
} |
|
2279 |
break; |
|
2280 |
default: |
|
2281 |
fprintf(stderr, "Too many ':' characters\n"); |
|
2282 |
goto return_err; |
|
2283 |
} |
|
2284 |
|
|
2285 |
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) |
|
2286 |
{ |
|
2287 |
perror("bind"); |
|
2288 |
goto return_err; |
|
2289 |
} |
|
2290 |
|
|
2291 |
s->fd = fd; |
|
2292 |
s->bufcnt = 0; |
|
2293 |
s->bufptr = 0; |
|
2294 |
chr->opaque = s; |
|
2295 |
chr->chr_write = udp_chr_write; |
|
2296 |
chr->chr_add_read_handler = udp_chr_add_read_handler; |
|
2297 |
return chr; |
|
2298 |
|
|
2299 |
return_err: |
|
2300 |
if (chr) |
|
2301 |
free(chr); |
|
2302 |
if (s) |
|
2303 |
free(s); |
|
2304 |
if (fd >= 0) |
|
2305 |
closesocket(fd); |
|
2306 |
return NULL; |
|
2307 |
} |
|
2308 |
|
|
2309 |
/***********************************************************/ |
|
2310 |
/* TCP Net console */ |
|
2311 |
|
|
2312 |
typedef struct { |
|
2313 |
IOCanRWHandler *fd_can_read; |
|
2314 |
IOReadHandler *fd_read; |
|
2315 |
void *fd_opaque; |
|
2316 |
int fd, listen_fd; |
|
2317 |
int connected; |
|
2318 |
int max_size; |
|
2319 |
} TCPCharDriver; |
|
2320 |
|
|
2321 |
static void tcp_chr_accept(void *opaque); |
|
2322 |
|
|
2323 |
static int tcp_chr_write(CharDriverState *chr, const uint8_t *buf, int len) |
|
2324 |
{ |
|
2325 |
TCPCharDriver *s = chr->opaque; |
|
2326 |
if (s->connected) { |
|
2327 |
return send_all(s->fd, buf, len); |
|
2328 |
} else { |
|
2329 |
/* XXX: indicate an error ? */ |
|
2330 |
return len; |
|
2331 |
} |
|
2332 |
} |
|
2333 |
|
|
2334 |
static int tcp_chr_read_poll(void *opaque) |
|
2335 |
{ |
|
2336 |
CharDriverState *chr = opaque; |
|
2337 |
TCPCharDriver *s = chr->opaque; |
|
2338 |
if (!s->connected) |
|
2339 |
return 0; |
|
2340 |
s->max_size = s->fd_can_read(s->fd_opaque); |
|
2341 |
return s->max_size; |
|
2342 |
} |
|
2343 |
|
|
2344 |
static void tcp_chr_read(void *opaque) |
|
2345 |
{ |
|
2346 |
CharDriverState *chr = opaque; |
|
2347 |
TCPCharDriver *s = chr->opaque; |
|
2348 |
uint8_t buf[1024]; |
|
2349 |
int len, size; |
|
2350 |
|
|
2351 |
if (!s->connected || s->max_size <= 0) |
|
2352 |
return; |
|
2353 |
len = sizeof(buf); |
|
2354 |
if (len > s->max_size) |
|
2355 |
len = s->max_size; |
|
2356 |
size = recv(s->fd, buf, len, 0); |
|
2357 |
if (size == 0) { |
|
2358 |
/* connection closed */ |
|
2359 |
s->connected = 0; |
|
2360 |
if (s->listen_fd >= 0) { |
|
2361 |
qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); |
|
2362 |
} |
|
2363 |
qemu_set_fd_handler(s->fd, NULL, NULL, NULL); |
|
2364 |
closesocket(s->fd); |
|
2365 |
s->fd = -1; |
|
2366 |
} else if (size > 0) { |
|
2367 |
s->fd_read(s->fd_opaque, buf, size); |
|
2368 |
} |
|
2369 |
} |
|
2370 |
|
|
2371 |
static void tcp_chr_add_read_handler(CharDriverState *chr, |
|
2372 |
IOCanRWHandler *fd_can_read, |
|
2373 |
IOReadHandler *fd_read, void *opaque) |
|
2374 |
{ |
|
2375 |
TCPCharDriver *s = chr->opaque; |
|
2376 |
|
|
2377 |
s->fd_can_read = fd_can_read; |
|
2378 |
s->fd_read = fd_read; |
|
2379 |
s->fd_opaque = opaque; |
|
2380 |
} |
|
2381 |
|
|
2382 |
static void tcp_chr_connect(void *opaque) |
|
2383 |
{ |
|
2384 |
CharDriverState *chr = opaque; |
|
2385 |
TCPCharDriver *s = chr->opaque; |
|
2386 |
|
|
2387 |
s->connected = 1; |
|
2388 |
qemu_set_fd_handler2(s->fd, tcp_chr_read_poll, |
|
2389 |
tcp_chr_read, NULL, chr); |
|
2390 |
} |
|
2391 |
|
|
2392 |
static void tcp_chr_accept(void *opaque) |
|
2393 |
{ |
|
2394 |
CharDriverState *chr = opaque; |
|
2395 |
TCPCharDriver *s = chr->opaque; |
|
2396 |
struct sockaddr_in saddr; |
|
2397 |
socklen_t len; |
|
2398 |
int fd; |
|
2399 |
|
|
2400 |
for(;;) { |
|
2401 |
len = sizeof(saddr); |
|
2402 |
fd = accept(s->listen_fd, (struct sockaddr *)&saddr, &len); |
|
2403 |
if (fd < 0 && errno != EINTR) { |
|
2404 |
return; |
|
2405 |
} else if (fd >= 0) { |
|
2406 |
break; |
|
2407 |
} |
|
2408 |
} |
|
2409 |
socket_set_nonblock(fd); |
|
2410 |
s->fd = fd; |
|
2411 |
qemu_set_fd_handler(s->listen_fd, NULL, NULL, NULL); |
|
2412 |
tcp_chr_connect(chr); |
|
2413 |
} |
|
2414 |
|
|
2415 |
static void tcp_chr_close(CharDriverState *chr) |
|
2416 |
{ |
|
2417 |
TCPCharDriver *s = chr->opaque; |
|
2418 |
if (s->fd >= 0) |
|
2419 |
closesocket(s->fd); |
|
2420 |
if (s->listen_fd >= 0) |
|
2421 |
closesocket(s->listen_fd); |
|
2422 |
qemu_free(s); |
|
2423 |
} |
|
2424 |
|
|
2425 |
static CharDriverState *qemu_chr_open_tcp(const char *host_str, |
|
2426 |
int is_listen) |
|
2427 |
{ |
|
2428 |
CharDriverState *chr = NULL; |
|
2429 |
TCPCharDriver *s = NULL; |
|
2430 |
int fd = -1, ret, err, val; |
|
2431 |
struct sockaddr_in saddr; |
|
2432 |
|
|
2433 |
if (parse_host_port(&saddr, host_str) < 0) |
|
2434 |
goto fail; |
|
2435 |
|
|
2436 |
chr = qemu_mallocz(sizeof(CharDriverState)); |
|
2437 |
if (!chr) |
|
2438 |
goto fail; |
|
2439 |
s = qemu_mallocz(sizeof(TCPCharDriver)); |
|
2440 |
if (!s) |
|
2441 |
goto fail; |
|
2442 |
|
|
2443 |
fd = socket(PF_INET, SOCK_STREAM, 0); |
|
2444 |
if (fd < 0) |
|
2445 |
goto fail; |
|
2446 |
socket_set_nonblock(fd); |
|
2447 |
|
|
2448 |
s->connected = 0; |
|
2449 |
s->fd = -1; |
|
2450 |
s->listen_fd = -1; |
|
2451 |
if (is_listen) { |
|
2452 |
/* allow fast reuse */ |
|
2453 |
val = 1; |
|
2454 |
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); |
|
2455 |
|
|
2456 |
ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); |
|
2457 |
if (ret < 0) |
|
2458 |
goto fail; |
|
2459 |
ret = listen(fd, 0); |
|
2460 |
if (ret < 0) |
|
2461 |
goto fail; |
|
2462 |
s->listen_fd = fd; |
|
2463 |
qemu_set_fd_handler(s->listen_fd, tcp_chr_accept, NULL, chr); |
|
2464 |
} else { |
|
2465 |
for(;;) { |
|
2466 |
ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); |
|
2467 |
if (ret < 0) { |
|
2468 |
err = socket_error(); |
|
2469 |
if (err == EINTR || err == EWOULDBLOCK) { |
|
2470 |
} else if (err == EINPROGRESS) { |
|
2471 |
break; |
|
2472 |
} else { |
|
2473 |
goto fail; |
|
2474 |
} |
|
2475 |
} else { |
|
2476 |
s->connected = 1; |
|
2477 |
break; |
|
2478 |
} |
|
2479 |
} |
|
2480 |
s->fd = fd; |
|
2481 |
if (s->connected) |
|
2482 |
tcp_chr_connect(chr); |
|
2483 |
else |
|
2484 |
qemu_set_fd_handler(s->fd, NULL, tcp_chr_connect, chr); |
|
2485 |
} |
|
2486 |
|
|
2487 |
chr->opaque = s; |
|
2488 |
chr->chr_write = tcp_chr_write; |
|
2489 |
chr->chr_add_read_handler = tcp_chr_add_read_handler; |
|
2490 |
chr->chr_close = tcp_chr_close; |
|
2491 |
return chr; |
|
2492 |
fail: |
|
2493 |
if (fd >= 0) |
|
2494 |
closesocket(fd); |
|
2495 |
qemu_free(s); |
|
2496 |
qemu_free(chr); |
|
2497 |
return NULL; |
|
2498 |
} |
|
2499 |
|
|
2133 | 2500 |
CharDriverState *qemu_chr_open(const char *filename) |
2134 | 2501 |
{ |
2135 | 2502 |
const char *p; |
... | ... | |
2139 | 2506 |
} else if (!strcmp(filename, "null")) { |
2140 | 2507 |
return qemu_chr_open_null(); |
2141 | 2508 |
} else |
2509 |
if (strstart(filename, "tcp:", &p)) { |
|
2510 |
return qemu_chr_open_tcp(p, 0); |
|
2511 |
} else |
|
2512 |
if (strstart(filename, "tcpl:", &p)) { |
|
2513 |
return qemu_chr_open_tcp(p, 1); |
|
2514 |
} else |
|
2515 |
if (strstart(filename, "udp:", &p)) { |
|
2516 |
return qemu_chr_open_udp(p); |
|
2517 |
} else |
|
2142 | 2518 |
#ifndef _WIN32 |
2143 | 2519 |
if (strstart(filename, "file:", &p)) { |
2144 | 2520 |
return qemu_chr_open_file_out(p); |
... | ... | |
2844 | 3220 |
socket_set_nonblock(fd); |
2845 | 3221 |
return fd; |
2846 | 3222 |
fail: |
2847 |
if (fd>=0) close(fd); |
|
3223 |
if (fd >= 0) |
|
3224 |
closesocket(fd); |
|
2848 | 3225 |
return -1; |
2849 | 3226 |
} |
2850 | 3227 |
|
... | ... | |
2972 | 3349 |
} |
2973 | 3350 |
s1 = net_socket_fd_init(s->vlan, fd, 1); |
2974 | 3351 |
if (!s1) { |
2975 |
close(fd); |
|
3352 |
closesocket(fd);
|
|
2976 | 3353 |
} else { |
2977 | 3354 |
snprintf(s1->vc->info_str, sizeof(s1->vc->info_str), |
2978 | 3355 |
"socket: connection from %s:%d", |
Also available in: Unified diff