]> git.proxmox.com Git - qemu.git/blame - slirp/slirp.c
qcow2: Bring synchronous read/write back to life
[qemu.git] / slirp / slirp.c
CommitLineData
d75a0b97
FB
1/*
2 * libslirp glue
3 *
4 * Copyright (c) 2004-2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
e1c5a2b3 24#include "qemu-common.h"
f833ef21 25#include "qemu-timer.h"
0580ac91 26#include "qemu-char.h"
f0cbd3ec 27#include "slirp.h"
062e5527 28#include "hw/hw.h"
f0cbd3ec
FB
29
30/* host address */
31struct in_addr our_addr;
32/* host dns address */
33struct in_addr dns_addr;
34/* host loopback address */
35struct in_addr loopback_addr;
36
a13a4126 37/* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
9634d903 38static const uint8_t special_ethaddr[6] = {
a13a4126 39 0x52, 0x55, 0x00, 0x00, 0x00, 0x00
f0cbd3ec
FB
40};
41
de806f07 42static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
f0cbd3ec 43
f0cbd3ec
FB
44/* XXX: suppress those select globals */
45fd_set *global_readfds, *global_writefds, *global_xfds;
46
f1d99bbd
JK
47u_int curtime;
48static u_int time_fasttimo, last_slowtimo;
49static int do_slowtimo;
50
45578f49 51static TAILQ_HEAD(slirp_instances, Slirp) slirp_instances =
b1c99fcd 52 TAILQ_HEAD_INITIALIZER(slirp_instances);
115defd1 53
f0cbd3ec
FB
54#ifdef _WIN32
55
56static int get_dns_addr(struct in_addr *pdns_addr)
57{
379ff53d
FB
58 FIXED_INFO *FixedInfo=NULL;
59 ULONG BufLen;
60 DWORD ret;
61 IP_ADDR_STRING *pIPAddr;
62 struct in_addr tmp_addr;
3b46e624 63
379ff53d
FB
64 FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
65 BufLen = sizeof(FIXED_INFO);
3b46e624 66
379ff53d
FB
67 if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
68 if (FixedInfo) {
69 GlobalFree(FixedInfo);
70 FixedInfo = NULL;
71 }
72 FixedInfo = GlobalAlloc(GPTR, BufLen);
73 }
5fafdf24 74
379ff53d
FB
75 if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
76 printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
77 if (FixedInfo) {
78 GlobalFree(FixedInfo);
79 FixedInfo = NULL;
80 }
81 return -1;
82 }
3b46e624 83
379ff53d
FB
84 pIPAddr = &(FixedInfo->DnsServerList);
85 inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
86 *pdns_addr = tmp_addr;
379ff53d
FB
87 if (FixedInfo) {
88 GlobalFree(FixedInfo);
89 FixedInfo = NULL;
90 }
91 return 0;
f0cbd3ec
FB
92}
93
df461894
JK
94static void winsock_cleanup(void)
95{
96 WSACleanup();
97}
98
f0cbd3ec
FB
99#else
100
101static int get_dns_addr(struct in_addr *pdns_addr)
102{
103 char buff[512];
363a37d5 104 char buff2[257];
f0cbd3ec
FB
105 FILE *f;
106 int found = 0;
107 struct in_addr tmp_addr;
3b46e624 108
f0cbd3ec
FB
109 f = fopen("/etc/resolv.conf", "r");
110 if (!f)
111 return -1;
112
31a60e22 113#ifdef DEBUG
f0cbd3ec 114 lprint("IP address of your DNS(s): ");
31a60e22 115#endif
f0cbd3ec
FB
116 while (fgets(buff, 512, f) != NULL) {
117 if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
118 if (!inet_aton(buff2, &tmp_addr))
119 continue;
120 if (tmp_addr.s_addr == loopback_addr.s_addr)
121 tmp_addr = our_addr;
122 /* If it's the first one, set it to dns_addr */
123 if (!found)
124 *pdns_addr = tmp_addr;
31a60e22 125#ifdef DEBUG
f0cbd3ec
FB
126 else
127 lprint(", ");
31a60e22 128#endif
f0cbd3ec 129 if (++found > 3) {
31a60e22 130#ifdef DEBUG
f0cbd3ec 131 lprint("(more)");
31a60e22 132#endif
f0cbd3ec 133 break;
31a60e22
BS
134 }
135#ifdef DEBUG
136 else
f0cbd3ec 137 lprint("%s", inet_ntoa(tmp_addr));
31a60e22 138#endif
f0cbd3ec
FB
139 }
140 }
1d43a717 141 fclose(f);
f0cbd3ec
FB
142 if (!found)
143 return -1;
144 return 0;
145}
146
147#endif
148
df461894 149static void slirp_init_once(void)
379ff53d 150{
df461894
JK
151 static int initialized;
152 struct hostent *he;
153 char our_name[256];
154#ifdef _WIN32
155 WSADATA Data;
379ff53d
FB
156#endif
157
df461894
JK
158 if (initialized) {
159 return;
160 }
161 initialized = 1;
162
163#ifdef _WIN32
164 WSAStartup(MAKEWORD(2,0), &Data);
165 atexit(winsock_cleanup);
166#endif
167
168 loopback_addr.s_addr = htonl(INADDR_LOOPBACK);
169
170 /* FIXME: This address may change during runtime */
171 if (gethostname(our_name, sizeof(our_name)) == 0) {
172 he = gethostbyname(our_name);
173 if (he) {
174 our_addr = *(struct in_addr *)he->h_addr;
175 }
176 }
177 if (our_addr.s_addr == 0) {
178 our_addr = loopback_addr;
179 }
180
181 /* FIXME: This address may change during runtime */
182 if (get_dns_addr(&dns_addr) < 0) {
183 dns_addr = loopback_addr;
184 }
185}
186
062e5527
AL
187static void slirp_state_save(QEMUFile *f, void *opaque);
188static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
189
9f8bd042
JK
190Slirp *slirp_init(int restricted, struct in_addr vnetwork,
191 struct in_addr vnetmask, struct in_addr vhost,
192 const char *vhostname, const char *tftp_path,
193 const char *bootfile, struct in_addr vdhcp_start,
194 struct in_addr vnameserver, void *opaque)
f0cbd3ec 195{
ad0d8c4c 196 Slirp *slirp = qemu_mallocz(sizeof(Slirp));
460fec67 197
df461894 198 slirp_init_once();
379ff53d 199
460fec67 200 slirp->restricted = restricted;
f0cbd3ec 201
460fec67
JK
202 if_init(slirp);
203 ip_init(slirp);
f0cbd3ec
FB
204
205 /* Initialise mbufs *after* setting the MTU */
460fec67 206 m_init(slirp);
f0cbd3ec 207
460fec67
JK
208 slirp->vnetwork_addr = vnetwork;
209 slirp->vnetwork_mask = vnetmask;
210 slirp->vhost_addr = vhost;
c92ef6a2 211 if (vhostname) {
460fec67
JK
212 pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
213 vhostname);
a13a4126 214 }
ad196a9d 215 if (tftp_path) {
460fec67 216 slirp->tftp_prefix = qemu_strdup(tftp_path);
ad196a9d 217 }
ad196a9d 218 if (bootfile) {
460fec67 219 slirp->bootp_filename = qemu_strdup(bootfile);
ad196a9d 220 }
460fec67
JK
221 slirp->vdhcp_startaddr = vdhcp_start;
222 slirp->vnameserver_addr = vnameserver;
ad196a9d 223
9f8bd042
JK
224 slirp->opaque = opaque;
225
0a1f851e 226 register_savevm("slirp", 0, 3, slirp_state_save, slirp_state_load, slirp);
9f8bd042 227
b1c99fcd 228 TAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
ad0d8c4c 229
9f8bd042 230 return slirp;
f0cbd3ec
FB
231}
232
ad0d8c4c
JK
233void slirp_cleanup(Slirp *slirp)
234{
b1c99fcd
JK
235 TAILQ_REMOVE(&slirp_instances, slirp, entry);
236
ad0d8c4c
JK
237 unregister_savevm("slirp", slirp);
238
239 qemu_free(slirp->tftp_prefix);
240 qemu_free(slirp->bootp_filename);
241 qemu_free(slirp);
ad0d8c4c
JK
242}
243
f0cbd3ec
FB
244#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
245#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
246#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
247
5fafdf24 248void slirp_select_fill(int *pnfds,
f0cbd3ec
FB
249 fd_set *readfds, fd_set *writefds, fd_set *xfds)
250{
b1c99fcd 251 Slirp *slirp;
f0cbd3ec 252 struct socket *so, *so_next;
f0cbd3ec 253 int nfds;
f0cbd3ec 254
b1c99fcd 255 if (TAILQ_EMPTY(&slirp_instances)) {
d918f23e
JK
256 return;
257 }
258
f0cbd3ec
FB
259 /* fail safe */
260 global_readfds = NULL;
261 global_writefds = NULL;
262 global_xfds = NULL;
3b46e624 263
f0cbd3ec
FB
264 nfds = *pnfds;
265 /*
266 * First, TCP sockets
267 */
268 do_slowtimo = 0;
d918f23e 269
b1c99fcd 270 TAILQ_FOREACH(slirp, &slirp_instances, entry) {
5fafdf24 271 /*
f0cbd3ec
FB
272 * *_slowtimo needs calling if there are IP fragments
273 * in the fragment queue, or there are TCP connections active
274 */
b1c99fcd 275 do_slowtimo |= ((slirp->tcb.so_next != &slirp->tcb) ||
460fec67 276 (&slirp->ipq.ip_link != slirp->ipq.ip_link.next));
3b46e624 277
460fec67
JK
278 for (so = slirp->tcb.so_next; so != &slirp->tcb;
279 so = so_next) {
f0cbd3ec 280 so_next = so->so_next;
3b46e624 281
f0cbd3ec
FB
282 /*
283 * See if we need a tcp_fasttimo
284 */
285 if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
286 time_fasttimo = curtime; /* Flag when we want a fasttimo */
3b46e624 287
f0cbd3ec
FB
288 /*
289 * NOFDREF can include still connecting to local-host,
290 * newly socreated() sockets etc. Don't want to select these.
291 */
292 if (so->so_state & SS_NOFDREF || so->s == -1)
293 continue;
3b46e624 294
f0cbd3ec
FB
295 /*
296 * Set for reading sockets which are accepting
297 */
298 if (so->so_state & SS_FACCEPTCONN) {
299 FD_SET(so->s, readfds);
300 UPD_NFDS(so->s);
301 continue;
302 }
3b46e624 303
f0cbd3ec
FB
304 /*
305 * Set for writing sockets which are connecting
306 */
307 if (so->so_state & SS_ISFCONNECTING) {
308 FD_SET(so->s, writefds);
309 UPD_NFDS(so->s);
310 continue;
311 }
3b46e624 312
f0cbd3ec
FB
313 /*
314 * Set for writing if we are connected, can send more, and
315 * we have something to send
316 */
317 if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
318 FD_SET(so->s, writefds);
319 UPD_NFDS(so->s);
320 }
3b46e624 321
f0cbd3ec
FB
322 /*
323 * Set for reading (and urgent data) if we are connected, can
324 * receive more, and we have room for it XXX /2 ?
325 */
326 if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
327 FD_SET(so->s, readfds);
328 FD_SET(so->s, xfds);
329 UPD_NFDS(so->s);
330 }
331 }
3b46e624 332
f0cbd3ec
FB
333 /*
334 * UDP sockets
335 */
460fec67
JK
336 for (so = slirp->udb.so_next; so != &slirp->udb;
337 so = so_next) {
f0cbd3ec 338 so_next = so->so_next;
3b46e624 339
f0cbd3ec
FB
340 /*
341 * See if it's timed out
342 */
343 if (so->so_expire) {
344 if (so->so_expire <= curtime) {
345 udp_detach(so);
346 continue;
347 } else
348 do_slowtimo = 1; /* Let socket expire */
349 }
3b46e624 350
f0cbd3ec
FB
351 /*
352 * When UDP packets are received from over the
353 * link, they're sendto()'d straight away, so
354 * no need for setting for writing
355 * Limit the number of packets queued by this session
356 * to 4. Note that even though we try and limit this
357 * to 4 packets, the session could have more queued
358 * if the packets needed to be fragmented
359 * (XXX <= 4 ?)
360 */
361 if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
362 FD_SET(so->s, readfds);
363 UPD_NFDS(so->s);
364 }
365 }
b1c99fcd 366 }
5fafdf24 367
f0cbd3ec 368 *pnfds = nfds;
5fafdf24 369}
f0cbd3ec 370
d918f23e
JK
371void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
372 int select_error)
f0cbd3ec 373{
b1c99fcd 374 Slirp *slirp;
f0cbd3ec
FB
375 struct socket *so, *so_next;
376 int ret;
377
b1c99fcd 378 if (TAILQ_EMPTY(&slirp_instances)) {
d918f23e
JK
379 return;
380 }
381
f0cbd3ec
FB
382 global_readfds = readfds;
383 global_writefds = writefds;
384 global_xfds = xfds;
385
f833ef21 386 curtime = qemu_get_clock(rt_clock);
5fafdf24 387
b1c99fcd 388 TAILQ_FOREACH(slirp, &slirp_instances, entry) {
f0cbd3ec 389 /*
5fafdf24 390 * See if anything has timed out
f0cbd3ec 391 */
df5f8956 392 if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
460fec67 393 tcp_fasttimo(slirp);
f0cbd3ec
FB
394 time_fasttimo = 0;
395 }
396 if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
460fec67
JK
397 ip_slowtimo(slirp);
398 tcp_slowtimo(slirp);
f0cbd3ec
FB
399 last_slowtimo = curtime;
400 }
5fafdf24 401
f0cbd3ec
FB
402 /*
403 * Check sockets
404 */
d918f23e 405 if (!select_error) {
f0cbd3ec
FB
406 /*
407 * Check TCP sockets
408 */
460fec67
JK
409 for (so = slirp->tcb.so_next; so != &slirp->tcb;
410 so = so_next) {
f0cbd3ec 411 so_next = so->so_next;
3b46e624 412
f0cbd3ec
FB
413 /*
414 * FD_ISSET is meaningless on these sockets
415 * (and they can crash the program)
416 */
417 if (so->so_state & SS_NOFDREF || so->s == -1)
418 continue;
3b46e624 419
f0cbd3ec
FB
420 /*
421 * Check for URG data
422 * This will soread as well, so no need to
423 * test for readfds below if this succeeds
424 */
425 if (FD_ISSET(so->s, xfds))
426 sorecvoob(so);
427 /*
428 * Check sockets for reading
429 */
430 else if (FD_ISSET(so->s, readfds)) {
431 /*
432 * Check for incoming connections
433 */
434 if (so->so_state & SS_FACCEPTCONN) {
435 tcp_connect(so);
436 continue;
437 } /* else */
438 ret = soread(so);
3b46e624 439
f0cbd3ec
FB
440 /* Output it if we read something */
441 if (ret > 0)
442 tcp_output(sototcpcb(so));
443 }
3b46e624 444
f0cbd3ec
FB
445 /*
446 * Check sockets for writing
447 */
448 if (FD_ISSET(so->s, writefds)) {
449 /*
450 * Check for non-blocking, still-connecting sockets
451 */
452 if (so->so_state & SS_ISFCONNECTING) {
453 /* Connected */
454 so->so_state &= ~SS_ISFCONNECTING;
3b46e624 455
0a656f5f 456 ret = send(so->s, (const void *) &ret, 0, 0);
f0cbd3ec
FB
457 if (ret < 0) {
458 /* XXXXX Must fix, zero bytes is a NOP */
459 if (errno == EAGAIN || errno == EWOULDBLOCK ||
460 errno == EINPROGRESS || errno == ENOTCONN)
461 continue;
3b46e624 462
f0cbd3ec 463 /* else failed */
f932b6ce
JK
464 so->so_state &= SS_PERSISTENT_MASK;
465 so->so_state |= SS_NOFDREF;
f0cbd3ec
FB
466 }
467 /* else so->so_state &= ~SS_ISFCONNECTING; */
3b46e624 468
f0cbd3ec
FB
469 /*
470 * Continue tcp_input
471 */
472 tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
473 /* continue; */
474 } else
475 ret = sowrite(so);
476 /*
5fafdf24 477 * XXXXX If we wrote something (a lot), there
f0cbd3ec
FB
478 * could be a need for a window update.
479 * In the worst case, the remote will send
480 * a window probe to get things going again
481 */
482 }
3b46e624 483
f0cbd3ec
FB
484 /*
485 * Probe a still-connecting, non-blocking socket
486 * to check if it's still alive
487 */
488#ifdef PROBE_CONN
489 if (so->so_state & SS_ISFCONNECTING) {
02d2c54c 490 ret = recv(so->s, (char *)&ret, 0,0);
3b46e624 491
f0cbd3ec
FB
492 if (ret < 0) {
493 /* XXX */
494 if (errno == EAGAIN || errno == EWOULDBLOCK ||
495 errno == EINPROGRESS || errno == ENOTCONN)
496 continue; /* Still connecting, continue */
3b46e624 497
f0cbd3ec 498 /* else failed */
f932b6ce
JK
499 so->so_state &= SS_PERSISTENT_MASK;
500 so->so_state |= SS_NOFDREF;
3b46e624 501
f0cbd3ec
FB
502 /* tcp_input will take care of it */
503 } else {
02d2c54c 504 ret = send(so->s, &ret, 0,0);
f0cbd3ec
FB
505 if (ret < 0) {
506 /* XXX */
507 if (errno == EAGAIN || errno == EWOULDBLOCK ||
508 errno == EINPROGRESS || errno == ENOTCONN)
509 continue;
510 /* else failed */
f932b6ce
JK
511 so->so_state &= SS_PERSISTENT_MASK;
512 so->so_state |= SS_NOFDREF;
f0cbd3ec
FB
513 } else
514 so->so_state &= ~SS_ISFCONNECTING;
3b46e624 515
f0cbd3ec
FB
516 }
517 tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
518 } /* SS_ISFCONNECTING */
519#endif
520 }
3b46e624 521
f0cbd3ec
FB
522 /*
523 * Now UDP sockets.
524 * Incoming packets are sent straight away, they're not buffered.
525 * Incoming UDP data isn't buffered either.
526 */
460fec67
JK
527 for (so = slirp->udb.so_next; so != &slirp->udb;
528 so = so_next) {
f0cbd3ec 529 so_next = so->so_next;
3b46e624 530
f0cbd3ec
FB
531 if (so->s != -1 && FD_ISSET(so->s, readfds)) {
532 sorecvfrom(so);
533 }
534 }
535 }
5fafdf24 536
f0cbd3ec
FB
537 /*
538 * See if we can start outputting
539 */
460fec67
JK
540 if (slirp->if_queued) {
541 if_start(slirp);
542 }
b1c99fcd 543 }
02d2c54c
FB
544
545 /* clear global file descriptor sets.
546 * these reside on the stack in vl.c
547 * so they're unusable if we're not in
548 * slirp_select_fill or slirp_select_poll.
549 */
550 global_readfds = NULL;
551 global_writefds = NULL;
552 global_xfds = NULL;
f0cbd3ec
FB
553}
554
555#define ETH_ALEN 6
556#define ETH_HLEN 14
557
558#define ETH_P_IP 0x0800 /* Internet Protocol packet */
559#define ETH_P_ARP 0x0806 /* Address Resolution packet */
560
561#define ARPOP_REQUEST 1 /* ARP request */
562#define ARPOP_REPLY 2 /* ARP reply */
563
5fafdf24 564struct ethhdr
f0cbd3ec
FB
565{
566 unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
567 unsigned char h_source[ETH_ALEN]; /* source ether addr */
568 unsigned short h_proto; /* packet type ID field */
569};
570
571struct arphdr
572{
573 unsigned short ar_hrd; /* format of hardware address */
574 unsigned short ar_pro; /* format of protocol address */
575 unsigned char ar_hln; /* length of hardware address */
576 unsigned char ar_pln; /* length of protocol address */
577 unsigned short ar_op; /* ARP opcode (command) */
578
579 /*
580 * Ethernet looks like this : This bit is variable sized however...
581 */
582 unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
a13a4126 583 uint32_t ar_sip; /* sender IP address */
f0cbd3ec 584 unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
a13a4126
JK
585 uint32_t ar_tip ; /* target IP address */
586} __attribute__((packed));
f0cbd3ec 587
460fec67 588static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
f0cbd3ec
FB
589{
590 struct ethhdr *eh = (struct ethhdr *)pkt;
591 struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
592 uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
593 struct ethhdr *reh = (struct ethhdr *)arp_reply;
594 struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
595 int ar_op;
a3d4af03 596 struct ex_list *ex_ptr;
f0cbd3ec
FB
597
598 ar_op = ntohs(ah->ar_op);
599 switch(ar_op) {
600 case ARPOP_REQUEST:
460fec67
JK
601 if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
602 slirp->vnetwork_addr.s_addr) {
603 if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
604 ah->ar_tip == slirp->vhost_addr.s_addr)
a3d4af03 605 goto arp_ok;
460fec67 606 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
a13a4126 607 if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
a3d4af03
FB
608 goto arp_ok;
609 }
610 return;
611 arp_ok:
f0cbd3ec 612 /* XXX: make an ARP request to have the client address */
460fec67 613 memcpy(slirp->client_ethaddr, eh->h_source, ETH_ALEN);
f0cbd3ec
FB
614
615 /* ARP request for alias/dns mac address */
616 memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
a13a4126
JK
617 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
618 memcpy(&reh->h_source[2], &ah->ar_tip, 4);
f0cbd3ec
FB
619 reh->h_proto = htons(ETH_P_ARP);
620
621 rah->ar_hrd = htons(1);
622 rah->ar_pro = htons(ETH_P_IP);
623 rah->ar_hln = ETH_ALEN;
624 rah->ar_pln = 4;
625 rah->ar_op = htons(ARPOP_REPLY);
626 memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
a13a4126 627 rah->ar_sip = ah->ar_tip;
f0cbd3ec 628 memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
a13a4126 629 rah->ar_tip = ah->ar_sip;
9f8bd042 630 slirp_output(slirp->opaque, arp_reply, sizeof(arp_reply));
f0cbd3ec
FB
631 }
632 break;
de806f07
FB
633 case ARPOP_REPLY:
634 /* reply to request of client mac address ? */
460fec67
JK
635 if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN) &&
636 ah->ar_sip == slirp->client_ipaddr.s_addr) {
637 memcpy(slirp->client_ethaddr, ah->ar_sha, ETH_ALEN);
de806f07
FB
638 }
639 break;
f0cbd3ec
FB
640 default:
641 break;
642 }
643}
644
9f8bd042 645void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
f0cbd3ec
FB
646{
647 struct mbuf *m;
648 int proto;
649
650 if (pkt_len < ETH_HLEN)
651 return;
3b46e624 652
f0cbd3ec
FB
653 proto = ntohs(*(uint16_t *)(pkt + 12));
654 switch(proto) {
655 case ETH_P_ARP:
460fec67 656 arp_input(slirp, pkt, pkt_len);
f0cbd3ec
FB
657 break;
658 case ETH_P_IP:
460fec67 659 m = m_get(slirp);
f0cbd3ec
FB
660 if (!m)
661 return;
38f3e7c2 662 /* Note: we add to align the IP header */
e8e880a7
AJ
663 if (M_FREEROOM(m) < pkt_len + 2) {
664 m_inc(m, pkt_len + 2);
665 }
38f3e7c2
FB
666 m->m_len = pkt_len + 2;
667 memcpy(m->m_data + 2, pkt, pkt_len);
f0cbd3ec 668
38f3e7c2
FB
669 m->m_data += 2 + ETH_HLEN;
670 m->m_len -= 2 + ETH_HLEN;
f0cbd3ec
FB
671
672 ip_input(m);
673 break;
674 default:
675 break;
676 }
677}
678
679/* output the IP packet to the ethernet device */
460fec67 680void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len)
f0cbd3ec
FB
681{
682 uint8_t buf[1600];
683 struct ethhdr *eh = (struct ethhdr *)buf;
684
685 if (ip_data_len + ETH_HLEN > sizeof(buf))
686 return;
de806f07 687
460fec67 688 if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN)) {
de806f07
FB
689 uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
690 struct ethhdr *reh = (struct ethhdr *)arp_req;
691 struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
692 const struct ip *iph = (const struct ip *)ip_data;
693
694 /* If the client addr is not known, there is no point in
695 sending the packet to it. Normally the sender should have
696 done an ARP request to get its MAC address. Here we do it
697 in place of sending the packet and we hope that the sender
698 will retry sending its packet. */
699 memset(reh->h_dest, 0xff, ETH_ALEN);
a13a4126 700 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
460fec67 701 memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
de806f07
FB
702 reh->h_proto = htons(ETH_P_ARP);
703 rah->ar_hrd = htons(1);
704 rah->ar_pro = htons(ETH_P_IP);
705 rah->ar_hln = ETH_ALEN;
706 rah->ar_pln = 4;
707 rah->ar_op = htons(ARPOP_REQUEST);
708 /* source hw addr */
a13a4126 709 memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
460fec67 710 memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
de806f07 711 /* source IP */
460fec67 712 rah->ar_sip = slirp->vhost_addr.s_addr;
de806f07
FB
713 /* target hw addr (none) */
714 memset(rah->ar_tha, 0, ETH_ALEN);
715 /* target IP */
a13a4126 716 rah->ar_tip = iph->ip_dst.s_addr;
460fec67 717 slirp->client_ipaddr = iph->ip_dst;
9f8bd042 718 slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
de806f07 719 } else {
460fec67 720 memcpy(eh->h_dest, slirp->client_ethaddr, ETH_ALEN);
a13a4126 721 memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
de806f07 722 /* XXX: not correct */
460fec67 723 memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
de806f07
FB
724 eh->h_proto = htons(ETH_P_IP);
725 memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
9f8bd042 726 slirp_output(slirp->opaque, buf, ip_data_len + ETH_HLEN);
de806f07 727 }
f0cbd3ec 728}
9bf05444 729
9c12a6f2 730/* Drop host forwarding rule, return 0 if found. */
9f8bd042
JK
731int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
732 int host_port)
c1261d8d
AG
733{
734 struct socket *so;
460fec67 735 struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);
2ad82cf9
JK
736 struct sockaddr_in addr;
737 int port = htons(host_port);
738 socklen_t addr_len;
c1261d8d 739
c1261d8d 740 for (so = head->so_next; so != head; so = so->so_next) {
2ad82cf9 741 addr_len = sizeof(addr);
9c12a6f2
JK
742 if ((so->so_state & SS_HOSTFWD) &&
743 getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
3c6a0580 744 addr.sin_addr.s_addr == host_addr.s_addr &&
2ad82cf9 745 addr.sin_port == port) {
c1261d8d
AG
746 close(so->s);
747 sofree(so);
9c12a6f2 748 return 0;
c1261d8d
AG
749 }
750 }
751
9c12a6f2 752 return -1;
c1261d8d
AG
753}
754
9f8bd042
JK
755int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
756 int host_port, struct in_addr guest_addr, int guest_port)
9bf05444 757{
a13a4126 758 if (!guest_addr.s_addr) {
460fec67 759 guest_addr = slirp->vdhcp_startaddr;
a13a4126 760 }
9bf05444 761 if (is_udp) {
460fec67
JK
762 if (!udp_listen(slirp, host_addr.s_addr, htons(host_port),
763 guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
9bf05444
FB
764 return -1;
765 } else {
460fec67
JK
766 if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port),
767 guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
9bf05444
FB
768 return -1;
769 }
770 return 0;
771}
a3d4af03 772
9f8bd042 773int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
b0dc7873 774 struct in_addr *guest_addr, int guest_port)
a3d4af03 775{
b0dc7873
JK
776 if (!guest_addr->s_addr) {
777 guest_addr->s_addr = slirp->vnetwork_addr.s_addr |
460fec67 778 (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
c92ef6a2 779 }
b0dc7873 780 if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) !=
460fec67 781 slirp->vnetwork_addr.s_addr ||
b0dc7873
JK
782 guest_addr->s_addr == slirp->vhost_addr.s_addr ||
783 guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
a13a4126
JK
784 return -1;
785 }
b0dc7873 786 return add_exec(&slirp->exec_list, do_pty, (char *)args, *guest_addr,
a13a4126 787 htons(guest_port));
a3d4af03 788}
e1c5a2b3
AL
789
790ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
791{
792 if (so->s == -1 && so->extra) {
793 qemu_chr_write(so->extra, buf, len);
794 return len;
795 }
796
797 return send(so->s, buf, len, flags);
798}
799
a13a4126 800static struct socket *
460fec67 801slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port)
e1c5a2b3 802{
a13a4126 803 struct socket *so;
e1c5a2b3 804
460fec67 805 for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
a13a4126
JK
806 if (so->so_faddr.s_addr == guest_addr.s_addr &&
807 htons(so->so_fport) == guest_port) {
808 return so;
809 }
810 }
811 return NULL;
e1c5a2b3
AL
812}
813
9f8bd042
JK
814size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
815 int guest_port)
e1c5a2b3
AL
816{
817 struct iovec iov[2];
818 struct socket *so;
819
460fec67 820 so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
e1c5a2b3
AL
821
822 if (!so || so->so_state & SS_NOFDREF)
823 return 0;
824
825 if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
826 return 0;
827
828 return sopreprbuf(so, iov, NULL);
829}
830
9f8bd042 831void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
c92ef6a2 832 const uint8_t *buf, int size)
e1c5a2b3
AL
833{
834 int ret;
460fec67 835 struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
a13a4126 836
e1c5a2b3
AL
837 if (!so)
838 return;
839
0580ac91 840 ret = soreadbuf(so, (const char *)buf, size);
e1c5a2b3
AL
841
842 if (ret > 0)
843 tcp_output(sototcpcb(so));
844}
062e5527
AL
845
846static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
847{
848 int i;
849
850 qemu_put_sbe16(f, tp->t_state);
851 for (i = 0; i < TCPT_NTIMERS; i++)
852 qemu_put_sbe16(f, tp->t_timer[i]);
853 qemu_put_sbe16(f, tp->t_rxtshift);
854 qemu_put_sbe16(f, tp->t_rxtcur);
855 qemu_put_sbe16(f, tp->t_dupacks);
856 qemu_put_be16(f, tp->t_maxseg);
857 qemu_put_sbyte(f, tp->t_force);
858 qemu_put_be16(f, tp->t_flags);
859 qemu_put_be32(f, tp->snd_una);
860 qemu_put_be32(f, tp->snd_nxt);
861 qemu_put_be32(f, tp->snd_up);
862 qemu_put_be32(f, tp->snd_wl1);
863 qemu_put_be32(f, tp->snd_wl2);
864 qemu_put_be32(f, tp->iss);
865 qemu_put_be32(f, tp->snd_wnd);
866 qemu_put_be32(f, tp->rcv_wnd);
867 qemu_put_be32(f, tp->rcv_nxt);
868 qemu_put_be32(f, tp->rcv_up);
869 qemu_put_be32(f, tp->irs);
870 qemu_put_be32(f, tp->rcv_adv);
871 qemu_put_be32(f, tp->snd_max);
872 qemu_put_be32(f, tp->snd_cwnd);
873 qemu_put_be32(f, tp->snd_ssthresh);
874 qemu_put_sbe16(f, tp->t_idle);
875 qemu_put_sbe16(f, tp->t_rtt);
876 qemu_put_be32(f, tp->t_rtseq);
877 qemu_put_sbe16(f, tp->t_srtt);
878 qemu_put_sbe16(f, tp->t_rttvar);
879 qemu_put_be16(f, tp->t_rttmin);
880 qemu_put_be32(f, tp->max_sndwnd);
881 qemu_put_byte(f, tp->t_oobflags);
882 qemu_put_byte(f, tp->t_iobc);
883 qemu_put_sbe16(f, tp->t_softerror);
884 qemu_put_byte(f, tp->snd_scale);
885 qemu_put_byte(f, tp->rcv_scale);
886 qemu_put_byte(f, tp->request_r_scale);
887 qemu_put_byte(f, tp->requested_s_scale);
888 qemu_put_be32(f, tp->ts_recent);
889 qemu_put_be32(f, tp->ts_recent_age);
890 qemu_put_be32(f, tp->last_ack_sent);
891}
892
893static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
894{
895 uint32_t off;
896
897 qemu_put_be32(f, sbuf->sb_cc);
898 qemu_put_be32(f, sbuf->sb_datalen);
899 off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
900 qemu_put_sbe32(f, off);
901 off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
902 qemu_put_sbe32(f, off);
903 qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
904}
905
906static void slirp_socket_save(QEMUFile *f, struct socket *so)
907{
908 qemu_put_be32(f, so->so_urgc);
909 qemu_put_be32(f, so->so_faddr.s_addr);
910 qemu_put_be32(f, so->so_laddr.s_addr);
911 qemu_put_be16(f, so->so_fport);
912 qemu_put_be16(f, so->so_lport);
913 qemu_put_byte(f, so->so_iptos);
914 qemu_put_byte(f, so->so_emu);
915 qemu_put_byte(f, so->so_type);
916 qemu_put_be32(f, so->so_state);
917 slirp_sbuf_save(f, &so->so_rcv);
918 slirp_sbuf_save(f, &so->so_snd);
919 slirp_tcp_save(f, so->so_tcpcb);
920}
921
0a1f851e
JK
922static void slirp_bootp_save(QEMUFile *f, Slirp *slirp)
923{
924 int i;
925
926 for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
927 qemu_put_be16(f, slirp->bootp_clients[i].allocated);
928 qemu_put_buffer(f, slirp->bootp_clients[i].macaddr, 6);
929 }
930}
931
062e5527
AL
932static void slirp_state_save(QEMUFile *f, void *opaque)
933{
460fec67 934 Slirp *slirp = opaque;
062e5527
AL
935 struct ex_list *ex_ptr;
936
460fec67 937 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
062e5527
AL
938 if (ex_ptr->ex_pty == 3) {
939 struct socket *so;
460fec67
JK
940 so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
941 ntohs(ex_ptr->ex_fport));
062e5527
AL
942 if (!so)
943 continue;
944
945 qemu_put_byte(f, 42);
946 slirp_socket_save(f, so);
947 }
948 qemu_put_byte(f, 0);
285f7a62 949
460fec67 950 qemu_put_be16(f, slirp->ip_id);
0a1f851e
JK
951
952 slirp_bootp_save(f, slirp);
062e5527
AL
953}
954
955static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
956{
957 int i;
958
959 tp->t_state = qemu_get_sbe16(f);
960 for (i = 0; i < TCPT_NTIMERS; i++)
961 tp->t_timer[i] = qemu_get_sbe16(f);
962 tp->t_rxtshift = qemu_get_sbe16(f);
963 tp->t_rxtcur = qemu_get_sbe16(f);
964 tp->t_dupacks = qemu_get_sbe16(f);
965 tp->t_maxseg = qemu_get_be16(f);
966 tp->t_force = qemu_get_sbyte(f);
967 tp->t_flags = qemu_get_be16(f);
968 tp->snd_una = qemu_get_be32(f);
969 tp->snd_nxt = qemu_get_be32(f);
970 tp->snd_up = qemu_get_be32(f);
971 tp->snd_wl1 = qemu_get_be32(f);
972 tp->snd_wl2 = qemu_get_be32(f);
973 tp->iss = qemu_get_be32(f);
974 tp->snd_wnd = qemu_get_be32(f);
975 tp->rcv_wnd = qemu_get_be32(f);
976 tp->rcv_nxt = qemu_get_be32(f);
977 tp->rcv_up = qemu_get_be32(f);
978 tp->irs = qemu_get_be32(f);
979 tp->rcv_adv = qemu_get_be32(f);
980 tp->snd_max = qemu_get_be32(f);
981 tp->snd_cwnd = qemu_get_be32(f);
982 tp->snd_ssthresh = qemu_get_be32(f);
983 tp->t_idle = qemu_get_sbe16(f);
984 tp->t_rtt = qemu_get_sbe16(f);
985 tp->t_rtseq = qemu_get_be32(f);
986 tp->t_srtt = qemu_get_sbe16(f);
987 tp->t_rttvar = qemu_get_sbe16(f);
988 tp->t_rttmin = qemu_get_be16(f);
989 tp->max_sndwnd = qemu_get_be32(f);
990 tp->t_oobflags = qemu_get_byte(f);
991 tp->t_iobc = qemu_get_byte(f);
992 tp->t_softerror = qemu_get_sbe16(f);
993 tp->snd_scale = qemu_get_byte(f);
994 tp->rcv_scale = qemu_get_byte(f);
995 tp->request_r_scale = qemu_get_byte(f);
996 tp->requested_s_scale = qemu_get_byte(f);
997 tp->ts_recent = qemu_get_be32(f);
998 tp->ts_recent_age = qemu_get_be32(f);
999 tp->last_ack_sent = qemu_get_be32(f);
1000 tcp_template(tp);
1001}
1002
1003static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
1004{
1005 uint32_t off, sb_cc, sb_datalen;
1006
1007 sb_cc = qemu_get_be32(f);
1008 sb_datalen = qemu_get_be32(f);
1009
1010 sbreserve(sbuf, sb_datalen);
1011
1012 if (sbuf->sb_datalen != sb_datalen)
1013 return -ENOMEM;
1014
1015 sbuf->sb_cc = sb_cc;
1016
1017 off = qemu_get_sbe32(f);
1018 sbuf->sb_wptr = sbuf->sb_data + off;
1019 off = qemu_get_sbe32(f);
1020 sbuf->sb_rptr = sbuf->sb_data + off;
1021 qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
1022
1023 return 0;
1024}
1025
1026static int slirp_socket_load(QEMUFile *f, struct socket *so)
1027{
1028 if (tcp_attach(so) < 0)
1029 return -ENOMEM;
1030
1031 so->so_urgc = qemu_get_be32(f);
1032 so->so_faddr.s_addr = qemu_get_be32(f);
1033 so->so_laddr.s_addr = qemu_get_be32(f);
1034 so->so_fport = qemu_get_be16(f);
1035 so->so_lport = qemu_get_be16(f);
1036 so->so_iptos = qemu_get_byte(f);
1037 so->so_emu = qemu_get_byte(f);
1038 so->so_type = qemu_get_byte(f);
1039 so->so_state = qemu_get_be32(f);
1040 if (slirp_sbuf_load(f, &so->so_rcv) < 0)
1041 return -ENOMEM;
1042 if (slirp_sbuf_load(f, &so->so_snd) < 0)
1043 return -ENOMEM;
1044 slirp_tcp_load(f, so->so_tcpcb);
1045
1046 return 0;
1047}
1048
0a1f851e
JK
1049static void slirp_bootp_load(QEMUFile *f, Slirp *slirp)
1050{
1051 int i;
1052
1053 for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
1054 slirp->bootp_clients[i].allocated = qemu_get_be16(f);
1055 qemu_get_buffer(f, slirp->bootp_clients[i].macaddr, 6);
1056 }
1057}
1058
062e5527
AL
1059static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
1060{
460fec67 1061 Slirp *slirp = opaque;
062e5527
AL
1062 struct ex_list *ex_ptr;
1063 int r;
1064
1065 while ((r = qemu_get_byte(f))) {
1066 int ret;
460fec67 1067 struct socket *so = socreate(slirp);
062e5527
AL
1068
1069 if (!so)
1070 return -ENOMEM;
1071
1072 ret = slirp_socket_load(f, so);
1073
1074 if (ret < 0)
1075 return ret;
1076
460fec67
JK
1077 if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) !=
1078 slirp->vnetwork_addr.s_addr) {
062e5527 1079 return -EINVAL;
a13a4126 1080 }
460fec67 1081 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
062e5527 1082 if (ex_ptr->ex_pty == 3 &&
a13a4126
JK
1083 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
1084 so->so_fport == ex_ptr->ex_fport) {
062e5527 1085 break;
a13a4126
JK
1086 }
1087 }
062e5527
AL
1088 if (!ex_ptr)
1089 return -EINVAL;
1090
0580ac91 1091 so->extra = (void *)ex_ptr->ex_exec;
062e5527
AL
1092 }
1093
285f7a62 1094 if (version_id >= 2) {
460fec67 1095 slirp->ip_id = qemu_get_be16(f);
285f7a62
JK
1096 }
1097
0a1f851e
JK
1098 if (version_id >= 3) {
1099 slirp_bootp_load(f, slirp);
1100 }
1101
062e5527
AL
1102 return 0;
1103}