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