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