slirp: Make IP packet ID consistent
[qemu-kvm/fedora.git] / slirp / slirp.c
blob02f6fe50fc504bcacb543aced09fd9c5e6a99752
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 /* virtual network configuration */
37 struct in_addr vnetwork_addr;
38 struct in_addr vnetwork_mask;
39 struct in_addr vhost_addr;
40 struct in_addr vdhcp_startaddr;
41 struct in_addr vnameserver_addr;
43 /* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
44 static const uint8_t special_ethaddr[6] = {
45 0x52, 0x55, 0x00, 0x00, 0x00, 0x00
48 /* ARP cache for the guest IP addresses (XXX: allow many entries) */
49 uint8_t client_ethaddr[6];
50 static struct in_addr client_ipaddr;
52 static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
54 int slirp_restrict;
55 static int do_slowtimo;
56 int link_up;
57 struct timeval tt;
58 struct ex_list *exec_list;
60 /* XXX: suppress those select globals */
61 fd_set *global_readfds, *global_writefds, *global_xfds;
63 char slirp_hostname[33];
65 #ifdef _WIN32
67 static int get_dns_addr(struct in_addr *pdns_addr)
69 FIXED_INFO *FixedInfo=NULL;
70 ULONG BufLen;
71 DWORD ret;
72 IP_ADDR_STRING *pIPAddr;
73 struct in_addr tmp_addr;
75 FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
76 BufLen = sizeof(FIXED_INFO);
78 if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
79 if (FixedInfo) {
80 GlobalFree(FixedInfo);
81 FixedInfo = NULL;
83 FixedInfo = GlobalAlloc(GPTR, BufLen);
86 if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
87 printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
88 if (FixedInfo) {
89 GlobalFree(FixedInfo);
90 FixedInfo = NULL;
92 return -1;
95 pIPAddr = &(FixedInfo->DnsServerList);
96 inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
97 *pdns_addr = tmp_addr;
98 if (FixedInfo) {
99 GlobalFree(FixedInfo);
100 FixedInfo = NULL;
102 return 0;
105 static void winsock_cleanup(void)
107 WSACleanup();
110 #else
112 static int get_dns_addr(struct in_addr *pdns_addr)
114 char buff[512];
115 char buff2[257];
116 FILE *f;
117 int found = 0;
118 struct in_addr tmp_addr;
120 f = fopen("/etc/resolv.conf", "r");
121 if (!f)
122 return -1;
124 #ifdef DEBUG
125 lprint("IP address of your DNS(s): ");
126 #endif
127 while (fgets(buff, 512, f) != NULL) {
128 if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
129 if (!inet_aton(buff2, &tmp_addr))
130 continue;
131 if (tmp_addr.s_addr == loopback_addr.s_addr)
132 tmp_addr = our_addr;
133 /* If it's the first one, set it to dns_addr */
134 if (!found)
135 *pdns_addr = tmp_addr;
136 #ifdef DEBUG
137 else
138 lprint(", ");
139 #endif
140 if (++found > 3) {
141 #ifdef DEBUG
142 lprint("(more)");
143 #endif
144 break;
146 #ifdef DEBUG
147 else
148 lprint("%s", inet_ntoa(tmp_addr));
149 #endif
152 fclose(f);
153 if (!found)
154 return -1;
155 return 0;
158 #endif
160 static void slirp_init_once(void)
162 static int initialized;
163 struct hostent *he;
164 char our_name[256];
165 #ifdef _WIN32
166 WSADATA Data;
167 #endif
169 if (initialized) {
170 return;
172 initialized = 1;
174 #ifdef _WIN32
175 WSAStartup(MAKEWORD(2,0), &Data);
176 atexit(winsock_cleanup);
177 #endif
179 loopback_addr.s_addr = htonl(INADDR_LOOPBACK);
181 /* FIXME: This address may change during runtime */
182 if (gethostname(our_name, sizeof(our_name)) == 0) {
183 he = gethostbyname(our_name);
184 if (he) {
185 our_addr = *(struct in_addr *)he->h_addr;
188 if (our_addr.s_addr == 0) {
189 our_addr = loopback_addr;
192 /* FIXME: This address may change during runtime */
193 if (get_dns_addr(&dns_addr) < 0) {
194 dns_addr = loopback_addr;
198 static void slirp_state_save(QEMUFile *f, void *opaque);
199 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
201 void slirp_init(int restricted, struct in_addr vnetwork,
202 struct in_addr vnetmask, struct in_addr vhost,
203 const char *vhostname, const char *tftp_path,
204 const char *bootfile, struct in_addr vdhcp_start,
205 struct in_addr vnameserver)
207 slirp_init_once();
209 link_up = 1;
210 slirp_restrict = restricted;
212 if_init();
213 ip_init();
215 /* Initialise mbufs *after* setting the MTU */
216 m_init();
218 vnetwork_addr = vnetwork;
219 vnetwork_mask = vnetmask;
220 vhost_addr = vhost;
221 if (vhostname) {
222 pstrcpy(slirp_hostname, sizeof(slirp_hostname), vhostname);
224 qemu_free(tftp_prefix);
225 tftp_prefix = NULL;
226 if (tftp_path) {
227 tftp_prefix = qemu_strdup(tftp_path);
229 qemu_free(bootp_filename);
230 bootp_filename = NULL;
231 if (bootfile) {
232 bootp_filename = qemu_strdup(bootfile);
234 vdhcp_startaddr = vdhcp_start;
235 vnameserver_addr = vnameserver;
237 register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, NULL);
240 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
241 #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
242 #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
245 * curtime kept to an accuracy of 1ms
247 #ifdef _WIN32
248 static void updtime(void)
250 struct _timeb tb;
252 _ftime(&tb);
253 curtime = (u_int)tb.time * (u_int)1000;
254 curtime += (u_int)tb.millitm;
256 #else
257 static void updtime(void)
259 gettimeofday(&tt, NULL);
261 curtime = (u_int)tt.tv_sec * (u_int)1000;
262 curtime += (u_int)tt.tv_usec / (u_int)1000;
264 if ((tt.tv_usec % 1000) >= 500)
265 curtime++;
267 #endif
269 void slirp_select_fill(int *pnfds,
270 fd_set *readfds, fd_set *writefds, fd_set *xfds)
272 struct socket *so, *so_next;
273 struct timeval timeout;
274 int nfds;
275 int tmp_time;
277 /* fail safe */
278 global_readfds = NULL;
279 global_writefds = NULL;
280 global_xfds = NULL;
282 nfds = *pnfds;
284 * First, TCP sockets
286 do_slowtimo = 0;
287 if (link_up) {
289 * *_slowtimo needs calling if there are IP fragments
290 * in the fragment queue, or there are TCP connections active
292 do_slowtimo = ((tcb.so_next != &tcb) ||
293 (&ipq.ip_link != ipq.ip_link.next));
295 for (so = tcb.so_next; so != &tcb; so = so_next) {
296 so_next = so->so_next;
299 * See if we need a tcp_fasttimo
301 if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
302 time_fasttimo = curtime; /* Flag when we want a fasttimo */
305 * NOFDREF can include still connecting to local-host,
306 * newly socreated() sockets etc. Don't want to select these.
308 if (so->so_state & SS_NOFDREF || so->s == -1)
309 continue;
312 * Set for reading sockets which are accepting
314 if (so->so_state & SS_FACCEPTCONN) {
315 FD_SET(so->s, readfds);
316 UPD_NFDS(so->s);
317 continue;
321 * Set for writing sockets which are connecting
323 if (so->so_state & SS_ISFCONNECTING) {
324 FD_SET(so->s, writefds);
325 UPD_NFDS(so->s);
326 continue;
330 * Set for writing if we are connected, can send more, and
331 * we have something to send
333 if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
334 FD_SET(so->s, writefds);
335 UPD_NFDS(so->s);
339 * Set for reading (and urgent data) if we are connected, can
340 * receive more, and we have room for it XXX /2 ?
342 if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
343 FD_SET(so->s, readfds);
344 FD_SET(so->s, xfds);
345 UPD_NFDS(so->s);
350 * UDP sockets
352 for (so = udb.so_next; so != &udb; so = so_next) {
353 so_next = so->so_next;
356 * See if it's timed out
358 if (so->so_expire) {
359 if (so->so_expire <= curtime) {
360 udp_detach(so);
361 continue;
362 } else
363 do_slowtimo = 1; /* Let socket expire */
367 * When UDP packets are received from over the
368 * link, they're sendto()'d straight away, so
369 * no need for setting for writing
370 * Limit the number of packets queued by this session
371 * to 4. Note that even though we try and limit this
372 * to 4 packets, the session could have more queued
373 * if the packets needed to be fragmented
374 * (XXX <= 4 ?)
376 if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
377 FD_SET(so->s, readfds);
378 UPD_NFDS(so->s);
384 * Setup timeout to use minimum CPU usage, especially when idle
388 * First, see the timeout needed by *timo
390 timeout.tv_sec = 0;
391 timeout.tv_usec = -1;
393 * If a slowtimo is needed, set timeout to 500ms from the last
394 * slow timeout. If a fast timeout is needed, set timeout within
395 * 200ms of when it was requested.
397 if (do_slowtimo) {
398 /* XXX + 10000 because some select()'s aren't that accurate */
399 timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
400 if (timeout.tv_usec < 0)
401 timeout.tv_usec = 0;
402 else if (timeout.tv_usec > 510000)
403 timeout.tv_usec = 510000;
405 /* Can only fasttimo if we also slowtimo */
406 if (time_fasttimo) {
407 tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
408 if (tmp_time < 0)
409 tmp_time = 0;
411 /* Choose the smallest of the 2 */
412 if (tmp_time < timeout.tv_usec)
413 timeout.tv_usec = (u_int)tmp_time;
416 *pnfds = nfds;
419 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
421 struct socket *so, *so_next;
422 int ret;
424 global_readfds = readfds;
425 global_writefds = writefds;
426 global_xfds = xfds;
428 /* Update time */
429 updtime();
432 * See if anything has timed out
434 if (link_up) {
435 if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
436 tcp_fasttimo();
437 time_fasttimo = 0;
439 if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
440 ip_slowtimo();
441 tcp_slowtimo();
442 last_slowtimo = curtime;
447 * Check sockets
449 if (link_up) {
451 * Check TCP sockets
453 for (so = tcb.so_next; so != &tcb; so = so_next) {
454 so_next = so->so_next;
457 * FD_ISSET is meaningless on these sockets
458 * (and they can crash the program)
460 if (so->so_state & SS_NOFDREF || so->s == -1)
461 continue;
464 * Check for URG data
465 * This will soread as well, so no need to
466 * test for readfds below if this succeeds
468 if (FD_ISSET(so->s, xfds))
469 sorecvoob(so);
471 * Check sockets for reading
473 else if (FD_ISSET(so->s, readfds)) {
475 * Check for incoming connections
477 if (so->so_state & SS_FACCEPTCONN) {
478 tcp_connect(so);
479 continue;
480 } /* else */
481 ret = soread(so);
483 /* Output it if we read something */
484 if (ret > 0)
485 tcp_output(sototcpcb(so));
489 * Check sockets for writing
491 if (FD_ISSET(so->s, writefds)) {
493 * Check for non-blocking, still-connecting sockets
495 if (so->so_state & SS_ISFCONNECTING) {
496 /* Connected */
497 so->so_state &= ~SS_ISFCONNECTING;
499 ret = send(so->s, (const void *) &ret, 0, 0);
500 if (ret < 0) {
501 /* XXXXX Must fix, zero bytes is a NOP */
502 if (errno == EAGAIN || errno == EWOULDBLOCK ||
503 errno == EINPROGRESS || errno == ENOTCONN)
504 continue;
506 /* else failed */
507 so->so_state &= SS_PERSISTENT_MASK;
508 so->so_state |= SS_NOFDREF;
510 /* else so->so_state &= ~SS_ISFCONNECTING; */
513 * Continue tcp_input
515 tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
516 /* continue; */
517 } else
518 ret = sowrite(so);
520 * XXXXX If we wrote something (a lot), there
521 * could be a need for a window update.
522 * In the worst case, the remote will send
523 * a window probe to get things going again
528 * Probe a still-connecting, non-blocking socket
529 * to check if it's still alive
531 #ifdef PROBE_CONN
532 if (so->so_state & SS_ISFCONNECTING) {
533 ret = recv(so->s, (char *)&ret, 0,0);
535 if (ret < 0) {
536 /* XXX */
537 if (errno == EAGAIN || errno == EWOULDBLOCK ||
538 errno == EINPROGRESS || errno == ENOTCONN)
539 continue; /* Still connecting, continue */
541 /* else failed */
542 so->so_state &= SS_PERSISTENT_MASK;
543 so->so_state |= SS_NOFDREF;
545 /* tcp_input will take care of it */
546 } else {
547 ret = send(so->s, &ret, 0,0);
548 if (ret < 0) {
549 /* XXX */
550 if (errno == EAGAIN || errno == EWOULDBLOCK ||
551 errno == EINPROGRESS || errno == ENOTCONN)
552 continue;
553 /* else failed */
554 so->so_state &= SS_PERSISTENT_MASK;
555 so->so_state |= SS_NOFDREF;
556 } else
557 so->so_state &= ~SS_ISFCONNECTING;
560 tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
561 } /* SS_ISFCONNECTING */
562 #endif
566 * Now UDP sockets.
567 * Incoming packets are sent straight away, they're not buffered.
568 * Incoming UDP data isn't buffered either.
570 for (so = udb.so_next; so != &udb; so = so_next) {
571 so_next = so->so_next;
573 if (so->s != -1 && FD_ISSET(so->s, readfds)) {
574 sorecvfrom(so);
580 * See if we can start outputting
582 if (if_queued && link_up)
583 if_start();
585 /* clear global file descriptor sets.
586 * these reside on the stack in vl.c
587 * so they're unusable if we're not in
588 * slirp_select_fill or slirp_select_poll.
590 global_readfds = NULL;
591 global_writefds = NULL;
592 global_xfds = NULL;
595 #define ETH_ALEN 6
596 #define ETH_HLEN 14
598 #define ETH_P_IP 0x0800 /* Internet Protocol packet */
599 #define ETH_P_ARP 0x0806 /* Address Resolution packet */
601 #define ARPOP_REQUEST 1 /* ARP request */
602 #define ARPOP_REPLY 2 /* ARP reply */
604 struct ethhdr
606 unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
607 unsigned char h_source[ETH_ALEN]; /* source ether addr */
608 unsigned short h_proto; /* packet type ID field */
611 struct arphdr
613 unsigned short ar_hrd; /* format of hardware address */
614 unsigned short ar_pro; /* format of protocol address */
615 unsigned char ar_hln; /* length of hardware address */
616 unsigned char ar_pln; /* length of protocol address */
617 unsigned short ar_op; /* ARP opcode (command) */
620 * Ethernet looks like this : This bit is variable sized however...
622 unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
623 uint32_t ar_sip; /* sender IP address */
624 unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
625 uint32_t ar_tip ; /* target IP address */
626 } __attribute__((packed));
628 static void arp_input(const uint8_t *pkt, int pkt_len)
630 struct ethhdr *eh = (struct ethhdr *)pkt;
631 struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
632 uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
633 struct ethhdr *reh = (struct ethhdr *)arp_reply;
634 struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
635 int ar_op;
636 struct ex_list *ex_ptr;
638 ar_op = ntohs(ah->ar_op);
639 switch(ar_op) {
640 case ARPOP_REQUEST:
641 if ((ah->ar_tip & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) {
642 if (ah->ar_tip == vnameserver_addr.s_addr ||
643 ah->ar_tip == vhost_addr.s_addr)
644 goto arp_ok;
645 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
646 if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
647 goto arp_ok;
649 return;
650 arp_ok:
651 /* XXX: make an ARP request to have the client address */
652 memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
654 /* ARP request for alias/dns mac address */
655 memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
656 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
657 memcpy(&reh->h_source[2], &ah->ar_tip, 4);
658 reh->h_proto = htons(ETH_P_ARP);
660 rah->ar_hrd = htons(1);
661 rah->ar_pro = htons(ETH_P_IP);
662 rah->ar_hln = ETH_ALEN;
663 rah->ar_pln = 4;
664 rah->ar_op = htons(ARPOP_REPLY);
665 memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
666 rah->ar_sip = ah->ar_tip;
667 memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
668 rah->ar_tip = ah->ar_sip;
669 slirp_output(arp_reply, sizeof(arp_reply));
671 break;
672 case ARPOP_REPLY:
673 /* reply to request of client mac address ? */
674 if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) &&
675 ah->ar_sip == client_ipaddr.s_addr) {
676 memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN);
678 break;
679 default:
680 break;
684 void slirp_input(const uint8_t *pkt, int pkt_len)
686 struct mbuf *m;
687 int proto;
689 if (pkt_len < ETH_HLEN)
690 return;
692 proto = ntohs(*(uint16_t *)(pkt + 12));
693 switch(proto) {
694 case ETH_P_ARP:
695 arp_input(pkt, pkt_len);
696 break;
697 case ETH_P_IP:
698 m = m_get();
699 if (!m)
700 return;
701 /* Note: we add to align the IP header */
702 if (M_FREEROOM(m) < pkt_len + 2) {
703 m_inc(m, pkt_len + 2);
705 m->m_len = pkt_len + 2;
706 memcpy(m->m_data + 2, pkt, pkt_len);
708 m->m_data += 2 + ETH_HLEN;
709 m->m_len -= 2 + ETH_HLEN;
711 ip_input(m);
712 break;
713 default:
714 break;
718 /* output the IP packet to the ethernet device */
719 void if_encap(const uint8_t *ip_data, int ip_data_len)
721 uint8_t buf[1600];
722 struct ethhdr *eh = (struct ethhdr *)buf;
724 if (ip_data_len + ETH_HLEN > sizeof(buf))
725 return;
727 if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN)) {
728 uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
729 struct ethhdr *reh = (struct ethhdr *)arp_req;
730 struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
731 const struct ip *iph = (const struct ip *)ip_data;
733 /* If the client addr is not known, there is no point in
734 sending the packet to it. Normally the sender should have
735 done an ARP request to get its MAC address. Here we do it
736 in place of sending the packet and we hope that the sender
737 will retry sending its packet. */
738 memset(reh->h_dest, 0xff, ETH_ALEN);
739 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
740 memcpy(&reh->h_source[2], &vhost_addr, 4);
741 reh->h_proto = htons(ETH_P_ARP);
742 rah->ar_hrd = htons(1);
743 rah->ar_pro = htons(ETH_P_IP);
744 rah->ar_hln = ETH_ALEN;
745 rah->ar_pln = 4;
746 rah->ar_op = htons(ARPOP_REQUEST);
747 /* source hw addr */
748 memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
749 memcpy(&rah->ar_sha[2], &vhost_addr, 4);
750 /* source IP */
751 rah->ar_sip = vhost_addr.s_addr;
752 /* target hw addr (none) */
753 memset(rah->ar_tha, 0, ETH_ALEN);
754 /* target IP */
755 rah->ar_tip = iph->ip_dst.s_addr;
756 client_ipaddr = iph->ip_dst;
757 slirp_output(arp_req, sizeof(arp_req));
758 } else {
759 memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
760 memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
761 /* XXX: not correct */
762 memcpy(&eh->h_source[2], &vhost_addr, 4);
763 eh->h_proto = htons(ETH_P_IP);
764 memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
765 slirp_output(buf, ip_data_len + ETH_HLEN);
769 /* Drop host forwarding rule, return 0 if found. */
770 int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port)
772 struct socket *so;
773 struct socket *head = (is_udp ? &udb : &tcb);
774 struct sockaddr_in addr;
775 int port = htons(host_port);
776 socklen_t addr_len;
778 for (so = head->so_next; so != head; so = so->so_next) {
779 addr_len = sizeof(addr);
780 if ((so->so_state & SS_HOSTFWD) &&
781 getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
782 addr.sin_addr.s_addr == host_addr.s_addr &&
783 addr.sin_port == port) {
784 close(so->s);
785 sofree(so);
786 return 0;
790 return -1;
793 int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,
794 struct in_addr guest_addr, int guest_port)
796 if (!guest_addr.s_addr) {
797 guest_addr = vdhcp_startaddr;
799 if (is_udp) {
800 if (!udp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
801 htons(guest_port), SS_HOSTFWD))
802 return -1;
803 } else {
804 if (!tcp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
805 htons(guest_port), SS_HOSTFWD))
806 return -1;
808 return 0;
811 int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
812 int guest_port)
814 if (!guest_addr.s_addr) {
815 guest_addr.s_addr =
816 vnetwork_addr.s_addr | (htonl(0x0204) & ~vnetwork_mask.s_addr);
818 if ((guest_addr.s_addr & vnetwork_mask.s_addr) != vnetwork_addr.s_addr ||
819 guest_addr.s_addr == vhost_addr.s_addr ||
820 guest_addr.s_addr == vnameserver_addr.s_addr) {
821 return -1;
823 return add_exec(&exec_list, do_pty, (char *)args, guest_addr,
824 htons(guest_port));
827 ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
829 if (so->s == -1 && so->extra) {
830 qemu_chr_write(so->extra, buf, len);
831 return len;
834 return send(so->s, buf, len, flags);
837 static struct socket *
838 slirp_find_ctl_socket(struct in_addr guest_addr, int guest_port)
840 struct socket *so;
842 for (so = tcb.so_next; so != &tcb; so = so->so_next) {
843 if (so->so_faddr.s_addr == guest_addr.s_addr &&
844 htons(so->so_fport) == guest_port) {
845 return so;
848 return NULL;
851 size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port)
853 struct iovec iov[2];
854 struct socket *so;
856 if (!link_up)
857 return 0;
859 so = slirp_find_ctl_socket(guest_addr, guest_port);
861 if (!so || so->so_state & SS_NOFDREF)
862 return 0;
864 if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
865 return 0;
867 return sopreprbuf(so, iov, NULL);
870 void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
871 const uint8_t *buf, int size)
873 int ret;
874 struct socket *so = slirp_find_ctl_socket(guest_addr, guest_port);
876 if (!so)
877 return;
879 ret = soreadbuf(so, (const char *)buf, size);
881 if (ret > 0)
882 tcp_output(sototcpcb(so));
885 static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
887 int i;
889 qemu_put_sbe16(f, tp->t_state);
890 for (i = 0; i < TCPT_NTIMERS; i++)
891 qemu_put_sbe16(f, tp->t_timer[i]);
892 qemu_put_sbe16(f, tp->t_rxtshift);
893 qemu_put_sbe16(f, tp->t_rxtcur);
894 qemu_put_sbe16(f, tp->t_dupacks);
895 qemu_put_be16(f, tp->t_maxseg);
896 qemu_put_sbyte(f, tp->t_force);
897 qemu_put_be16(f, tp->t_flags);
898 qemu_put_be32(f, tp->snd_una);
899 qemu_put_be32(f, tp->snd_nxt);
900 qemu_put_be32(f, tp->snd_up);
901 qemu_put_be32(f, tp->snd_wl1);
902 qemu_put_be32(f, tp->snd_wl2);
903 qemu_put_be32(f, tp->iss);
904 qemu_put_be32(f, tp->snd_wnd);
905 qemu_put_be32(f, tp->rcv_wnd);
906 qemu_put_be32(f, tp->rcv_nxt);
907 qemu_put_be32(f, tp->rcv_up);
908 qemu_put_be32(f, tp->irs);
909 qemu_put_be32(f, tp->rcv_adv);
910 qemu_put_be32(f, tp->snd_max);
911 qemu_put_be32(f, tp->snd_cwnd);
912 qemu_put_be32(f, tp->snd_ssthresh);
913 qemu_put_sbe16(f, tp->t_idle);
914 qemu_put_sbe16(f, tp->t_rtt);
915 qemu_put_be32(f, tp->t_rtseq);
916 qemu_put_sbe16(f, tp->t_srtt);
917 qemu_put_sbe16(f, tp->t_rttvar);
918 qemu_put_be16(f, tp->t_rttmin);
919 qemu_put_be32(f, tp->max_sndwnd);
920 qemu_put_byte(f, tp->t_oobflags);
921 qemu_put_byte(f, tp->t_iobc);
922 qemu_put_sbe16(f, tp->t_softerror);
923 qemu_put_byte(f, tp->snd_scale);
924 qemu_put_byte(f, tp->rcv_scale);
925 qemu_put_byte(f, tp->request_r_scale);
926 qemu_put_byte(f, tp->requested_s_scale);
927 qemu_put_be32(f, tp->ts_recent);
928 qemu_put_be32(f, tp->ts_recent_age);
929 qemu_put_be32(f, tp->last_ack_sent);
932 static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
934 uint32_t off;
936 qemu_put_be32(f, sbuf->sb_cc);
937 qemu_put_be32(f, sbuf->sb_datalen);
938 off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
939 qemu_put_sbe32(f, off);
940 off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
941 qemu_put_sbe32(f, off);
942 qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
945 static void slirp_socket_save(QEMUFile *f, struct socket *so)
947 qemu_put_be32(f, so->so_urgc);
948 qemu_put_be32(f, so->so_faddr.s_addr);
949 qemu_put_be32(f, so->so_laddr.s_addr);
950 qemu_put_be16(f, so->so_fport);
951 qemu_put_be16(f, so->so_lport);
952 qemu_put_byte(f, so->so_iptos);
953 qemu_put_byte(f, so->so_emu);
954 qemu_put_byte(f, so->so_type);
955 qemu_put_be32(f, so->so_state);
956 slirp_sbuf_save(f, &so->so_rcv);
957 slirp_sbuf_save(f, &so->so_snd);
958 slirp_tcp_save(f, so->so_tcpcb);
961 static void slirp_state_save(QEMUFile *f, void *opaque)
963 struct ex_list *ex_ptr;
965 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
966 if (ex_ptr->ex_pty == 3) {
967 struct socket *so;
968 so = slirp_find_ctl_socket(ex_ptr->ex_addr, ntohs(ex_ptr->ex_fport));
969 if (!so)
970 continue;
972 qemu_put_byte(f, 42);
973 slirp_socket_save(f, so);
975 qemu_put_byte(f, 0);
977 qemu_put_be16(f, ip_id);
980 static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
982 int i;
984 tp->t_state = qemu_get_sbe16(f);
985 for (i = 0; i < TCPT_NTIMERS; i++)
986 tp->t_timer[i] = qemu_get_sbe16(f);
987 tp->t_rxtshift = qemu_get_sbe16(f);
988 tp->t_rxtcur = qemu_get_sbe16(f);
989 tp->t_dupacks = qemu_get_sbe16(f);
990 tp->t_maxseg = qemu_get_be16(f);
991 tp->t_force = qemu_get_sbyte(f);
992 tp->t_flags = qemu_get_be16(f);
993 tp->snd_una = qemu_get_be32(f);
994 tp->snd_nxt = qemu_get_be32(f);
995 tp->snd_up = qemu_get_be32(f);
996 tp->snd_wl1 = qemu_get_be32(f);
997 tp->snd_wl2 = qemu_get_be32(f);
998 tp->iss = qemu_get_be32(f);
999 tp->snd_wnd = qemu_get_be32(f);
1000 tp->rcv_wnd = qemu_get_be32(f);
1001 tp->rcv_nxt = qemu_get_be32(f);
1002 tp->rcv_up = qemu_get_be32(f);
1003 tp->irs = qemu_get_be32(f);
1004 tp->rcv_adv = qemu_get_be32(f);
1005 tp->snd_max = qemu_get_be32(f);
1006 tp->snd_cwnd = qemu_get_be32(f);
1007 tp->snd_ssthresh = qemu_get_be32(f);
1008 tp->t_idle = qemu_get_sbe16(f);
1009 tp->t_rtt = qemu_get_sbe16(f);
1010 tp->t_rtseq = qemu_get_be32(f);
1011 tp->t_srtt = qemu_get_sbe16(f);
1012 tp->t_rttvar = qemu_get_sbe16(f);
1013 tp->t_rttmin = qemu_get_be16(f);
1014 tp->max_sndwnd = qemu_get_be32(f);
1015 tp->t_oobflags = qemu_get_byte(f);
1016 tp->t_iobc = qemu_get_byte(f);
1017 tp->t_softerror = qemu_get_sbe16(f);
1018 tp->snd_scale = qemu_get_byte(f);
1019 tp->rcv_scale = qemu_get_byte(f);
1020 tp->request_r_scale = qemu_get_byte(f);
1021 tp->requested_s_scale = qemu_get_byte(f);
1022 tp->ts_recent = qemu_get_be32(f);
1023 tp->ts_recent_age = qemu_get_be32(f);
1024 tp->last_ack_sent = qemu_get_be32(f);
1025 tcp_template(tp);
1028 static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
1030 uint32_t off, sb_cc, sb_datalen;
1032 sb_cc = qemu_get_be32(f);
1033 sb_datalen = qemu_get_be32(f);
1035 sbreserve(sbuf, sb_datalen);
1037 if (sbuf->sb_datalen != sb_datalen)
1038 return -ENOMEM;
1040 sbuf->sb_cc = sb_cc;
1042 off = qemu_get_sbe32(f);
1043 sbuf->sb_wptr = sbuf->sb_data + off;
1044 off = qemu_get_sbe32(f);
1045 sbuf->sb_rptr = sbuf->sb_data + off;
1046 qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
1048 return 0;
1051 static int slirp_socket_load(QEMUFile *f, struct socket *so)
1053 if (tcp_attach(so) < 0)
1054 return -ENOMEM;
1056 so->so_urgc = qemu_get_be32(f);
1057 so->so_faddr.s_addr = qemu_get_be32(f);
1058 so->so_laddr.s_addr = qemu_get_be32(f);
1059 so->so_fport = qemu_get_be16(f);
1060 so->so_lport = qemu_get_be16(f);
1061 so->so_iptos = qemu_get_byte(f);
1062 so->so_emu = qemu_get_byte(f);
1063 so->so_type = qemu_get_byte(f);
1064 so->so_state = qemu_get_be32(f);
1065 if (slirp_sbuf_load(f, &so->so_rcv) < 0)
1066 return -ENOMEM;
1067 if (slirp_sbuf_load(f, &so->so_snd) < 0)
1068 return -ENOMEM;
1069 slirp_tcp_load(f, so->so_tcpcb);
1071 return 0;
1074 static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
1076 struct ex_list *ex_ptr;
1077 int r;
1079 while ((r = qemu_get_byte(f))) {
1080 int ret;
1081 struct socket *so = socreate();
1083 if (!so)
1084 return -ENOMEM;
1086 ret = slirp_socket_load(f, so);
1088 if (ret < 0)
1089 return ret;
1091 if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) !=
1092 vnetwork_addr.s_addr) {
1093 return -EINVAL;
1095 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
1096 if (ex_ptr->ex_pty == 3 &&
1097 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
1098 so->so_fport == ex_ptr->ex_fport) {
1099 break;
1102 if (!ex_ptr)
1103 return -EINVAL;
1105 so->extra = (void *)ex_ptr->ex_exec;
1108 if (version_id >= 2) {
1109 ip_id = qemu_get_be16(f);
1112 return 0;