add roms/pcbios
[armpft.git] / slirp / slirp.c
blob6731f529f6942d8871acfd10013e4c40bed6ce53
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("slirp", 0, 3, slirp_state_save, slirp_state_load, slirp);
237 QTAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
239 return slirp;
242 void slirp_cleanup(Slirp *slirp)
244 QTAILQ_REMOVE(&slirp_instances, slirp, entry);
246 unregister_savevm("slirp", slirp);
248 qemu_free(slirp->tftp_prefix);
249 qemu_free(slirp->bootp_filename);
250 qemu_free(slirp);
253 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
254 #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
255 #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
257 void slirp_select_fill(int *pnfds,
258 fd_set *readfds, fd_set *writefds, fd_set *xfds)
260 Slirp *slirp;
261 struct socket *so, *so_next;
262 int nfds;
264 if (QTAILQ_EMPTY(&slirp_instances)) {
265 return;
268 /* fail safe */
269 global_readfds = NULL;
270 global_writefds = NULL;
271 global_xfds = NULL;
273 nfds = *pnfds;
275 * First, TCP sockets
277 do_slowtimo = 0;
279 QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
281 * *_slowtimo needs calling if there are IP fragments
282 * in the fragment queue, or there are TCP connections active
284 do_slowtimo |= ((slirp->tcb.so_next != &slirp->tcb) ||
285 (&slirp->ipq.ip_link != slirp->ipq.ip_link.next));
287 for (so = slirp->tcb.so_next; so != &slirp->tcb;
288 so = so_next) {
289 so_next = so->so_next;
292 * See if we need a tcp_fasttimo
294 if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
295 time_fasttimo = curtime; /* Flag when we want a fasttimo */
298 * NOFDREF can include still connecting to local-host,
299 * newly socreated() sockets etc. Don't want to select these.
301 if (so->so_state & SS_NOFDREF || so->s == -1)
302 continue;
305 * Set for reading sockets which are accepting
307 if (so->so_state & SS_FACCEPTCONN) {
308 FD_SET(so->s, readfds);
309 UPD_NFDS(so->s);
310 continue;
314 * Set for writing sockets which are connecting
316 if (so->so_state & SS_ISFCONNECTING) {
317 FD_SET(so->s, writefds);
318 UPD_NFDS(so->s);
319 continue;
323 * Set for writing if we are connected, can send more, and
324 * we have something to send
326 if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
327 FD_SET(so->s, writefds);
328 UPD_NFDS(so->s);
332 * Set for reading (and urgent data) if we are connected, can
333 * receive more, and we have room for it XXX /2 ?
335 if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
336 FD_SET(so->s, readfds);
337 FD_SET(so->s, xfds);
338 UPD_NFDS(so->s);
343 * UDP sockets
345 for (so = slirp->udb.so_next; so != &slirp->udb;
346 so = so_next) {
347 so_next = so->so_next;
350 * See if it's timed out
352 if (so->so_expire) {
353 if (so->so_expire <= curtime) {
354 udp_detach(so);
355 continue;
356 } else
357 do_slowtimo = 1; /* Let socket expire */
361 * When UDP packets are received from over the
362 * link, they're sendto()'d straight away, so
363 * no need for setting for writing
364 * Limit the number of packets queued by this session
365 * to 4. Note that even though we try and limit this
366 * to 4 packets, the session could have more queued
367 * if the packets needed to be fragmented
368 * (XXX <= 4 ?)
370 if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
371 FD_SET(so->s, readfds);
372 UPD_NFDS(so->s);
377 *pnfds = nfds;
380 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
381 int select_error)
383 Slirp *slirp;
384 struct socket *so, *so_next;
385 int ret;
387 if (QTAILQ_EMPTY(&slirp_instances)) {
388 return;
391 global_readfds = readfds;
392 global_writefds = writefds;
393 global_xfds = xfds;
395 curtime = qemu_get_clock(rt_clock);
397 QTAILQ_FOREACH(slirp, &slirp_instances, entry) {
399 * See if anything has timed out
401 if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
402 tcp_fasttimo(slirp);
403 time_fasttimo = 0;
405 if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
406 ip_slowtimo(slirp);
407 tcp_slowtimo(slirp);
408 last_slowtimo = curtime;
412 * Check sockets
414 if (!select_error) {
416 * Check TCP sockets
418 for (so = slirp->tcb.so_next; so != &slirp->tcb;
419 so = so_next) {
420 so_next = so->so_next;
423 * FD_ISSET is meaningless on these sockets
424 * (and they can crash the program)
426 if (so->so_state & SS_NOFDREF || so->s == -1)
427 continue;
430 * Check for URG data
431 * This will soread as well, so no need to
432 * test for readfds below if this succeeds
434 if (FD_ISSET(so->s, xfds))
435 sorecvoob(so);
437 * Check sockets for reading
439 else if (FD_ISSET(so->s, readfds)) {
441 * Check for incoming connections
443 if (so->so_state & SS_FACCEPTCONN) {
444 tcp_connect(so);
445 continue;
446 } /* else */
447 ret = soread(so);
449 /* Output it if we read something */
450 if (ret > 0)
451 tcp_output(sototcpcb(so));
455 * Check sockets for writing
457 if (FD_ISSET(so->s, writefds)) {
459 * Check for non-blocking, still-connecting sockets
461 if (so->so_state & SS_ISFCONNECTING) {
462 /* Connected */
463 so->so_state &= ~SS_ISFCONNECTING;
465 ret = send(so->s, (const void *) &ret, 0, 0);
466 if (ret < 0) {
467 /* XXXXX Must fix, zero bytes is a NOP */
468 if (errno == EAGAIN || errno == EWOULDBLOCK ||
469 errno == EINPROGRESS || errno == ENOTCONN)
470 continue;
472 /* else failed */
473 so->so_state &= SS_PERSISTENT_MASK;
474 so->so_state |= SS_NOFDREF;
476 /* else so->so_state &= ~SS_ISFCONNECTING; */
479 * Continue tcp_input
481 tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
482 /* continue; */
483 } else
484 ret = sowrite(so);
486 * XXXXX If we wrote something (a lot), there
487 * could be a need for a window update.
488 * In the worst case, the remote will send
489 * a window probe to get things going again
494 * Probe a still-connecting, non-blocking socket
495 * to check if it's still alive
497 #ifdef PROBE_CONN
498 if (so->so_state & SS_ISFCONNECTING) {
499 ret = recv(so->s, (char *)&ret, 0,0);
501 if (ret < 0) {
502 /* XXX */
503 if (errno == EAGAIN || errno == EWOULDBLOCK ||
504 errno == EINPROGRESS || errno == ENOTCONN)
505 continue; /* Still connecting, continue */
507 /* else failed */
508 so->so_state &= SS_PERSISTENT_MASK;
509 so->so_state |= SS_NOFDREF;
511 /* tcp_input will take care of it */
512 } else {
513 ret = send(so->s, &ret, 0,0);
514 if (ret < 0) {
515 /* XXX */
516 if (errno == EAGAIN || errno == EWOULDBLOCK ||
517 errno == EINPROGRESS || errno == ENOTCONN)
518 continue;
519 /* else failed */
520 so->so_state &= SS_PERSISTENT_MASK;
521 so->so_state |= SS_NOFDREF;
522 } else
523 so->so_state &= ~SS_ISFCONNECTING;
526 tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
527 } /* SS_ISFCONNECTING */
528 #endif
532 * Now UDP sockets.
533 * Incoming packets are sent straight away, they're not buffered.
534 * Incoming UDP data isn't buffered either.
536 for (so = slirp->udb.so_next; so != &slirp->udb;
537 so = so_next) {
538 so_next = so->so_next;
540 if (so->s != -1 && FD_ISSET(so->s, readfds)) {
541 sorecvfrom(so);
547 * See if we can start outputting
549 if (slirp->if_queued) {
550 if_start(slirp);
554 /* clear global file descriptor sets.
555 * these reside on the stack in vl.c
556 * so they're unusable if we're not in
557 * slirp_select_fill or slirp_select_poll.
559 global_readfds = NULL;
560 global_writefds = NULL;
561 global_xfds = NULL;
564 #define ETH_ALEN 6
565 #define ETH_HLEN 14
567 #define ETH_P_IP 0x0800 /* Internet Protocol packet */
568 #define ETH_P_ARP 0x0806 /* Address Resolution packet */
570 #define ARPOP_REQUEST 1 /* ARP request */
571 #define ARPOP_REPLY 2 /* ARP reply */
573 struct ethhdr
575 unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
576 unsigned char h_source[ETH_ALEN]; /* source ether addr */
577 unsigned short h_proto; /* packet type ID field */
580 struct arphdr
582 unsigned short ar_hrd; /* format of hardware address */
583 unsigned short ar_pro; /* format of protocol address */
584 unsigned char ar_hln; /* length of hardware address */
585 unsigned char ar_pln; /* length of protocol address */
586 unsigned short ar_op; /* ARP opcode (command) */
589 * Ethernet looks like this : This bit is variable sized however...
591 unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
592 uint32_t ar_sip; /* sender IP address */
593 unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
594 uint32_t ar_tip ; /* target IP address */
595 } __attribute__((packed));
597 static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
599 struct ethhdr *eh = (struct ethhdr *)pkt;
600 struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
601 uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
602 struct ethhdr *reh = (struct ethhdr *)arp_reply;
603 struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
604 int ar_op;
605 struct ex_list *ex_ptr;
607 ar_op = ntohs(ah->ar_op);
608 switch(ar_op) {
609 case ARPOP_REQUEST:
610 if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
611 slirp->vnetwork_addr.s_addr) {
612 if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
613 ah->ar_tip == slirp->vhost_addr.s_addr)
614 goto arp_ok;
615 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
616 if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
617 goto arp_ok;
619 return;
620 arp_ok:
621 /* XXX: make an ARP request to have the client address */
622 memcpy(slirp->client_ethaddr, eh->h_source, ETH_ALEN);
624 /* ARP request for alias/dns mac address */
625 memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
626 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
627 memcpy(&reh->h_source[2], &ah->ar_tip, 4);
628 reh->h_proto = htons(ETH_P_ARP);
630 rah->ar_hrd = htons(1);
631 rah->ar_pro = htons(ETH_P_IP);
632 rah->ar_hln = ETH_ALEN;
633 rah->ar_pln = 4;
634 rah->ar_op = htons(ARPOP_REPLY);
635 memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
636 rah->ar_sip = ah->ar_tip;
637 memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
638 rah->ar_tip = ah->ar_sip;
639 slirp_output(slirp->opaque, arp_reply, sizeof(arp_reply));
641 break;
642 case ARPOP_REPLY:
643 /* reply to request of client mac address ? */
644 if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN) &&
645 ah->ar_sip == slirp->client_ipaddr.s_addr) {
646 memcpy(slirp->client_ethaddr, ah->ar_sha, ETH_ALEN);
648 break;
649 default:
650 break;
654 void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
656 struct mbuf *m;
657 int proto;
659 if (pkt_len < ETH_HLEN)
660 return;
662 proto = ntohs(*(uint16_t *)(pkt + 12));
663 switch(proto) {
664 case ETH_P_ARP:
665 arp_input(slirp, pkt, pkt_len);
666 break;
667 case ETH_P_IP:
668 m = m_get(slirp);
669 if (!m)
670 return;
671 /* Note: we add to align the IP header */
672 if (M_FREEROOM(m) < pkt_len + 2) {
673 m_inc(m, pkt_len + 2);
675 m->m_len = pkt_len + 2;
676 memcpy(m->m_data + 2, pkt, pkt_len);
678 m->m_data += 2 + ETH_HLEN;
679 m->m_len -= 2 + ETH_HLEN;
681 ip_input(m);
682 break;
683 default:
684 break;
688 /* output the IP packet to the ethernet device */
689 void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len)
691 uint8_t buf[1600];
692 struct ethhdr *eh = (struct ethhdr *)buf;
694 if (ip_data_len + ETH_HLEN > sizeof(buf))
695 return;
697 if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN)) {
698 uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
699 struct ethhdr *reh = (struct ethhdr *)arp_req;
700 struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
701 const struct ip *iph = (const struct ip *)ip_data;
703 /* If the client addr is not known, there is no point in
704 sending the packet to it. Normally the sender should have
705 done an ARP request to get its MAC address. Here we do it
706 in place of sending the packet and we hope that the sender
707 will retry sending its packet. */
708 memset(reh->h_dest, 0xff, ETH_ALEN);
709 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
710 memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
711 reh->h_proto = htons(ETH_P_ARP);
712 rah->ar_hrd = htons(1);
713 rah->ar_pro = htons(ETH_P_IP);
714 rah->ar_hln = ETH_ALEN;
715 rah->ar_pln = 4;
716 rah->ar_op = htons(ARPOP_REQUEST);
717 /* source hw addr */
718 memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
719 memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
720 /* source IP */
721 rah->ar_sip = slirp->vhost_addr.s_addr;
722 /* target hw addr (none) */
723 memset(rah->ar_tha, 0, ETH_ALEN);
724 /* target IP */
725 rah->ar_tip = iph->ip_dst.s_addr;
726 slirp->client_ipaddr = iph->ip_dst;
727 slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
728 } else {
729 memcpy(eh->h_dest, slirp->client_ethaddr, ETH_ALEN);
730 memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
731 /* XXX: not correct */
732 memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
733 eh->h_proto = htons(ETH_P_IP);
734 memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
735 slirp_output(slirp->opaque, buf, ip_data_len + ETH_HLEN);
739 /* Drop host forwarding rule, return 0 if found. */
740 int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
741 int host_port)
743 struct socket *so;
744 struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);
745 struct sockaddr_in addr;
746 int port = htons(host_port);
747 socklen_t addr_len;
749 for (so = head->so_next; so != head; so = so->so_next) {
750 addr_len = sizeof(addr);
751 if ((so->so_state & SS_HOSTFWD) &&
752 getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
753 addr.sin_addr.s_addr == host_addr.s_addr &&
754 addr.sin_port == port) {
755 close(so->s);
756 sofree(so);
757 return 0;
761 return -1;
764 int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
765 int host_port, struct in_addr guest_addr, int guest_port)
767 if (!guest_addr.s_addr) {
768 guest_addr = slirp->vdhcp_startaddr;
770 if (is_udp) {
771 if (!udp_listen(slirp, host_addr.s_addr, htons(host_port),
772 guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
773 return -1;
774 } else {
775 if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port),
776 guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
777 return -1;
779 return 0;
782 int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
783 struct in_addr *guest_addr, int guest_port)
785 if (!guest_addr->s_addr) {
786 guest_addr->s_addr = slirp->vnetwork_addr.s_addr |
787 (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
789 if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) !=
790 slirp->vnetwork_addr.s_addr ||
791 guest_addr->s_addr == slirp->vhost_addr.s_addr ||
792 guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
793 return -1;
795 return add_exec(&slirp->exec_list, do_pty, (char *)args, *guest_addr,
796 htons(guest_port));
799 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
801 if (so->s == -1 && so->extra) {
802 qemu_chr_write(so->extra, buf, len);
803 return len;
806 return send(so->s, buf, len, flags);
809 static struct socket *
810 slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port)
812 struct socket *so;
814 for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
815 if (so->so_faddr.s_addr == guest_addr.s_addr &&
816 htons(so->so_fport) == guest_port) {
817 return so;
820 return NULL;
823 size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
824 int guest_port)
826 struct iovec iov[2];
827 struct socket *so;
829 so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
831 if (!so || so->so_state & SS_NOFDREF)
832 return 0;
834 if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
835 return 0;
837 return sopreprbuf(so, iov, NULL);
840 void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
841 const uint8_t *buf, int size)
843 int ret;
844 struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
846 if (!so)
847 return;
849 ret = soreadbuf(so, (const char *)buf, size);
851 if (ret > 0)
852 tcp_output(sototcpcb(so));
855 static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
857 int i;
859 qemu_put_sbe16(f, tp->t_state);
860 for (i = 0; i < TCPT_NTIMERS; i++)
861 qemu_put_sbe16(f, tp->t_timer[i]);
862 qemu_put_sbe16(f, tp->t_rxtshift);
863 qemu_put_sbe16(f, tp->t_rxtcur);
864 qemu_put_sbe16(f, tp->t_dupacks);
865 qemu_put_be16(f, tp->t_maxseg);
866 qemu_put_sbyte(f, tp->t_force);
867 qemu_put_be16(f, tp->t_flags);
868 qemu_put_be32(f, tp->snd_una);
869 qemu_put_be32(f, tp->snd_nxt);
870 qemu_put_be32(f, tp->snd_up);
871 qemu_put_be32(f, tp->snd_wl1);
872 qemu_put_be32(f, tp->snd_wl2);
873 qemu_put_be32(f, tp->iss);
874 qemu_put_be32(f, tp->snd_wnd);
875 qemu_put_be32(f, tp->rcv_wnd);
876 qemu_put_be32(f, tp->rcv_nxt);
877 qemu_put_be32(f, tp->rcv_up);
878 qemu_put_be32(f, tp->irs);
879 qemu_put_be32(f, tp->rcv_adv);
880 qemu_put_be32(f, tp->snd_max);
881 qemu_put_be32(f, tp->snd_cwnd);
882 qemu_put_be32(f, tp->snd_ssthresh);
883 qemu_put_sbe16(f, tp->t_idle);
884 qemu_put_sbe16(f, tp->t_rtt);
885 qemu_put_be32(f, tp->t_rtseq);
886 qemu_put_sbe16(f, tp->t_srtt);
887 qemu_put_sbe16(f, tp->t_rttvar);
888 qemu_put_be16(f, tp->t_rttmin);
889 qemu_put_be32(f, tp->max_sndwnd);
890 qemu_put_byte(f, tp->t_oobflags);
891 qemu_put_byte(f, tp->t_iobc);
892 qemu_put_sbe16(f, tp->t_softerror);
893 qemu_put_byte(f, tp->snd_scale);
894 qemu_put_byte(f, tp->rcv_scale);
895 qemu_put_byte(f, tp->request_r_scale);
896 qemu_put_byte(f, tp->requested_s_scale);
897 qemu_put_be32(f, tp->ts_recent);
898 qemu_put_be32(f, tp->ts_recent_age);
899 qemu_put_be32(f, tp->last_ack_sent);
902 static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
904 uint32_t off;
906 qemu_put_be32(f, sbuf->sb_cc);
907 qemu_put_be32(f, sbuf->sb_datalen);
908 off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
909 qemu_put_sbe32(f, off);
910 off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
911 qemu_put_sbe32(f, off);
912 qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
915 static void slirp_socket_save(QEMUFile *f, struct socket *so)
917 qemu_put_be32(f, so->so_urgc);
918 qemu_put_be32(f, so->so_faddr.s_addr);
919 qemu_put_be32(f, so->so_laddr.s_addr);
920 qemu_put_be16(f, so->so_fport);
921 qemu_put_be16(f, so->so_lport);
922 qemu_put_byte(f, so->so_iptos);
923 qemu_put_byte(f, so->so_emu);
924 qemu_put_byte(f, so->so_type);
925 qemu_put_be32(f, so->so_state);
926 slirp_sbuf_save(f, &so->so_rcv);
927 slirp_sbuf_save(f, &so->so_snd);
928 slirp_tcp_save(f, so->so_tcpcb);
931 static void slirp_bootp_save(QEMUFile *f, Slirp *slirp)
933 int i;
935 for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
936 qemu_put_be16(f, slirp->bootp_clients[i].allocated);
937 qemu_put_buffer(f, slirp->bootp_clients[i].macaddr, 6);
941 static void slirp_state_save(QEMUFile *f, void *opaque)
943 Slirp *slirp = opaque;
944 struct ex_list *ex_ptr;
946 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
947 if (ex_ptr->ex_pty == 3) {
948 struct socket *so;
949 so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
950 ntohs(ex_ptr->ex_fport));
951 if (!so)
952 continue;
954 qemu_put_byte(f, 42);
955 slirp_socket_save(f, so);
957 qemu_put_byte(f, 0);
959 qemu_put_be16(f, slirp->ip_id);
961 slirp_bootp_save(f, slirp);
964 static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
966 int i;
968 tp->t_state = qemu_get_sbe16(f);
969 for (i = 0; i < TCPT_NTIMERS; i++)
970 tp->t_timer[i] = qemu_get_sbe16(f);
971 tp->t_rxtshift = qemu_get_sbe16(f);
972 tp->t_rxtcur = qemu_get_sbe16(f);
973 tp->t_dupacks = qemu_get_sbe16(f);
974 tp->t_maxseg = qemu_get_be16(f);
975 tp->t_force = qemu_get_sbyte(f);
976 tp->t_flags = qemu_get_be16(f);
977 tp->snd_una = qemu_get_be32(f);
978 tp->snd_nxt = qemu_get_be32(f);
979 tp->snd_up = qemu_get_be32(f);
980 tp->snd_wl1 = qemu_get_be32(f);
981 tp->snd_wl2 = qemu_get_be32(f);
982 tp->iss = qemu_get_be32(f);
983 tp->snd_wnd = qemu_get_be32(f);
984 tp->rcv_wnd = qemu_get_be32(f);
985 tp->rcv_nxt = qemu_get_be32(f);
986 tp->rcv_up = qemu_get_be32(f);
987 tp->irs = qemu_get_be32(f);
988 tp->rcv_adv = qemu_get_be32(f);
989 tp->snd_max = qemu_get_be32(f);
990 tp->snd_cwnd = qemu_get_be32(f);
991 tp->snd_ssthresh = qemu_get_be32(f);
992 tp->t_idle = qemu_get_sbe16(f);
993 tp->t_rtt = qemu_get_sbe16(f);
994 tp->t_rtseq = qemu_get_be32(f);
995 tp->t_srtt = qemu_get_sbe16(f);
996 tp->t_rttvar = qemu_get_sbe16(f);
997 tp->t_rttmin = qemu_get_be16(f);
998 tp->max_sndwnd = qemu_get_be32(f);
999 tp->t_oobflags = qemu_get_byte(f);
1000 tp->t_iobc = qemu_get_byte(f);
1001 tp->t_softerror = qemu_get_sbe16(f);
1002 tp->snd_scale = qemu_get_byte(f);
1003 tp->rcv_scale = qemu_get_byte(f);
1004 tp->request_r_scale = qemu_get_byte(f);
1005 tp->requested_s_scale = qemu_get_byte(f);
1006 tp->ts_recent = qemu_get_be32(f);
1007 tp->ts_recent_age = qemu_get_be32(f);
1008 tp->last_ack_sent = qemu_get_be32(f);
1009 tcp_template(tp);
1012 static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
1014 uint32_t off, sb_cc, sb_datalen;
1016 sb_cc = qemu_get_be32(f);
1017 sb_datalen = qemu_get_be32(f);
1019 sbreserve(sbuf, sb_datalen);
1021 if (sbuf->sb_datalen != sb_datalen)
1022 return -ENOMEM;
1024 sbuf->sb_cc = sb_cc;
1026 off = qemu_get_sbe32(f);
1027 sbuf->sb_wptr = sbuf->sb_data + off;
1028 off = qemu_get_sbe32(f);
1029 sbuf->sb_rptr = sbuf->sb_data + off;
1030 qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
1032 return 0;
1035 static int slirp_socket_load(QEMUFile *f, struct socket *so)
1037 if (tcp_attach(so) < 0)
1038 return -ENOMEM;
1040 so->so_urgc = qemu_get_be32(f);
1041 so->so_faddr.s_addr = qemu_get_be32(f);
1042 so->so_laddr.s_addr = qemu_get_be32(f);
1043 so->so_fport = qemu_get_be16(f);
1044 so->so_lport = qemu_get_be16(f);
1045 so->so_iptos = qemu_get_byte(f);
1046 so->so_emu = qemu_get_byte(f);
1047 so->so_type = qemu_get_byte(f);
1048 so->so_state = qemu_get_be32(f);
1049 if (slirp_sbuf_load(f, &so->so_rcv) < 0)
1050 return -ENOMEM;
1051 if (slirp_sbuf_load(f, &so->so_snd) < 0)
1052 return -ENOMEM;
1053 slirp_tcp_load(f, so->so_tcpcb);
1055 return 0;
1058 static void slirp_bootp_load(QEMUFile *f, Slirp *slirp)
1060 int i;
1062 for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
1063 slirp->bootp_clients[i].allocated = qemu_get_be16(f);
1064 qemu_get_buffer(f, slirp->bootp_clients[i].macaddr, 6);
1068 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
1070 Slirp *slirp = opaque;
1071 struct ex_list *ex_ptr;
1072 int r;
1074 while ((r = qemu_get_byte(f))) {
1075 int ret;
1076 struct socket *so = socreate(slirp);
1078 if (!so)
1079 return -ENOMEM;
1081 ret = slirp_socket_load(f, so);
1083 if (ret < 0)
1084 return ret;
1086 if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) !=
1087 slirp->vnetwork_addr.s_addr) {
1088 return -EINVAL;
1090 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
1091 if (ex_ptr->ex_pty == 3 &&
1092 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
1093 so->so_fport == ex_ptr->ex_fport) {
1094 break;
1097 if (!ex_ptr)
1098 return -EINVAL;
1100 so->extra = (void *)ex_ptr->ex_exec;
1103 if (version_id >= 2) {
1104 slirp->ip_id = qemu_get_be16(f);
1107 if (version_id >= 3) {
1108 slirp_bootp_load(f, slirp);
1111 return 0;