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