cocoa: Revert dependency on VNC
[qemu/kevin.git] / slirp / slirp.c
blob1593be177e4a8facec4db75255020cf0b232a708
1 /*
2 * libslirp glue
4 * Copyright (c) 2004-2008 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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.
24 #include "qemu-common.h"
25 #include "qemu-timer.h"
26 #include "qemu-char.h"
27 #include "slirp.h"
28 #include "hw/hw.h"
30 /* host loopback address */
31 struct in_addr loopback_addr;
33 /* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
34 static const uint8_t special_ethaddr[6] = {
35 0x52, 0x55, 0x00, 0x00, 0x00, 0x00
38 static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
40 /* XXX: suppress those select globals */
41 fd_set *global_readfds, *global_writefds, *global_xfds;
43 u_int curtime;
44 static u_int time_fasttimo, last_slowtimo;
45 static int do_slowtimo;
47 static QTAILQ_HEAD(slirp_instances, Slirp) slirp_instances =
48 QTAILQ_HEAD_INITIALIZER(slirp_instances);
50 static struct in_addr dns_addr;
51 static u_int dns_addr_time;
53 #ifdef _WIN32
55 int get_dns_addr(struct in_addr *pdns_addr)
57 FIXED_INFO *FixedInfo=NULL;
58 ULONG BufLen;
59 DWORD ret;
60 IP_ADDR_STRING *pIPAddr;
61 struct in_addr tmp_addr;
63 if (dns_addr.s_addr != 0 && (curtime - dns_addr_time) < 1000) {
64 *pdns_addr = dns_addr;
65 return 0;
68 FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
69 BufLen = sizeof(FIXED_INFO);
71 if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
72 if (FixedInfo) {
73 GlobalFree(FixedInfo);
74 FixedInfo = NULL;
76 FixedInfo = GlobalAlloc(GPTR, BufLen);
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;
85 return -1;
88 pIPAddr = &(FixedInfo->DnsServerList);
89 inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
90 *pdns_addr = tmp_addr;
91 dns_addr = tmp_addr;
92 dns_addr_time = curtime;
93 if (FixedInfo) {
94 GlobalFree(FixedInfo);
95 FixedInfo = NULL;
97 return 0;
100 static void winsock_cleanup(void)
102 WSACleanup();
105 #else
107 static struct stat dns_addr_stat;
109 int get_dns_addr(struct in_addr *pdns_addr)
111 char buff[512];
112 char buff2[257];
113 FILE *f;
114 int found = 0;
115 struct in_addr tmp_addr;
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;
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;
135 f = fopen("/etc/resolv.conf", "r");
136 if (!f)
137 return -1;
139 #ifdef DEBUG
140 lprint("IP address of your DNS(s): ");
141 #endif
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;
146 /* If it's the first one, set it to dns_addr */
147 if (!found) {
148 *pdns_addr = tmp_addr;
149 dns_addr = tmp_addr;
150 dns_addr_time = curtime;
152 #ifdef DEBUG
153 else
154 lprint(", ");
155 #endif
156 if (++found > 3) {
157 #ifdef DEBUG
158 lprint("(more)");
159 #endif
160 break;
162 #ifdef DEBUG
163 else
164 lprint("%s", inet_ntoa(tmp_addr));
165 #endif
168 fclose(f);
169 if (!found)
170 return -1;
171 return 0;
174 #endif
176 static void slirp_init_once(void)
178 static int initialized;
179 #ifdef _WIN32
180 WSADATA Data;
181 #endif
183 if (initialized) {
184 return;
186 initialized = 1;
188 #ifdef _WIN32
189 WSAStartup(MAKEWORD(2,0), &Data);
190 atexit(winsock_cleanup);
191 #endif
193 loopback_addr.s_addr = htonl(INADDR_LOOPBACK);
196 static void slirp_state_save(QEMUFile *f, void *opaque);
197 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
199 Slirp *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)
205 Slirp *slirp = qemu_mallocz(sizeof(Slirp));
207 slirp_init_once();
209 slirp->restricted = restricted;
211 if_init(slirp);
212 ip_init(slirp);
214 /* Initialise mbufs *after* setting the MTU */
215 m_init(slirp);
217 slirp->vnetwork_addr = vnetwork;
218 slirp->vnetwork_mask = vnetmask;
219 slirp->vhost_addr = vhost;
220 if (vhostname) {
221 pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
222 vhostname);
224 if (tftp_path) {
225 slirp->tftp_prefix = qemu_strdup(tftp_path);
227 if (bootfile) {
228 slirp->bootp_filename = qemu_strdup(bootfile);
230 slirp->vdhcp_startaddr = vdhcp_start;
231 slirp->vnameserver_addr = vnameserver;
233 slirp->opaque = opaque;
235 register_savevm(NULL, "slirp", 0, 3,
236 slirp_state_save, slirp_state_load, slirp);
238 QTAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
240 return slirp;
243 void slirp_cleanup(Slirp *slirp)
245 QTAILQ_REMOVE(&slirp_instances, slirp, entry);
247 unregister_savevm(NULL, "slirp", slirp);
249 qemu_free(slirp->tftp_prefix);
250 qemu_free(slirp->bootp_filename);
251 qemu_free(slirp);
254 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
255 #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
256 #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
258 void slirp_select_fill(int *pnfds,
259 fd_set *readfds, fd_set *writefds, fd_set *xfds)
261 Slirp *slirp;
262 struct socket *so, *so_next;
263 int nfds;
265 if (QTAILQ_EMPTY(&slirp_instances)) {
266 return;
269 /* fail safe */
270 global_readfds = NULL;
271 global_writefds = NULL;
272 global_xfds = NULL;
274 nfds = *pnfds;
276 * First, TCP sockets
278 do_slowtimo = 0;
280 QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
282 * *_slowtimo needs calling if there are IP fragments
283 * in the fragment queue, or there are TCP connections active
285 do_slowtimo |= ((slirp->tcb.so_next != &slirp->tcb) ||
286 (&slirp->ipq.ip_link != slirp->ipq.ip_link.next));
288 for (so = slirp->tcb.so_next; so != &slirp->tcb;
289 so = so_next) {
290 so_next = so->so_next;
293 * See if we need a tcp_fasttimo
295 if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
296 time_fasttimo = curtime; /* Flag when we want a fasttimo */
299 * NOFDREF can include still connecting to local-host,
300 * newly socreated() sockets etc. Don't want to select these.
302 if (so->so_state & SS_NOFDREF || so->s == -1)
303 continue;
306 * Set for reading sockets which are accepting
308 if (so->so_state & SS_FACCEPTCONN) {
309 FD_SET(so->s, readfds);
310 UPD_NFDS(so->s);
311 continue;
315 * Set for writing sockets which are connecting
317 if (so->so_state & SS_ISFCONNECTING) {
318 FD_SET(so->s, writefds);
319 UPD_NFDS(so->s);
320 continue;
324 * Set for writing if we are connected, can send more, and
325 * we have something to send
327 if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
328 FD_SET(so->s, writefds);
329 UPD_NFDS(so->s);
333 * Set for reading (and urgent data) if we are connected, can
334 * receive more, and we have room for it XXX /2 ?
336 if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
337 FD_SET(so->s, readfds);
338 FD_SET(so->s, xfds);
339 UPD_NFDS(so->s);
344 * UDP sockets
346 for (so = slirp->udb.so_next; so != &slirp->udb;
347 so = so_next) {
348 so_next = so->so_next;
351 * See if it's timed out
353 if (so->so_expire) {
354 if (so->so_expire <= curtime) {
355 udp_detach(so);
356 continue;
357 } else
358 do_slowtimo = 1; /* Let socket expire */
362 * When UDP packets are received from over the
363 * link, they're sendto()'d straight away, so
364 * no need for setting for writing
365 * Limit the number of packets queued by this session
366 * to 4. Note that even though we try and limit this
367 * to 4 packets, the session could have more queued
368 * if the packets needed to be fragmented
369 * (XXX <= 4 ?)
371 if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
372 FD_SET(so->s, readfds);
373 UPD_NFDS(so->s);
378 *pnfds = nfds;
381 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
382 int select_error)
384 Slirp *slirp;
385 struct socket *so, *so_next;
386 int ret;
388 if (QTAILQ_EMPTY(&slirp_instances)) {
389 return;
392 global_readfds = readfds;
393 global_writefds = writefds;
394 global_xfds = xfds;
396 curtime = qemu_get_clock_ms(rt_clock);
398 QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
400 * See if anything has timed out
402 if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
403 tcp_fasttimo(slirp);
404 time_fasttimo = 0;
406 if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
407 ip_slowtimo(slirp);
408 tcp_slowtimo(slirp);
409 last_slowtimo = curtime;
413 * Check sockets
415 if (!select_error) {
417 * Check TCP sockets
419 for (so = slirp->tcb.so_next; so != &slirp->tcb;
420 so = so_next) {
421 so_next = so->so_next;
424 * FD_ISSET is meaningless on these sockets
425 * (and they can crash the program)
427 if (so->so_state & SS_NOFDREF || so->s == -1)
428 continue;
431 * Check for URG data
432 * This will soread as well, so no need to
433 * test for readfds below if this succeeds
435 if (FD_ISSET(so->s, xfds))
436 sorecvoob(so);
438 * Check sockets for reading
440 else if (FD_ISSET(so->s, readfds)) {
442 * Check for incoming connections
444 if (so->so_state & SS_FACCEPTCONN) {
445 tcp_connect(so);
446 continue;
447 } /* else */
448 ret = soread(so);
450 /* Output it if we read something */
451 if (ret > 0)
452 tcp_output(sototcpcb(so));
456 * Check sockets for writing
458 if (FD_ISSET(so->s, writefds)) {
460 * Check for non-blocking, still-connecting sockets
462 if (so->so_state & SS_ISFCONNECTING) {
463 /* Connected */
464 so->so_state &= ~SS_ISFCONNECTING;
466 ret = send(so->s, (const void *) &ret, 0, 0);
467 if (ret < 0) {
468 /* XXXXX Must fix, zero bytes is a NOP */
469 if (errno == EAGAIN || errno == EWOULDBLOCK ||
470 errno == EINPROGRESS || errno == ENOTCONN)
471 continue;
473 /* else failed */
474 so->so_state &= SS_PERSISTENT_MASK;
475 so->so_state |= SS_NOFDREF;
477 /* else so->so_state &= ~SS_ISFCONNECTING; */
480 * Continue tcp_input
482 tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
483 /* continue; */
484 } else
485 ret = sowrite(so);
487 * XXXXX If we wrote something (a lot), there
488 * could be a need for a window update.
489 * In the worst case, the remote will send
490 * a window probe to get things going again
495 * Probe a still-connecting, non-blocking socket
496 * to check if it's still alive
498 #ifdef PROBE_CONN
499 if (so->so_state & SS_ISFCONNECTING) {
500 ret = recv(so->s, (char *)&ret, 0,0);
502 if (ret < 0) {
503 /* XXX */
504 if (errno == EAGAIN || errno == EWOULDBLOCK ||
505 errno == EINPROGRESS || errno == ENOTCONN)
506 continue; /* Still connecting, continue */
508 /* else failed */
509 so->so_state &= SS_PERSISTENT_MASK;
510 so->so_state |= SS_NOFDREF;
512 /* tcp_input will take care of it */
513 } else {
514 ret = send(so->s, &ret, 0,0);
515 if (ret < 0) {
516 /* XXX */
517 if (errno == EAGAIN || errno == EWOULDBLOCK ||
518 errno == EINPROGRESS || errno == ENOTCONN)
519 continue;
520 /* else failed */
521 so->so_state &= SS_PERSISTENT_MASK;
522 so->so_state |= SS_NOFDREF;
523 } else
524 so->so_state &= ~SS_ISFCONNECTING;
527 tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
528 } /* SS_ISFCONNECTING */
529 #endif
533 * Now UDP sockets.
534 * Incoming packets are sent straight away, they're not buffered.
535 * Incoming UDP data isn't buffered either.
537 for (so = slirp->udb.so_next; so != &slirp->udb;
538 so = so_next) {
539 so_next = so->so_next;
541 if (so->s != -1 && FD_ISSET(so->s, readfds)) {
542 sorecvfrom(so);
548 * See if we can start outputting
550 if (slirp->if_queued) {
551 if_start(slirp);
555 /* clear global file descriptor sets.
556 * these reside on the stack in vl.c
557 * so they're unusable if we're not in
558 * slirp_select_fill or slirp_select_poll.
560 global_readfds = NULL;
561 global_writefds = NULL;
562 global_xfds = NULL;
565 #define ETH_ALEN 6
566 #define ETH_HLEN 14
568 #define ETH_P_IP 0x0800 /* Internet Protocol packet */
569 #define ETH_P_ARP 0x0806 /* Address Resolution packet */
571 #define ARPOP_REQUEST 1 /* ARP request */
572 #define ARPOP_REPLY 2 /* ARP reply */
574 struct ethhdr
576 unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
577 unsigned char h_source[ETH_ALEN]; /* source ether addr */
578 unsigned short h_proto; /* packet type ID field */
581 struct arphdr
583 unsigned short ar_hrd; /* format of hardware address */
584 unsigned short ar_pro; /* format of protocol address */
585 unsigned char ar_hln; /* length of hardware address */
586 unsigned char ar_pln; /* length of protocol address */
587 unsigned short ar_op; /* ARP opcode (command) */
590 * Ethernet looks like this : This bit is variable sized however...
592 unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
593 uint32_t ar_sip; /* sender IP address */
594 unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
595 uint32_t ar_tip ; /* target IP address */
596 } __attribute__((packed));
598 static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
600 struct ethhdr *eh = (struct ethhdr *)pkt;
601 struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
602 uint8_t arp_reply[max(ETH_HLEN + sizeof(struct arphdr), 64)];
603 struct ethhdr *reh = (struct ethhdr *)arp_reply;
604 struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
605 int ar_op;
606 struct ex_list *ex_ptr;
608 ar_op = ntohs(ah->ar_op);
609 switch(ar_op) {
610 case ARPOP_REQUEST:
611 if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
612 slirp->vnetwork_addr.s_addr) {
613 if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
614 ah->ar_tip == slirp->vhost_addr.s_addr)
615 goto arp_ok;
616 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
617 if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
618 goto arp_ok;
620 return;
621 arp_ok:
622 memset(arp_reply, 0, sizeof(arp_reply));
623 /* XXX: make an ARP request to have the client address */
624 memcpy(slirp->client_ethaddr, eh->h_source, ETH_ALEN);
626 /* ARP request for alias/dns mac address */
627 memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
628 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
629 memcpy(&reh->h_source[2], &ah->ar_tip, 4);
630 reh->h_proto = htons(ETH_P_ARP);
632 rah->ar_hrd = htons(1);
633 rah->ar_pro = htons(ETH_P_IP);
634 rah->ar_hln = ETH_ALEN;
635 rah->ar_pln = 4;
636 rah->ar_op = htons(ARPOP_REPLY);
637 memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
638 rah->ar_sip = ah->ar_tip;
639 memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
640 rah->ar_tip = ah->ar_sip;
641 slirp_output(slirp->opaque, arp_reply, sizeof(arp_reply));
643 break;
644 case ARPOP_REPLY:
645 /* reply to request of client mac address ? */
646 if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN) &&
647 ah->ar_sip == slirp->client_ipaddr.s_addr) {
648 memcpy(slirp->client_ethaddr, ah->ar_sha, ETH_ALEN);
650 break;
651 default:
652 break;
656 void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
658 struct mbuf *m;
659 int proto;
661 if (pkt_len < ETH_HLEN)
662 return;
664 proto = ntohs(*(uint16_t *)(pkt + 12));
665 switch(proto) {
666 case ETH_P_ARP:
667 arp_input(slirp, pkt, pkt_len);
668 break;
669 case ETH_P_IP:
670 m = m_get(slirp);
671 if (!m)
672 return;
673 /* Note: we add to align the IP header */
674 if (M_FREEROOM(m) < pkt_len + 2) {
675 m_inc(m, pkt_len + 2);
677 m->m_len = pkt_len + 2;
678 memcpy(m->m_data + 2, pkt, pkt_len);
680 m->m_data += 2 + ETH_HLEN;
681 m->m_len -= 2 + ETH_HLEN;
683 ip_input(m);
684 break;
685 default:
686 break;
690 /* output the IP packet to the ethernet device */
691 void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len)
693 uint8_t buf[1600];
694 struct ethhdr *eh = (struct ethhdr *)buf;
696 if (ip_data_len + ETH_HLEN > sizeof(buf))
697 return;
699 if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN)) {
700 uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
701 struct ethhdr *reh = (struct ethhdr *)arp_req;
702 struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
703 const struct ip *iph = (const struct ip *)ip_data;
705 /* If the client addr is not known, there is no point in
706 sending the packet to it. Normally the sender should have
707 done an ARP request to get its MAC address. Here we do it
708 in place of sending the packet and we hope that the sender
709 will retry sending its packet. */
710 memset(reh->h_dest, 0xff, ETH_ALEN);
711 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
712 memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
713 reh->h_proto = htons(ETH_P_ARP);
714 rah->ar_hrd = htons(1);
715 rah->ar_pro = htons(ETH_P_IP);
716 rah->ar_hln = ETH_ALEN;
717 rah->ar_pln = 4;
718 rah->ar_op = htons(ARPOP_REQUEST);
719 /* source hw addr */
720 memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
721 memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
722 /* source IP */
723 rah->ar_sip = slirp->vhost_addr.s_addr;
724 /* target hw addr (none) */
725 memset(rah->ar_tha, 0, ETH_ALEN);
726 /* target IP */
727 rah->ar_tip = iph->ip_dst.s_addr;
728 slirp->client_ipaddr = iph->ip_dst;
729 slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
730 } else {
731 memcpy(eh->h_dest, slirp->client_ethaddr, ETH_ALEN);
732 memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
733 /* XXX: not correct */
734 memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
735 eh->h_proto = htons(ETH_P_IP);
736 memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
737 slirp_output(slirp->opaque, buf, ip_data_len + ETH_HLEN);
741 /* Drop host forwarding rule, return 0 if found. */
742 int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
743 int host_port)
745 struct socket *so;
746 struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);
747 struct sockaddr_in addr;
748 int port = htons(host_port);
749 socklen_t addr_len;
751 for (so = head->so_next; so != head; so = so->so_next) {
752 addr_len = sizeof(addr);
753 if ((so->so_state & SS_HOSTFWD) &&
754 getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
755 addr.sin_addr.s_addr == host_addr.s_addr &&
756 addr.sin_port == port) {
757 close(so->s);
758 sofree(so);
759 return 0;
763 return -1;
766 int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
767 int host_port, struct in_addr guest_addr, int guest_port)
769 if (!guest_addr.s_addr) {
770 guest_addr = slirp->vdhcp_startaddr;
772 if (is_udp) {
773 if (!udp_listen(slirp, host_addr.s_addr, htons(host_port),
774 guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
775 return -1;
776 } else {
777 if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port),
778 guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
779 return -1;
781 return 0;
784 int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
785 struct in_addr *guest_addr, int guest_port)
787 if (!guest_addr->s_addr) {
788 guest_addr->s_addr = slirp->vnetwork_addr.s_addr |
789 (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
791 if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) !=
792 slirp->vnetwork_addr.s_addr ||
793 guest_addr->s_addr == slirp->vhost_addr.s_addr ||
794 guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
795 return -1;
797 return add_exec(&slirp->exec_list, do_pty, (char *)args, *guest_addr,
798 htons(guest_port));
801 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
803 if (so->s == -1 && so->extra) {
804 qemu_chr_write(so->extra, buf, len);
805 return len;
808 return send(so->s, buf, len, flags);
811 static struct socket *
812 slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port)
814 struct socket *so;
816 for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
817 if (so->so_faddr.s_addr == guest_addr.s_addr &&
818 htons(so->so_fport) == guest_port) {
819 return so;
822 return NULL;
825 size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
826 int guest_port)
828 struct iovec iov[2];
829 struct socket *so;
831 so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
833 if (!so || so->so_state & SS_NOFDREF)
834 return 0;
836 if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
837 return 0;
839 return sopreprbuf(so, iov, NULL);
842 void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
843 const uint8_t *buf, int size)
845 int ret;
846 struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
848 if (!so)
849 return;
851 ret = soreadbuf(so, (const char *)buf, size);
853 if (ret > 0)
854 tcp_output(sototcpcb(so));
857 static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
859 int i;
861 qemu_put_sbe16(f, tp->t_state);
862 for (i = 0; i < TCPT_NTIMERS; i++)
863 qemu_put_sbe16(f, tp->t_timer[i]);
864 qemu_put_sbe16(f, tp->t_rxtshift);
865 qemu_put_sbe16(f, tp->t_rxtcur);
866 qemu_put_sbe16(f, tp->t_dupacks);
867 qemu_put_be16(f, tp->t_maxseg);
868 qemu_put_sbyte(f, tp->t_force);
869 qemu_put_be16(f, tp->t_flags);
870 qemu_put_be32(f, tp->snd_una);
871 qemu_put_be32(f, tp->snd_nxt);
872 qemu_put_be32(f, tp->snd_up);
873 qemu_put_be32(f, tp->snd_wl1);
874 qemu_put_be32(f, tp->snd_wl2);
875 qemu_put_be32(f, tp->iss);
876 qemu_put_be32(f, tp->snd_wnd);
877 qemu_put_be32(f, tp->rcv_wnd);
878 qemu_put_be32(f, tp->rcv_nxt);
879 qemu_put_be32(f, tp->rcv_up);
880 qemu_put_be32(f, tp->irs);
881 qemu_put_be32(f, tp->rcv_adv);
882 qemu_put_be32(f, tp->snd_max);
883 qemu_put_be32(f, tp->snd_cwnd);
884 qemu_put_be32(f, tp->snd_ssthresh);
885 qemu_put_sbe16(f, tp->t_idle);
886 qemu_put_sbe16(f, tp->t_rtt);
887 qemu_put_be32(f, tp->t_rtseq);
888 qemu_put_sbe16(f, tp->t_srtt);
889 qemu_put_sbe16(f, tp->t_rttvar);
890 qemu_put_be16(f, tp->t_rttmin);
891 qemu_put_be32(f, tp->max_sndwnd);
892 qemu_put_byte(f, tp->t_oobflags);
893 qemu_put_byte(f, tp->t_iobc);
894 qemu_put_sbe16(f, tp->t_softerror);
895 qemu_put_byte(f, tp->snd_scale);
896 qemu_put_byte(f, tp->rcv_scale);
897 qemu_put_byte(f, tp->request_r_scale);
898 qemu_put_byte(f, tp->requested_s_scale);
899 qemu_put_be32(f, tp->ts_recent);
900 qemu_put_be32(f, tp->ts_recent_age);
901 qemu_put_be32(f, tp->last_ack_sent);
904 static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
906 uint32_t off;
908 qemu_put_be32(f, sbuf->sb_cc);
909 qemu_put_be32(f, sbuf->sb_datalen);
910 off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
911 qemu_put_sbe32(f, off);
912 off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
913 qemu_put_sbe32(f, off);
914 qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
917 static void slirp_socket_save(QEMUFile *f, struct socket *so)
919 qemu_put_be32(f, so->so_urgc);
920 qemu_put_be32(f, so->so_faddr.s_addr);
921 qemu_put_be32(f, so->so_laddr.s_addr);
922 qemu_put_be16(f, so->so_fport);
923 qemu_put_be16(f, so->so_lport);
924 qemu_put_byte(f, so->so_iptos);
925 qemu_put_byte(f, so->so_emu);
926 qemu_put_byte(f, so->so_type);
927 qemu_put_be32(f, so->so_state);
928 slirp_sbuf_save(f, &so->so_rcv);
929 slirp_sbuf_save(f, &so->so_snd);
930 slirp_tcp_save(f, so->so_tcpcb);
933 static void slirp_bootp_save(QEMUFile *f, Slirp *slirp)
935 int i;
937 for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
938 qemu_put_be16(f, slirp->bootp_clients[i].allocated);
939 qemu_put_buffer(f, slirp->bootp_clients[i].macaddr, 6);
943 static void slirp_state_save(QEMUFile *f, void *opaque)
945 Slirp *slirp = opaque;
946 struct ex_list *ex_ptr;
948 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
949 if (ex_ptr->ex_pty == 3) {
950 struct socket *so;
951 so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
952 ntohs(ex_ptr->ex_fport));
953 if (!so)
954 continue;
956 qemu_put_byte(f, 42);
957 slirp_socket_save(f, so);
959 qemu_put_byte(f, 0);
961 qemu_put_be16(f, slirp->ip_id);
963 slirp_bootp_save(f, slirp);
966 static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
968 int i;
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);
1014 static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
1016 uint32_t off, sb_cc, sb_datalen;
1018 sb_cc = qemu_get_be32(f);
1019 sb_datalen = qemu_get_be32(f);
1021 sbreserve(sbuf, sb_datalen);
1023 if (sbuf->sb_datalen != sb_datalen)
1024 return -ENOMEM;
1026 sbuf->sb_cc = sb_cc;
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);
1034 return 0;
1037 static int slirp_socket_load(QEMUFile *f, struct socket *so)
1039 if (tcp_attach(so) < 0)
1040 return -ENOMEM;
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);
1057 return 0;
1060 static void slirp_bootp_load(QEMUFile *f, Slirp *slirp)
1062 int i;
1064 for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
1065 slirp->bootp_clients[i].allocated = qemu_get_be16(f);
1066 qemu_get_buffer(f, slirp->bootp_clients[i].macaddr, 6);
1070 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
1072 Slirp *slirp = opaque;
1073 struct ex_list *ex_ptr;
1075 while (qemu_get_byte(f)) {
1076 int ret;
1077 struct socket *so = socreate(slirp);
1079 if (!so)
1080 return -ENOMEM;
1082 ret = slirp_socket_load(f, so);
1084 if (ret < 0)
1085 return ret;
1087 if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) !=
1088 slirp->vnetwork_addr.s_addr) {
1089 return -EINVAL;
1091 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
1092 if (ex_ptr->ex_pty == 3 &&
1093 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
1094 so->so_fport == ex_ptr->ex_fport) {
1095 break;
1098 if (!ex_ptr)
1099 return -EINVAL;
1101 so->extra = (void *)ex_ptr->ex_exec;
1104 if (version_id >= 2) {
1105 slirp->ip_id = qemu_get_be16(f);
1108 if (version_id >= 3) {
1109 slirp_bootp_load(f, slirp);
1112 return 0;