]> git.proxmox.com Git - qemu.git/blame - slirp/slirp.c
slirp: remove dead initialization, spotted by clang
[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
0a1f851e 235 register_savevm("slirp", 0, 3, slirp_state_save, slirp_state_load, slirp);
9f8bd042 236
72cf2d4f 237 QTAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
ad0d8c4c 238
9f8bd042 239 return slirp;
f0cbd3ec
FB
240}
241
ad0d8c4c
JK
242void slirp_cleanup(Slirp *slirp)
243{
72cf2d4f 244 QTAILQ_REMOVE(&slirp_instances, slirp, entry);
b1c99fcd 245
ad0d8c4c
JK
246 unregister_savevm("slirp", slirp);
247
248 qemu_free(slirp->tftp_prefix);
249 qemu_free(slirp->bootp_filename);
250 qemu_free(slirp);
ad0d8c4c
JK
251}
252
f0cbd3ec
FB
253#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
254#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
255#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
256
5fafdf24 257void slirp_select_fill(int *pnfds,
f0cbd3ec
FB
258 fd_set *readfds, fd_set *writefds, fd_set *xfds)
259{
b1c99fcd 260 Slirp *slirp;
f0cbd3ec 261 struct socket *so, *so_next;
f0cbd3ec 262 int nfds;
f0cbd3ec 263
72cf2d4f 264 if (QTAILQ_EMPTY(&slirp_instances)) {
d918f23e
JK
265 return;
266 }
267
f0cbd3ec
FB
268 /* fail safe */
269 global_readfds = NULL;
270 global_writefds = NULL;
271 global_xfds = NULL;
3b46e624 272
f0cbd3ec
FB
273 nfds = *pnfds;
274 /*
275 * First, TCP sockets
276 */
277 do_slowtimo = 0;
d918f23e 278
72cf2d4f 279 QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
5fafdf24 280 /*
f0cbd3ec
FB
281 * *_slowtimo needs calling if there are IP fragments
282 * in the fragment queue, or there are TCP connections active
283 */
b1c99fcd 284 do_slowtimo |= ((slirp->tcb.so_next != &slirp->tcb) ||
460fec67 285 (&slirp->ipq.ip_link != slirp->ipq.ip_link.next));
3b46e624 286
460fec67
JK
287 for (so = slirp->tcb.so_next; so != &slirp->tcb;
288 so = so_next) {
f0cbd3ec 289 so_next = so->so_next;
3b46e624 290
f0cbd3ec
FB
291 /*
292 * See if we need a tcp_fasttimo
293 */
294 if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
295 time_fasttimo = curtime; /* Flag when we want a fasttimo */
3b46e624 296
f0cbd3ec
FB
297 /*
298 * NOFDREF can include still connecting to local-host,
299 * newly socreated() sockets etc. Don't want to select these.
300 */
301 if (so->so_state & SS_NOFDREF || so->s == -1)
302 continue;
3b46e624 303
f0cbd3ec
FB
304 /*
305 * Set for reading sockets which are accepting
306 */
307 if (so->so_state & SS_FACCEPTCONN) {
308 FD_SET(so->s, readfds);
309 UPD_NFDS(so->s);
310 continue;
311 }
3b46e624 312
f0cbd3ec
FB
313 /*
314 * Set for writing sockets which are connecting
315 */
316 if (so->so_state & SS_ISFCONNECTING) {
317 FD_SET(so->s, writefds);
318 UPD_NFDS(so->s);
319 continue;
320 }
3b46e624 321
f0cbd3ec
FB
322 /*
323 * Set for writing if we are connected, can send more, and
324 * we have something to send
325 */
326 if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
327 FD_SET(so->s, writefds);
328 UPD_NFDS(so->s);
329 }
3b46e624 330
f0cbd3ec
FB
331 /*
332 * Set for reading (and urgent data) if we are connected, can
333 * receive more, and we have room for it XXX /2 ?
334 */
335 if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
336 FD_SET(so->s, readfds);
337 FD_SET(so->s, xfds);
338 UPD_NFDS(so->s);
339 }
340 }
3b46e624 341
f0cbd3ec
FB
342 /*
343 * UDP sockets
344 */
460fec67
JK
345 for (so = slirp->udb.so_next; so != &slirp->udb;
346 so = so_next) {
f0cbd3ec 347 so_next = so->so_next;
3b46e624 348
f0cbd3ec
FB
349 /*
350 * See if it's timed out
351 */
352 if (so->so_expire) {
353 if (so->so_expire <= curtime) {
354 udp_detach(so);
355 continue;
356 } else
357 do_slowtimo = 1; /* Let socket expire */
358 }
3b46e624 359
f0cbd3ec
FB
360 /*
361 * When UDP packets are received from over the
362 * link, they're sendto()'d straight away, so
363 * no need for setting for writing
364 * Limit the number of packets queued by this session
365 * to 4. Note that even though we try and limit this
366 * to 4 packets, the session could have more queued
367 * if the packets needed to be fragmented
368 * (XXX <= 4 ?)
369 */
370 if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
371 FD_SET(so->s, readfds);
372 UPD_NFDS(so->s);
373 }
374 }
b1c99fcd 375 }
5fafdf24 376
f0cbd3ec 377 *pnfds = nfds;
5fafdf24 378}
f0cbd3ec 379
d918f23e
JK
380void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
381 int select_error)
f0cbd3ec 382{
b1c99fcd 383 Slirp *slirp;
f0cbd3ec
FB
384 struct socket *so, *so_next;
385 int ret;
386
72cf2d4f 387 if (QTAILQ_EMPTY(&slirp_instances)) {
d918f23e
JK
388 return;
389 }
390
f0cbd3ec
FB
391 global_readfds = readfds;
392 global_writefds = writefds;
393 global_xfds = xfds;
394
aaf10d9d 395 curtime = qemu_get_clock(rt_clock);
5fafdf24 396
72cf2d4f 397 QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
f0cbd3ec 398 /*
5fafdf24 399 * See if anything has timed out
f0cbd3ec 400 */
df5f8956 401 if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
460fec67 402 tcp_fasttimo(slirp);
f0cbd3ec
FB
403 time_fasttimo = 0;
404 }
405 if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
460fec67
JK
406 ip_slowtimo(slirp);
407 tcp_slowtimo(slirp);
f0cbd3ec
FB
408 last_slowtimo = curtime;
409 }
5fafdf24 410
f0cbd3ec
FB
411 /*
412 * Check sockets
413 */
d918f23e 414 if (!select_error) {
f0cbd3ec
FB
415 /*
416 * Check TCP sockets
417 */
460fec67
JK
418 for (so = slirp->tcb.so_next; so != &slirp->tcb;
419 so = so_next) {
f0cbd3ec 420 so_next = so->so_next;
3b46e624 421
f0cbd3ec
FB
422 /*
423 * FD_ISSET is meaningless on these sockets
424 * (and they can crash the program)
425 */
426 if (so->so_state & SS_NOFDREF || so->s == -1)
427 continue;
3b46e624 428
f0cbd3ec
FB
429 /*
430 * Check for URG data
431 * This will soread as well, so no need to
432 * test for readfds below if this succeeds
433 */
434 if (FD_ISSET(so->s, xfds))
435 sorecvoob(so);
436 /*
437 * Check sockets for reading
438 */
439 else if (FD_ISSET(so->s, readfds)) {
440 /*
441 * Check for incoming connections
442 */
443 if (so->so_state & SS_FACCEPTCONN) {
444 tcp_connect(so);
445 continue;
446 } /* else */
447 ret = soread(so);
3b46e624 448
f0cbd3ec
FB
449 /* Output it if we read something */
450 if (ret > 0)
451 tcp_output(sototcpcb(so));
452 }
3b46e624 453
f0cbd3ec
FB
454 /*
455 * Check sockets for writing
456 */
457 if (FD_ISSET(so->s, writefds)) {
458 /*
459 * Check for non-blocking, still-connecting sockets
460 */
461 if (so->so_state & SS_ISFCONNECTING) {
462 /* Connected */
463 so->so_state &= ~SS_ISFCONNECTING;
3b46e624 464
0a656f5f 465 ret = send(so->s, (const void *) &ret, 0, 0);
f0cbd3ec
FB
466 if (ret < 0) {
467 /* XXXXX Must fix, zero bytes is a NOP */
468 if (errno == EAGAIN || errno == EWOULDBLOCK ||
469 errno == EINPROGRESS || errno == ENOTCONN)
470 continue;
3b46e624 471
f0cbd3ec 472 /* else failed */
f932b6ce
JK
473 so->so_state &= SS_PERSISTENT_MASK;
474 so->so_state |= SS_NOFDREF;
f0cbd3ec
FB
475 }
476 /* else so->so_state &= ~SS_ISFCONNECTING; */
3b46e624 477
f0cbd3ec
FB
478 /*
479 * Continue tcp_input
480 */
481 tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
482 /* continue; */
483 } else
484 ret = sowrite(so);
485 /*
5fafdf24 486 * XXXXX If we wrote something (a lot), there
f0cbd3ec
FB
487 * could be a need for a window update.
488 * In the worst case, the remote will send
489 * a window probe to get things going again
490 */
491 }
3b46e624 492
f0cbd3ec
FB
493 /*
494 * Probe a still-connecting, non-blocking socket
495 * to check if it's still alive
496 */
497#ifdef PROBE_CONN
498 if (so->so_state & SS_ISFCONNECTING) {
02d2c54c 499 ret = recv(so->s, (char *)&ret, 0,0);
3b46e624 500
f0cbd3ec
FB
501 if (ret < 0) {
502 /* XXX */
503 if (errno == EAGAIN || errno == EWOULDBLOCK ||
504 errno == EINPROGRESS || errno == ENOTCONN)
505 continue; /* Still connecting, continue */
3b46e624 506
f0cbd3ec 507 /* else failed */
f932b6ce
JK
508 so->so_state &= SS_PERSISTENT_MASK;
509 so->so_state |= SS_NOFDREF;
3b46e624 510
f0cbd3ec
FB
511 /* tcp_input will take care of it */
512 } else {
02d2c54c 513 ret = send(so->s, &ret, 0,0);
f0cbd3ec
FB
514 if (ret < 0) {
515 /* XXX */
516 if (errno == EAGAIN || errno == EWOULDBLOCK ||
517 errno == EINPROGRESS || errno == ENOTCONN)
518 continue;
519 /* else failed */
f932b6ce
JK
520 so->so_state &= SS_PERSISTENT_MASK;
521 so->so_state |= SS_NOFDREF;
f0cbd3ec
FB
522 } else
523 so->so_state &= ~SS_ISFCONNECTING;
3b46e624 524
f0cbd3ec
FB
525 }
526 tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
527 } /* SS_ISFCONNECTING */
528#endif
529 }
3b46e624 530
f0cbd3ec
FB
531 /*
532 * Now UDP sockets.
533 * Incoming packets are sent straight away, they're not buffered.
534 * Incoming UDP data isn't buffered either.
535 */
460fec67
JK
536 for (so = slirp->udb.so_next; so != &slirp->udb;
537 so = so_next) {
f0cbd3ec 538 so_next = so->so_next;
3b46e624 539
f0cbd3ec
FB
540 if (so->s != -1 && FD_ISSET(so->s, readfds)) {
541 sorecvfrom(so);
542 }
543 }
544 }
5fafdf24 545
f0cbd3ec
FB
546 /*
547 * See if we can start outputting
548 */
460fec67
JK
549 if (slirp->if_queued) {
550 if_start(slirp);
551 }
b1c99fcd 552 }
02d2c54c
FB
553
554 /* clear global file descriptor sets.
555 * these reside on the stack in vl.c
556 * so they're unusable if we're not in
557 * slirp_select_fill or slirp_select_poll.
558 */
559 global_readfds = NULL;
560 global_writefds = NULL;
561 global_xfds = NULL;
f0cbd3ec
FB
562}
563
564#define ETH_ALEN 6
565#define ETH_HLEN 14
566
567#define ETH_P_IP 0x0800 /* Internet Protocol packet */
568#define ETH_P_ARP 0x0806 /* Address Resolution packet */
569
570#define ARPOP_REQUEST 1 /* ARP request */
571#define ARPOP_REPLY 2 /* ARP reply */
572
5fafdf24 573struct ethhdr
f0cbd3ec
FB
574{
575 unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
576 unsigned char h_source[ETH_ALEN]; /* source ether addr */
577 unsigned short h_proto; /* packet type ID field */
578};
579
580struct arphdr
581{
582 unsigned short ar_hrd; /* format of hardware address */
583 unsigned short ar_pro; /* format of protocol address */
584 unsigned char ar_hln; /* length of hardware address */
585 unsigned char ar_pln; /* length of protocol address */
586 unsigned short ar_op; /* ARP opcode (command) */
587
588 /*
589 * Ethernet looks like this : This bit is variable sized however...
590 */
591 unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
a13a4126 592 uint32_t ar_sip; /* sender IP address */
f0cbd3ec 593 unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
a13a4126
JK
594 uint32_t ar_tip ; /* target IP address */
595} __attribute__((packed));
f0cbd3ec 596
460fec67 597static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
f0cbd3ec
FB
598{
599 struct ethhdr *eh = (struct ethhdr *)pkt;
600 struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
601 uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
602 struct ethhdr *reh = (struct ethhdr *)arp_reply;
603 struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
604 int ar_op;
a3d4af03 605 struct ex_list *ex_ptr;
f0cbd3ec
FB
606
607 ar_op = ntohs(ah->ar_op);
608 switch(ar_op) {
609 case ARPOP_REQUEST:
460fec67
JK
610 if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
611 slirp->vnetwork_addr.s_addr) {
612 if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
613 ah->ar_tip == slirp->vhost_addr.s_addr)
a3d4af03 614 goto arp_ok;
460fec67 615 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
a13a4126 616 if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
a3d4af03
FB
617 goto arp_ok;
618 }
619 return;
620 arp_ok:
f0cbd3ec 621 /* XXX: make an ARP request to have the client address */
460fec67 622 memcpy(slirp->client_ethaddr, eh->h_source, ETH_ALEN);
f0cbd3ec
FB
623
624 /* ARP request for alias/dns mac address */
625 memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
a13a4126
JK
626 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
627 memcpy(&reh->h_source[2], &ah->ar_tip, 4);
f0cbd3ec
FB
628 reh->h_proto = htons(ETH_P_ARP);
629
630 rah->ar_hrd = htons(1);
631 rah->ar_pro = htons(ETH_P_IP);
632 rah->ar_hln = ETH_ALEN;
633 rah->ar_pln = 4;
634 rah->ar_op = htons(ARPOP_REPLY);
635 memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
a13a4126 636 rah->ar_sip = ah->ar_tip;
f0cbd3ec 637 memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
a13a4126 638 rah->ar_tip = ah->ar_sip;
9f8bd042 639 slirp_output(slirp->opaque, arp_reply, sizeof(arp_reply));
f0cbd3ec
FB
640 }
641 break;
de806f07
FB
642 case ARPOP_REPLY:
643 /* reply to request of client mac address ? */
460fec67
JK
644 if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN) &&
645 ah->ar_sip == slirp->client_ipaddr.s_addr) {
646 memcpy(slirp->client_ethaddr, ah->ar_sha, ETH_ALEN);
de806f07
FB
647 }
648 break;
f0cbd3ec
FB
649 default:
650 break;
651 }
652}
653
9f8bd042 654void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
f0cbd3ec
FB
655{
656 struct mbuf *m;
657 int proto;
658
659 if (pkt_len < ETH_HLEN)
660 return;
3b46e624 661
f0cbd3ec
FB
662 proto = ntohs(*(uint16_t *)(pkt + 12));
663 switch(proto) {
664 case ETH_P_ARP:
460fec67 665 arp_input(slirp, pkt, pkt_len);
f0cbd3ec
FB
666 break;
667 case ETH_P_IP:
460fec67 668 m = m_get(slirp);
f0cbd3ec
FB
669 if (!m)
670 return;
38f3e7c2 671 /* Note: we add to align the IP header */
e8e880a7
AJ
672 if (M_FREEROOM(m) < pkt_len + 2) {
673 m_inc(m, pkt_len + 2);
674 }
38f3e7c2
FB
675 m->m_len = pkt_len + 2;
676 memcpy(m->m_data + 2, pkt, pkt_len);
f0cbd3ec 677
38f3e7c2
FB
678 m->m_data += 2 + ETH_HLEN;
679 m->m_len -= 2 + ETH_HLEN;
f0cbd3ec
FB
680
681 ip_input(m);
682 break;
683 default:
684 break;
685 }
686}
687
688/* output the IP packet to the ethernet device */
460fec67 689void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len)
f0cbd3ec
FB
690{
691 uint8_t buf[1600];
692 struct ethhdr *eh = (struct ethhdr *)buf;
693
694 if (ip_data_len + ETH_HLEN > sizeof(buf))
695 return;
de806f07 696
460fec67 697 if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN)) {
de806f07
FB
698 uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
699 struct ethhdr *reh = (struct ethhdr *)arp_req;
700 struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
701 const struct ip *iph = (const struct ip *)ip_data;
702
703 /* If the client addr is not known, there is no point in
704 sending the packet to it. Normally the sender should have
705 done an ARP request to get its MAC address. Here we do it
706 in place of sending the packet and we hope that the sender
707 will retry sending its packet. */
708 memset(reh->h_dest, 0xff, ETH_ALEN);
a13a4126 709 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
460fec67 710 memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
de806f07
FB
711 reh->h_proto = htons(ETH_P_ARP);
712 rah->ar_hrd = htons(1);
713 rah->ar_pro = htons(ETH_P_IP);
714 rah->ar_hln = ETH_ALEN;
715 rah->ar_pln = 4;
716 rah->ar_op = htons(ARPOP_REQUEST);
717 /* source hw addr */
a13a4126 718 memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
460fec67 719 memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
de806f07 720 /* source IP */
460fec67 721 rah->ar_sip = slirp->vhost_addr.s_addr;
de806f07
FB
722 /* target hw addr (none) */
723 memset(rah->ar_tha, 0, ETH_ALEN);
724 /* target IP */
a13a4126 725 rah->ar_tip = iph->ip_dst.s_addr;
460fec67 726 slirp->client_ipaddr = iph->ip_dst;
9f8bd042 727 slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
de806f07 728 } else {
460fec67 729 memcpy(eh->h_dest, slirp->client_ethaddr, ETH_ALEN);
a13a4126 730 memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
de806f07 731 /* XXX: not correct */
460fec67 732 memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
de806f07
FB
733 eh->h_proto = htons(ETH_P_IP);
734 memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
9f8bd042 735 slirp_output(slirp->opaque, buf, ip_data_len + ETH_HLEN);
de806f07 736 }
f0cbd3ec 737}
9bf05444 738
9c12a6f2 739/* Drop host forwarding rule, return 0 if found. */
9f8bd042
JK
740int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
741 int host_port)
c1261d8d
AG
742{
743 struct socket *so;
460fec67 744 struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);
2ad82cf9
JK
745 struct sockaddr_in addr;
746 int port = htons(host_port);
747 socklen_t addr_len;
c1261d8d 748
c1261d8d 749 for (so = head->so_next; so != head; so = so->so_next) {
2ad82cf9 750 addr_len = sizeof(addr);
9c12a6f2
JK
751 if ((so->so_state & SS_HOSTFWD) &&
752 getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
3c6a0580 753 addr.sin_addr.s_addr == host_addr.s_addr &&
2ad82cf9 754 addr.sin_port == port) {
c1261d8d
AG
755 close(so->s);
756 sofree(so);
9c12a6f2 757 return 0;
c1261d8d
AG
758 }
759 }
760
9c12a6f2 761 return -1;
c1261d8d
AG
762}
763
9f8bd042
JK
764int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
765 int host_port, struct in_addr guest_addr, int guest_port)
9bf05444 766{
a13a4126 767 if (!guest_addr.s_addr) {
460fec67 768 guest_addr = slirp->vdhcp_startaddr;
a13a4126 769 }
9bf05444 770 if (is_udp) {
460fec67
JK
771 if (!udp_listen(slirp, host_addr.s_addr, htons(host_port),
772 guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
9bf05444
FB
773 return -1;
774 } else {
460fec67
JK
775 if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port),
776 guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
9bf05444
FB
777 return -1;
778 }
779 return 0;
780}
a3d4af03 781
9f8bd042 782int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
bb53fc53 783 struct in_addr *guest_addr, int guest_port)
a3d4af03 784{
bb53fc53
JK
785 if (!guest_addr->s_addr) {
786 guest_addr->s_addr = slirp->vnetwork_addr.s_addr |
460fec67 787 (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
c92ef6a2 788 }
bb53fc53 789 if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) !=
460fec67 790 slirp->vnetwork_addr.s_addr ||
bb53fc53
JK
791 guest_addr->s_addr == slirp->vhost_addr.s_addr ||
792 guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
a13a4126
JK
793 return -1;
794 }
bb53fc53 795 return add_exec(&slirp->exec_list, do_pty, (char *)args, *guest_addr,
a13a4126 796 htons(guest_port));
a3d4af03 797}
e1c5a2b3
AL
798
799ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
800{
801 if (so->s == -1 && so->extra) {
802 qemu_chr_write(so->extra, buf, len);
803 return len;
804 }
805
806 return send(so->s, buf, len, flags);
807}
808
a13a4126 809static struct socket *
460fec67 810slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port)
e1c5a2b3 811{
a13a4126 812 struct socket *so;
e1c5a2b3 813
460fec67 814 for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
a13a4126
JK
815 if (so->so_faddr.s_addr == guest_addr.s_addr &&
816 htons(so->so_fport) == guest_port) {
817 return so;
818 }
819 }
820 return NULL;
e1c5a2b3
AL
821}
822
9f8bd042
JK
823size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
824 int guest_port)
e1c5a2b3
AL
825{
826 struct iovec iov[2];
827 struct socket *so;
828
460fec67 829 so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
e1c5a2b3
AL
830
831 if (!so || so->so_state & SS_NOFDREF)
832 return 0;
833
834 if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
835 return 0;
836
837 return sopreprbuf(so, iov, NULL);
838}
839
9f8bd042 840void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
c92ef6a2 841 const uint8_t *buf, int size)
e1c5a2b3
AL
842{
843 int ret;
460fec67 844 struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
a13a4126 845
e1c5a2b3
AL
846 if (!so)
847 return;
848
0580ac91 849 ret = soreadbuf(so, (const char *)buf, size);
e1c5a2b3
AL
850
851 if (ret > 0)
852 tcp_output(sototcpcb(so));
853}
062e5527
AL
854
855static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
856{
857 int i;
858
859 qemu_put_sbe16(f, tp->t_state);
860 for (i = 0; i < TCPT_NTIMERS; i++)
861 qemu_put_sbe16(f, tp->t_timer[i]);
862 qemu_put_sbe16(f, tp->t_rxtshift);
863 qemu_put_sbe16(f, tp->t_rxtcur);
864 qemu_put_sbe16(f, tp->t_dupacks);
865 qemu_put_be16(f, tp->t_maxseg);
866 qemu_put_sbyte(f, tp->t_force);
867 qemu_put_be16(f, tp->t_flags);
868 qemu_put_be32(f, tp->snd_una);
869 qemu_put_be32(f, tp->snd_nxt);
870 qemu_put_be32(f, tp->snd_up);
871 qemu_put_be32(f, tp->snd_wl1);
872 qemu_put_be32(f, tp->snd_wl2);
873 qemu_put_be32(f, tp->iss);
874 qemu_put_be32(f, tp->snd_wnd);
875 qemu_put_be32(f, tp->rcv_wnd);
876 qemu_put_be32(f, tp->rcv_nxt);
877 qemu_put_be32(f, tp->rcv_up);
878 qemu_put_be32(f, tp->irs);
879 qemu_put_be32(f, tp->rcv_adv);
880 qemu_put_be32(f, tp->snd_max);
881 qemu_put_be32(f, tp->snd_cwnd);
882 qemu_put_be32(f, tp->snd_ssthresh);
883 qemu_put_sbe16(f, tp->t_idle);
884 qemu_put_sbe16(f, tp->t_rtt);
885 qemu_put_be32(f, tp->t_rtseq);
886 qemu_put_sbe16(f, tp->t_srtt);
887 qemu_put_sbe16(f, tp->t_rttvar);
888 qemu_put_be16(f, tp->t_rttmin);
889 qemu_put_be32(f, tp->max_sndwnd);
890 qemu_put_byte(f, tp->t_oobflags);
891 qemu_put_byte(f, tp->t_iobc);
892 qemu_put_sbe16(f, tp->t_softerror);
893 qemu_put_byte(f, tp->snd_scale);
894 qemu_put_byte(f, tp->rcv_scale);
895 qemu_put_byte(f, tp->request_r_scale);
896 qemu_put_byte(f, tp->requested_s_scale);
897 qemu_put_be32(f, tp->ts_recent);
898 qemu_put_be32(f, tp->ts_recent_age);
899 qemu_put_be32(f, tp->last_ack_sent);
900}
901
902static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
903{
904 uint32_t off;
905
906 qemu_put_be32(f, sbuf->sb_cc);
907 qemu_put_be32(f, sbuf->sb_datalen);
908 off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
909 qemu_put_sbe32(f, off);
910 off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
911 qemu_put_sbe32(f, off);
912 qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
913}
914
915static void slirp_socket_save(QEMUFile *f, struct socket *so)
916{
917 qemu_put_be32(f, so->so_urgc);
918 qemu_put_be32(f, so->so_faddr.s_addr);
919 qemu_put_be32(f, so->so_laddr.s_addr);
920 qemu_put_be16(f, so->so_fport);
921 qemu_put_be16(f, so->so_lport);
922 qemu_put_byte(f, so->so_iptos);
923 qemu_put_byte(f, so->so_emu);
924 qemu_put_byte(f, so->so_type);
925 qemu_put_be32(f, so->so_state);
926 slirp_sbuf_save(f, &so->so_rcv);
927 slirp_sbuf_save(f, &so->so_snd);
928 slirp_tcp_save(f, so->so_tcpcb);
929}
930
0a1f851e
JK
931static void slirp_bootp_save(QEMUFile *f, Slirp *slirp)
932{
933 int i;
934
935 for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
936 qemu_put_be16(f, slirp->bootp_clients[i].allocated);
937 qemu_put_buffer(f, slirp->bootp_clients[i].macaddr, 6);
938 }
939}
940
062e5527
AL
941static void slirp_state_save(QEMUFile *f, void *opaque)
942{
460fec67 943 Slirp *slirp = opaque;
062e5527
AL
944 struct ex_list *ex_ptr;
945
460fec67 946 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
062e5527
AL
947 if (ex_ptr->ex_pty == 3) {
948 struct socket *so;
460fec67
JK
949 so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
950 ntohs(ex_ptr->ex_fport));
062e5527
AL
951 if (!so)
952 continue;
953
954 qemu_put_byte(f, 42);
955 slirp_socket_save(f, so);
956 }
957 qemu_put_byte(f, 0);
285f7a62 958
460fec67 959 qemu_put_be16(f, slirp->ip_id);
0a1f851e
JK
960
961 slirp_bootp_save(f, slirp);
062e5527
AL
962}
963
964static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
965{
966 int i;
967
968 tp->t_state = qemu_get_sbe16(f);
969 for (i = 0; i < TCPT_NTIMERS; i++)
970 tp->t_timer[i] = qemu_get_sbe16(f);
971 tp->t_rxtshift = qemu_get_sbe16(f);
972 tp->t_rxtcur = qemu_get_sbe16(f);
973 tp->t_dupacks = qemu_get_sbe16(f);
974 tp->t_maxseg = qemu_get_be16(f);
975 tp->t_force = qemu_get_sbyte(f);
976 tp->t_flags = qemu_get_be16(f);
977 tp->snd_una = qemu_get_be32(f);
978 tp->snd_nxt = qemu_get_be32(f);
979 tp->snd_up = qemu_get_be32(f);
980 tp->snd_wl1 = qemu_get_be32(f);
981 tp->snd_wl2 = qemu_get_be32(f);
982 tp->iss = qemu_get_be32(f);
983 tp->snd_wnd = qemu_get_be32(f);
984 tp->rcv_wnd = qemu_get_be32(f);
985 tp->rcv_nxt = qemu_get_be32(f);
986 tp->rcv_up = qemu_get_be32(f);
987 tp->irs = qemu_get_be32(f);
988 tp->rcv_adv = qemu_get_be32(f);
989 tp->snd_max = qemu_get_be32(f);
990 tp->snd_cwnd = qemu_get_be32(f);
991 tp->snd_ssthresh = qemu_get_be32(f);
992 tp->t_idle = qemu_get_sbe16(f);
993 tp->t_rtt = qemu_get_sbe16(f);
994 tp->t_rtseq = qemu_get_be32(f);
995 tp->t_srtt = qemu_get_sbe16(f);
996 tp->t_rttvar = qemu_get_sbe16(f);
997 tp->t_rttmin = qemu_get_be16(f);
998 tp->max_sndwnd = qemu_get_be32(f);
999 tp->t_oobflags = qemu_get_byte(f);
1000 tp->t_iobc = qemu_get_byte(f);
1001 tp->t_softerror = qemu_get_sbe16(f);
1002 tp->snd_scale = qemu_get_byte(f);
1003 tp->rcv_scale = qemu_get_byte(f);
1004 tp->request_r_scale = qemu_get_byte(f);
1005 tp->requested_s_scale = qemu_get_byte(f);
1006 tp->ts_recent = qemu_get_be32(f);
1007 tp->ts_recent_age = qemu_get_be32(f);
1008 tp->last_ack_sent = qemu_get_be32(f);
1009 tcp_template(tp);
1010}
1011
1012static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
1013{
1014 uint32_t off, sb_cc, sb_datalen;
1015
1016 sb_cc = qemu_get_be32(f);
1017 sb_datalen = qemu_get_be32(f);
1018
1019 sbreserve(sbuf, sb_datalen);
1020
1021 if (sbuf->sb_datalen != sb_datalen)
1022 return -ENOMEM;
1023
1024 sbuf->sb_cc = sb_cc;
1025
1026 off = qemu_get_sbe32(f);
1027 sbuf->sb_wptr = sbuf->sb_data + off;
1028 off = qemu_get_sbe32(f);
1029 sbuf->sb_rptr = sbuf->sb_data + off;
1030 qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
1031
1032 return 0;
1033}
1034
1035static int slirp_socket_load(QEMUFile *f, struct socket *so)
1036{
1037 if (tcp_attach(so) < 0)
1038 return -ENOMEM;
1039
1040 so->so_urgc = qemu_get_be32(f);
1041 so->so_faddr.s_addr = qemu_get_be32(f);
1042 so->so_laddr.s_addr = qemu_get_be32(f);
1043 so->so_fport = qemu_get_be16(f);
1044 so->so_lport = qemu_get_be16(f);
1045 so->so_iptos = qemu_get_byte(f);
1046 so->so_emu = qemu_get_byte(f);
1047 so->so_type = qemu_get_byte(f);
1048 so->so_state = qemu_get_be32(f);
1049 if (slirp_sbuf_load(f, &so->so_rcv) < 0)
1050 return -ENOMEM;
1051 if (slirp_sbuf_load(f, &so->so_snd) < 0)
1052 return -ENOMEM;
1053 slirp_tcp_load(f, so->so_tcpcb);
1054
1055 return 0;
1056}
1057
0a1f851e
JK
1058static void slirp_bootp_load(QEMUFile *f, Slirp *slirp)
1059{
1060 int i;
1061
1062 for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
1063 slirp->bootp_clients[i].allocated = qemu_get_be16(f);
1064 qemu_get_buffer(f, slirp->bootp_clients[i].macaddr, 6);
1065 }
1066}
1067
062e5527
AL
1068static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
1069{
460fec67 1070 Slirp *slirp = opaque;
062e5527
AL
1071 struct ex_list *ex_ptr;
1072 int r;
1073
1074 while ((r = qemu_get_byte(f))) {
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}