slirp: Factor out internal state structure
[qemu.git] / slirp / slirp.c
blob25bc8a4c57fca9da75c20f9ad8a531bcbd653a0e
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-char.h"
26 #include "slirp.h"
27 #include "hw/hw.h"
29 /* host address */
30 struct in_addr our_addr;
31 /* host dns address */
32 struct in_addr dns_addr;
33 /* host loopback address */
34 struct in_addr loopback_addr;
36 /* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
37 static const uint8_t special_ethaddr[6] = {
38 0x52, 0x55, 0x00, 0x00, 0x00, 0x00
41 static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
43 int link_up; // FIXME: kill this
45 /* XXX: suppress those select globals */
46 fd_set *global_readfds, *global_writefds, *global_xfds;
48 u_int curtime;
49 static u_int time_fasttimo, last_slowtimo;
50 static int do_slowtimo;
52 Slirp slirp_instance;
54 #ifdef _WIN32
56 static int get_dns_addr(struct in_addr *pdns_addr)
58 FIXED_INFO *FixedInfo=NULL;
59 ULONG BufLen;
60 DWORD ret;
61 IP_ADDR_STRING *pIPAddr;
62 struct in_addr tmp_addr;
64 FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
65 BufLen = sizeof(FIXED_INFO);
67 if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
68 if (FixedInfo) {
69 GlobalFree(FixedInfo);
70 FixedInfo = NULL;
72 FixedInfo = GlobalAlloc(GPTR, BufLen);
75 if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
76 printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
77 if (FixedInfo) {
78 GlobalFree(FixedInfo);
79 FixedInfo = NULL;
81 return -1;
84 pIPAddr = &(FixedInfo->DnsServerList);
85 inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
86 *pdns_addr = tmp_addr;
87 if (FixedInfo) {
88 GlobalFree(FixedInfo);
89 FixedInfo = NULL;
91 return 0;
94 static void winsock_cleanup(void)
96 WSACleanup();
99 #else
101 static int get_dns_addr(struct in_addr *pdns_addr)
103 char buff[512];
104 char buff2[257];
105 FILE *f;
106 int found = 0;
107 struct in_addr tmp_addr;
109 f = fopen("/etc/resolv.conf", "r");
110 if (!f)
111 return -1;
113 #ifdef DEBUG
114 lprint("IP address of your DNS(s): ");
115 #endif
116 while (fgets(buff, 512, f) != NULL) {
117 if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
118 if (!inet_aton(buff2, &tmp_addr))
119 continue;
120 if (tmp_addr.s_addr == loopback_addr.s_addr)
121 tmp_addr = our_addr;
122 /* If it's the first one, set it to dns_addr */
123 if (!found)
124 *pdns_addr = tmp_addr;
125 #ifdef DEBUG
126 else
127 lprint(", ");
128 #endif
129 if (++found > 3) {
130 #ifdef DEBUG
131 lprint("(more)");
132 #endif
133 break;
135 #ifdef DEBUG
136 else
137 lprint("%s", inet_ntoa(tmp_addr));
138 #endif
141 fclose(f);
142 if (!found)
143 return -1;
144 return 0;
147 #endif
149 static void slirp_init_once(void)
151 static int initialized;
152 struct hostent *he;
153 char our_name[256];
154 #ifdef _WIN32
155 WSADATA Data;
156 #endif
158 if (initialized) {
159 return;
161 initialized = 1;
163 #ifdef _WIN32
164 WSAStartup(MAKEWORD(2,0), &Data);
165 atexit(winsock_cleanup);
166 #endif
168 loopback_addr.s_addr = htonl(INADDR_LOOPBACK);
170 /* FIXME: This address may change during runtime */
171 if (gethostname(our_name, sizeof(our_name)) == 0) {
172 he = gethostbyname(our_name);
173 if (he) {
174 our_addr = *(struct in_addr *)he->h_addr;
177 if (our_addr.s_addr == 0) {
178 our_addr = loopback_addr;
181 /* FIXME: This address may change during runtime */
182 if (get_dns_addr(&dns_addr) < 0) {
183 dns_addr = loopback_addr;
187 static void slirp_state_save(QEMUFile *f, void *opaque);
188 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
190 void slirp_init(int restricted, struct in_addr vnetwork,
191 struct in_addr vnetmask, struct in_addr vhost,
192 const char *vhostname, const char *tftp_path,
193 const char *bootfile, struct in_addr vdhcp_start,
194 struct in_addr vnameserver)
196 Slirp *slirp = &slirp_instance;
198 slirp_init_once();
200 link_up = 1;
201 slirp->restricted = restricted;
203 if_init(slirp);
204 ip_init(slirp);
206 /* Initialise mbufs *after* setting the MTU */
207 m_init(slirp);
209 slirp->vnetwork_addr = vnetwork;
210 slirp->vnetwork_mask = vnetmask;
211 slirp->vhost_addr = vhost;
212 if (vhostname) {
213 pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
214 vhostname);
216 qemu_free(slirp->tftp_prefix);
217 slirp->tftp_prefix = NULL;
218 if (tftp_path) {
219 slirp->tftp_prefix = qemu_strdup(tftp_path);
221 qemu_free(slirp->bootp_filename);
222 slirp->bootp_filename = NULL;
223 if (bootfile) {
224 slirp->bootp_filename = qemu_strdup(bootfile);
226 slirp->vdhcp_startaddr = vdhcp_start;
227 slirp->vnameserver_addr = vnameserver;
229 register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, slirp);
232 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
233 #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
234 #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
237 * curtime kept to an accuracy of 1ms
239 #ifdef _WIN32
240 static void updtime(void)
242 struct _timeb tb;
244 _ftime(&tb);
246 curtime = tb.time * 1000 + tb.millitm;
248 #else
249 static void updtime(void)
251 struct timeval tv;
253 gettimeofday(&tv, NULL);
255 curtime = tv.tv_sec * 1000 + tv.tv_usec / 1000;
257 #endif
259 void slirp_select_fill(int *pnfds,
260 fd_set *readfds, fd_set *writefds, fd_set *xfds)
262 Slirp *slirp = &slirp_instance;
263 struct socket *so, *so_next;
264 int nfds;
266 if (!link_up) {
267 return;
270 /* fail safe */
271 global_readfds = NULL;
272 global_writefds = NULL;
273 global_xfds = NULL;
275 nfds = *pnfds;
277 * First, TCP sockets
279 do_slowtimo = 0;
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);
377 *pnfds = nfds;
380 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
381 int select_error)
383 Slirp *slirp = &slirp_instance;
384 struct socket *so, *so_next;
385 int ret;
387 if (!link_up) {
388 return;
391 global_readfds = readfds;
392 global_writefds = writefds;
393 global_xfds = xfds;
395 /* Update time */
396 updtime();
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);
553 /* clear global file descriptor sets.
554 * these reside on the stack in vl.c
555 * so they're unusable if we're not in
556 * slirp_select_fill or slirp_select_poll.
558 global_readfds = NULL;
559 global_writefds = NULL;
560 global_xfds = NULL;
563 #define ETH_ALEN 6
564 #define ETH_HLEN 14
566 #define ETH_P_IP 0x0800 /* Internet Protocol packet */
567 #define ETH_P_ARP 0x0806 /* Address Resolution packet */
569 #define ARPOP_REQUEST 1 /* ARP request */
570 #define ARPOP_REPLY 2 /* ARP reply */
572 struct ethhdr
574 unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
575 unsigned char h_source[ETH_ALEN]; /* source ether addr */
576 unsigned short h_proto; /* packet type ID field */
579 struct arphdr
581 unsigned short ar_hrd; /* format of hardware address */
582 unsigned short ar_pro; /* format of protocol address */
583 unsigned char ar_hln; /* length of hardware address */
584 unsigned char ar_pln; /* length of protocol address */
585 unsigned short ar_op; /* ARP opcode (command) */
588 * Ethernet looks like this : This bit is variable sized however...
590 unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
591 uint32_t ar_sip; /* sender IP address */
592 unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
593 uint32_t ar_tip ; /* target IP address */
594 } __attribute__((packed));
596 static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
598 struct ethhdr *eh = (struct ethhdr *)pkt;
599 struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
600 uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
601 struct ethhdr *reh = (struct ethhdr *)arp_reply;
602 struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
603 int ar_op;
604 struct ex_list *ex_ptr;
606 ar_op = ntohs(ah->ar_op);
607 switch(ar_op) {
608 case ARPOP_REQUEST:
609 if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
610 slirp->vnetwork_addr.s_addr) {
611 if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
612 ah->ar_tip == slirp->vhost_addr.s_addr)
613 goto arp_ok;
614 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
615 if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
616 goto arp_ok;
618 return;
619 arp_ok:
620 /* XXX: make an ARP request to have the client address */
621 memcpy(slirp->client_ethaddr, eh->h_source, ETH_ALEN);
623 /* ARP request for alias/dns mac address */
624 memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
625 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
626 memcpy(&reh->h_source[2], &ah->ar_tip, 4);
627 reh->h_proto = htons(ETH_P_ARP);
629 rah->ar_hrd = htons(1);
630 rah->ar_pro = htons(ETH_P_IP);
631 rah->ar_hln = ETH_ALEN;
632 rah->ar_pln = 4;
633 rah->ar_op = htons(ARPOP_REPLY);
634 memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
635 rah->ar_sip = ah->ar_tip;
636 memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
637 rah->ar_tip = ah->ar_sip;
638 slirp_output(arp_reply, sizeof(arp_reply));
640 break;
641 case ARPOP_REPLY:
642 /* reply to request of client mac address ? */
643 if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN) &&
644 ah->ar_sip == slirp->client_ipaddr.s_addr) {
645 memcpy(slirp->client_ethaddr, ah->ar_sha, ETH_ALEN);
647 break;
648 default:
649 break;
653 void slirp_input(const uint8_t *pkt, int pkt_len)
655 Slirp *slirp = &slirp_instance;
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(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(buf, ip_data_len + ETH_HLEN);
739 /* Drop host forwarding rule, return 0 if found. */
740 int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port)
742 Slirp *slirp = &slirp_instance;
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(int is_udp, struct in_addr host_addr, int host_port,
765 struct in_addr guest_addr, int guest_port)
767 Slirp *slirp = &slirp_instance;
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(int do_pty, const void *args, struct in_addr guest_addr,
785 int guest_port)
787 Slirp *slirp = &slirp_instance;
789 if (!guest_addr.s_addr) {
790 guest_addr.s_addr = slirp->vnetwork_addr.s_addr |
791 (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
793 if ((guest_addr.s_addr & slirp->vnetwork_mask.s_addr) !=
794 slirp->vnetwork_addr.s_addr ||
795 guest_addr.s_addr == slirp->vhost_addr.s_addr ||
796 guest_addr.s_addr == slirp->vnameserver_addr.s_addr) {
797 return -1;
799 return add_exec(&slirp->exec_list, do_pty, (char *)args, guest_addr,
800 htons(guest_port));
803 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
805 if (so->s == -1 && so->extra) {
806 qemu_chr_write(so->extra, buf, len);
807 return len;
810 return send(so->s, buf, len, flags);
813 static struct socket *
814 slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port)
816 struct socket *so;
818 for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
819 if (so->so_faddr.s_addr == guest_addr.s_addr &&
820 htons(so->so_fport) == guest_port) {
821 return so;
824 return NULL;
827 size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port)
829 Slirp *slirp = &slirp_instance;
830 struct iovec iov[2];
831 struct socket *so;
833 so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
835 if (!so || so->so_state & SS_NOFDREF)
836 return 0;
838 if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
839 return 0;
841 return sopreprbuf(so, iov, NULL);
844 void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
845 const uint8_t *buf, int size)
847 Slirp *slirp = &slirp_instance;
848 int ret;
849 struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
851 if (!so)
852 return;
854 ret = soreadbuf(so, (const char *)buf, size);
856 if (ret > 0)
857 tcp_output(sototcpcb(so));
860 static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
862 int i;
864 qemu_put_sbe16(f, tp->t_state);
865 for (i = 0; i < TCPT_NTIMERS; i++)
866 qemu_put_sbe16(f, tp->t_timer[i]);
867 qemu_put_sbe16(f, tp->t_rxtshift);
868 qemu_put_sbe16(f, tp->t_rxtcur);
869 qemu_put_sbe16(f, tp->t_dupacks);
870 qemu_put_be16(f, tp->t_maxseg);
871 qemu_put_sbyte(f, tp->t_force);
872 qemu_put_be16(f, tp->t_flags);
873 qemu_put_be32(f, tp->snd_una);
874 qemu_put_be32(f, tp->snd_nxt);
875 qemu_put_be32(f, tp->snd_up);
876 qemu_put_be32(f, tp->snd_wl1);
877 qemu_put_be32(f, tp->snd_wl2);
878 qemu_put_be32(f, tp->iss);
879 qemu_put_be32(f, tp->snd_wnd);
880 qemu_put_be32(f, tp->rcv_wnd);
881 qemu_put_be32(f, tp->rcv_nxt);
882 qemu_put_be32(f, tp->rcv_up);
883 qemu_put_be32(f, tp->irs);
884 qemu_put_be32(f, tp->rcv_adv);
885 qemu_put_be32(f, tp->snd_max);
886 qemu_put_be32(f, tp->snd_cwnd);
887 qemu_put_be32(f, tp->snd_ssthresh);
888 qemu_put_sbe16(f, tp->t_idle);
889 qemu_put_sbe16(f, tp->t_rtt);
890 qemu_put_be32(f, tp->t_rtseq);
891 qemu_put_sbe16(f, tp->t_srtt);
892 qemu_put_sbe16(f, tp->t_rttvar);
893 qemu_put_be16(f, tp->t_rttmin);
894 qemu_put_be32(f, tp->max_sndwnd);
895 qemu_put_byte(f, tp->t_oobflags);
896 qemu_put_byte(f, tp->t_iobc);
897 qemu_put_sbe16(f, tp->t_softerror);
898 qemu_put_byte(f, tp->snd_scale);
899 qemu_put_byte(f, tp->rcv_scale);
900 qemu_put_byte(f, tp->request_r_scale);
901 qemu_put_byte(f, tp->requested_s_scale);
902 qemu_put_be32(f, tp->ts_recent);
903 qemu_put_be32(f, tp->ts_recent_age);
904 qemu_put_be32(f, tp->last_ack_sent);
907 static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
909 uint32_t off;
911 qemu_put_be32(f, sbuf->sb_cc);
912 qemu_put_be32(f, sbuf->sb_datalen);
913 off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
914 qemu_put_sbe32(f, off);
915 off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
916 qemu_put_sbe32(f, off);
917 qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
920 static void slirp_socket_save(QEMUFile *f, struct socket *so)
922 qemu_put_be32(f, so->so_urgc);
923 qemu_put_be32(f, so->so_faddr.s_addr);
924 qemu_put_be32(f, so->so_laddr.s_addr);
925 qemu_put_be16(f, so->so_fport);
926 qemu_put_be16(f, so->so_lport);
927 qemu_put_byte(f, so->so_iptos);
928 qemu_put_byte(f, so->so_emu);
929 qemu_put_byte(f, so->so_type);
930 qemu_put_be32(f, so->so_state);
931 slirp_sbuf_save(f, &so->so_rcv);
932 slirp_sbuf_save(f, &so->so_snd);
933 slirp_tcp_save(f, so->so_tcpcb);
936 static void slirp_state_save(QEMUFile *f, void *opaque)
938 Slirp *slirp = opaque;
939 struct ex_list *ex_ptr;
941 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
942 if (ex_ptr->ex_pty == 3) {
943 struct socket *so;
944 so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
945 ntohs(ex_ptr->ex_fport));
946 if (!so)
947 continue;
949 qemu_put_byte(f, 42);
950 slirp_socket_save(f, so);
952 qemu_put_byte(f, 0);
954 qemu_put_be16(f, slirp->ip_id);
957 static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
959 int i;
961 tp->t_state = qemu_get_sbe16(f);
962 for (i = 0; i < TCPT_NTIMERS; i++)
963 tp->t_timer[i] = qemu_get_sbe16(f);
964 tp->t_rxtshift = qemu_get_sbe16(f);
965 tp->t_rxtcur = qemu_get_sbe16(f);
966 tp->t_dupacks = qemu_get_sbe16(f);
967 tp->t_maxseg = qemu_get_be16(f);
968 tp->t_force = qemu_get_sbyte(f);
969 tp->t_flags = qemu_get_be16(f);
970 tp->snd_una = qemu_get_be32(f);
971 tp->snd_nxt = qemu_get_be32(f);
972 tp->snd_up = qemu_get_be32(f);
973 tp->snd_wl1 = qemu_get_be32(f);
974 tp->snd_wl2 = qemu_get_be32(f);
975 tp->iss = qemu_get_be32(f);
976 tp->snd_wnd = qemu_get_be32(f);
977 tp->rcv_wnd = qemu_get_be32(f);
978 tp->rcv_nxt = qemu_get_be32(f);
979 tp->rcv_up = qemu_get_be32(f);
980 tp->irs = qemu_get_be32(f);
981 tp->rcv_adv = qemu_get_be32(f);
982 tp->snd_max = qemu_get_be32(f);
983 tp->snd_cwnd = qemu_get_be32(f);
984 tp->snd_ssthresh = qemu_get_be32(f);
985 tp->t_idle = qemu_get_sbe16(f);
986 tp->t_rtt = qemu_get_sbe16(f);
987 tp->t_rtseq = qemu_get_be32(f);
988 tp->t_srtt = qemu_get_sbe16(f);
989 tp->t_rttvar = qemu_get_sbe16(f);
990 tp->t_rttmin = qemu_get_be16(f);
991 tp->max_sndwnd = qemu_get_be32(f);
992 tp->t_oobflags = qemu_get_byte(f);
993 tp->t_iobc = qemu_get_byte(f);
994 tp->t_softerror = qemu_get_sbe16(f);
995 tp->snd_scale = qemu_get_byte(f);
996 tp->rcv_scale = qemu_get_byte(f);
997 tp->request_r_scale = qemu_get_byte(f);
998 tp->requested_s_scale = qemu_get_byte(f);
999 tp->ts_recent = qemu_get_be32(f);
1000 tp->ts_recent_age = qemu_get_be32(f);
1001 tp->last_ack_sent = qemu_get_be32(f);
1002 tcp_template(tp);
1005 static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
1007 uint32_t off, sb_cc, sb_datalen;
1009 sb_cc = qemu_get_be32(f);
1010 sb_datalen = qemu_get_be32(f);
1012 sbreserve(sbuf, sb_datalen);
1014 if (sbuf->sb_datalen != sb_datalen)
1015 return -ENOMEM;
1017 sbuf->sb_cc = sb_cc;
1019 off = qemu_get_sbe32(f);
1020 sbuf->sb_wptr = sbuf->sb_data + off;
1021 off = qemu_get_sbe32(f);
1022 sbuf->sb_rptr = sbuf->sb_data + off;
1023 qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
1025 return 0;
1028 static int slirp_socket_load(QEMUFile *f, struct socket *so)
1030 if (tcp_attach(so) < 0)
1031 return -ENOMEM;
1033 so->so_urgc = qemu_get_be32(f);
1034 so->so_faddr.s_addr = qemu_get_be32(f);
1035 so->so_laddr.s_addr = qemu_get_be32(f);
1036 so->so_fport = qemu_get_be16(f);
1037 so->so_lport = qemu_get_be16(f);
1038 so->so_iptos = qemu_get_byte(f);
1039 so->so_emu = qemu_get_byte(f);
1040 so->so_type = qemu_get_byte(f);
1041 so->so_state = qemu_get_be32(f);
1042 if (slirp_sbuf_load(f, &so->so_rcv) < 0)
1043 return -ENOMEM;
1044 if (slirp_sbuf_load(f, &so->so_snd) < 0)
1045 return -ENOMEM;
1046 slirp_tcp_load(f, so->so_tcpcb);
1048 return 0;
1051 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
1053 Slirp *slirp = opaque;
1054 struct ex_list *ex_ptr;
1055 int r;
1057 while ((r = qemu_get_byte(f))) {
1058 int ret;
1059 struct socket *so = socreate(slirp);
1061 if (!so)
1062 return -ENOMEM;
1064 ret = slirp_socket_load(f, so);
1066 if (ret < 0)
1067 return ret;
1069 if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) !=
1070 slirp->vnetwork_addr.s_addr) {
1071 return -EINVAL;
1073 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
1074 if (ex_ptr->ex_pty == 3 &&
1075 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
1076 so->so_fport == ex_ptr->ex_fport) {
1077 break;
1080 if (!ex_ptr)
1081 return -EINVAL;
1083 so->extra = (void *)ex_ptr->ex_exec;
1086 if (version_id >= 2) {
1087 slirp->ip_id = qemu_get_be16(f);
1090 return 0;