1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "qemu-common.h"
25#include "qemu-timer.h"
26#include "qemu-char.h"
27#include "slirp.h"
28#include "hw/hw.h"
29
30
31struct in_addr our_addr;
32
33struct in_addr dns_addr;
34
35struct in_addr loopback_addr;
36
37
38static const uint8_t special_ethaddr[6] = {
39 0x52, 0x55, 0x00, 0x00, 0x00, 0x00
40};
41
42static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
43
44
45fd_set *global_readfds, *global_writefds, *global_xfds;
46
47u_int curtime;
48static u_int time_fasttimo, last_slowtimo;
49static int do_slowtimo;
50
51static TAILQ_HEAD(slirp_instances, Slirp) slirp_instances =
52 TAILQ_HEAD_INITIALIZER(slirp_instances);
53
54#ifdef _WIN32
55
56static int get_dns_addr(struct in_addr *pdns_addr)
57{
58 FIXED_INFO *FixedInfo=NULL;
59 ULONG BufLen;
60 DWORD ret;
61 IP_ADDR_STRING *pIPAddr;
62 struct in_addr tmp_addr;
63
64 FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
65 BufLen = sizeof(FIXED_INFO);
66
67 if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
68 if (FixedInfo) {
69 GlobalFree(FixedInfo);
70 FixedInfo = NULL;
71 }
72 FixedInfo = GlobalAlloc(GPTR, BufLen);
73 }
74
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;
80 }
81 return -1;
82 }
83
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;
90 }
91 return 0;
92}
93
94static void winsock_cleanup(void)
95{
96 WSACleanup();
97}
98
99#else
100
101static int get_dns_addr(struct in_addr *pdns_addr)
102{
103 char buff[512];
104 char buff2[257];
105 FILE *f;
106 int found = 0;
107 struct in_addr tmp_addr;
108
109 f = fopen("/etc/resolv.conf", "r");
110 if (!f)
111 return -1;
112
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
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;
134 }
135#ifdef DEBUG
136 else
137 lprint("%s", inet_ntoa(tmp_addr));
138#endif
139 }
140 }
141 fclose(f);
142 if (!found)
143 return -1;
144 return 0;
145}
146
147#endif
148
149static void slirp_init_once(void)
150{
151 static int initialized;
152 struct hostent *he;
153 char our_name[256];
154#ifdef _WIN32
155 WSADATA Data;
156#endif
157
158 if (initialized) {
159 return;
160 }
161 initialized = 1;
162
163#ifdef _WIN32
164 WSAStartup(MAKEWORD(2,0), &Data);
165 atexit(winsock_cleanup);
166#endif
167
168 loopback_addr.s_addr = htonl(INADDR_LOOPBACK);
169
170
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;
175 }
176 }
177 if (our_addr.s_addr == 0) {
178 our_addr = loopback_addr;
179 }
180
181
182 if (get_dns_addr(&dns_addr) < 0) {
183 dns_addr = loopback_addr;
184 }
185}
186
187static void slirp_state_save(QEMUFile *f, void *opaque);
188static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
189
190Slirp *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, void *opaque)
195{
196 Slirp *slirp = qemu_mallocz(sizeof(Slirp));
197
198 slirp_init_once();
199
200 slirp->restricted = restricted;
201
202 if_init(slirp);
203 ip_init(slirp);
204
205
206 m_init(slirp);
207
208 slirp->vnetwork_addr = vnetwork;
209 slirp->vnetwork_mask = vnetmask;
210 slirp->vhost_addr = vhost;
211 if (vhostname) {
212 pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
213 vhostname);
214 }
215 if (tftp_path) {
216 slirp->tftp_prefix = qemu_strdup(tftp_path);
217 }
218 if (bootfile) {
219 slirp->bootp_filename = qemu_strdup(bootfile);
220 }
221 slirp->vdhcp_startaddr = vdhcp_start;
222 slirp->vnameserver_addr = vnameserver;
223
224 slirp->opaque = opaque;
225
226 register_savevm("slirp", 0, 3, slirp_state_save, slirp_state_load, slirp);
227
228 TAILQ_INSERT_TAIL(&slirp_instances, slirp, entry);
229
230 return slirp;
231}
232
233void slirp_cleanup(Slirp *slirp)
234{
235 TAILQ_REMOVE(&slirp_instances, slirp, entry);
236
237 unregister_savevm("slirp", slirp);
238
239 qemu_free(slirp->tftp_prefix);
240 qemu_free(slirp->bootp_filename);
241 qemu_free(slirp);
242}
243
244#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
245#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
246#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
247
248void slirp_select_fill(int *pnfds,
249 fd_set *readfds, fd_set *writefds, fd_set *xfds)
250{
251 Slirp *slirp;
252 struct socket *so, *so_next;
253 int nfds;
254
255 if (TAILQ_EMPTY(&slirp_instances)) {
256 return;
257 }
258
259
260 global_readfds = NULL;
261 global_writefds = NULL;
262 global_xfds = NULL;
263
264 nfds = *pnfds;
265
266
267
268 do_slowtimo = 0;
269
270 TAILQ_FOREACH(slirp, &slirp_instances, entry) {
271
272
273
274
275 do_slowtimo |= ((slirp->tcb.so_next != &slirp->tcb) ||
276 (&slirp->ipq.ip_link != slirp->ipq.ip_link.next));
277
278 for (so = slirp->tcb.so_next; so != &slirp->tcb;
279 so = so_next) {
280 so_next = so->so_next;
281
282
283
284
285 if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
286 time_fasttimo = curtime;
287
288
289
290
291
292 if (so->so_state & SS_NOFDREF || so->s == -1)
293 continue;
294
295
296
297
298 if (so->so_state & SS_FACCEPTCONN) {
299 FD_SET(so->s, readfds);
300 UPD_NFDS(so->s);
301 continue;
302 }
303
304
305
306
307 if (so->so_state & SS_ISFCONNECTING) {
308 FD_SET(so->s, writefds);
309 UPD_NFDS(so->s);
310 continue;
311 }
312
313
314
315
316
317 if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
318 FD_SET(so->s, writefds);
319 UPD_NFDS(so->s);
320 }
321
322
323
324
325
326 if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
327 FD_SET(so->s, readfds);
328 FD_SET(so->s, xfds);
329 UPD_NFDS(so->s);
330 }
331 }
332
333
334
335
336 for (so = slirp->udb.so_next; so != &slirp->udb;
337 so = so_next) {
338 so_next = so->so_next;
339
340
341
342
343 if (so->so_expire) {
344 if (so->so_expire <= curtime) {
345 udp_detach(so);
346 continue;
347 } else
348 do_slowtimo = 1;
349 }
350
351
352
353
354
355
356
357
358
359
360
361 if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
362 FD_SET(so->s, readfds);
363 UPD_NFDS(so->s);
364 }
365 }
366 }
367
368 *pnfds = nfds;
369}
370
371void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
372 int select_error)
373{
374 Slirp *slirp;
375 struct socket *so, *so_next;
376 int ret;
377
378 if (TAILQ_EMPTY(&slirp_instances)) {
379 return;
380 }
381
382 global_readfds = readfds;
383 global_writefds = writefds;
384 global_xfds = xfds;
385
386 curtime = qemu_get_clock(rt_clock);
387
388 TAILQ_FOREACH(slirp, &slirp_instances, entry) {
389
390
391
392 if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
393 tcp_fasttimo(slirp);
394 time_fasttimo = 0;
395 }
396 if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
397 ip_slowtimo(slirp);
398 tcp_slowtimo(slirp);
399 last_slowtimo = curtime;
400 }
401
402
403
404
405 if (!select_error) {
406
407
408
409 for (so = slirp->tcb.so_next; so != &slirp->tcb;
410 so = so_next) {
411 so_next = so->so_next;
412
413
414
415
416
417 if (so->so_state & SS_NOFDREF || so->s == -1)
418 continue;
419
420
421
422
423
424
425 if (FD_ISSET(so->s, xfds))
426 sorecvoob(so);
427
428
429
430 else if (FD_ISSET(so->s, readfds)) {
431
432
433
434 if (so->so_state & SS_FACCEPTCONN) {
435 tcp_connect(so);
436 continue;
437 }
438 ret = soread(so);
439
440
441 if (ret > 0)
442 tcp_output(sototcpcb(so));
443 }
444
445
446
447
448 if (FD_ISSET(so->s, writefds)) {
449
450
451
452 if (so->so_state & SS_ISFCONNECTING) {
453
454 so->so_state &= ~SS_ISFCONNECTING;
455
456 ret = send(so->s, (const void *) &ret, 0, 0);
457 if (ret < 0) {
458
459 if (errno == EAGAIN || errno == EWOULDBLOCK ||
460 errno == EINPROGRESS || errno == ENOTCONN)
461 continue;
462
463
464 so->so_state &= SS_PERSISTENT_MASK;
465 so->so_state |= SS_NOFDREF;
466 }
467
468
469
470
471
472 tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
473
474 } else
475 ret = sowrite(so);
476
477
478
479
480
481
482 }
483
484
485
486
487
488#ifdef PROBE_CONN
489 if (so->so_state & SS_ISFCONNECTING) {
490 ret = recv(so->s, (char *)&ret, 0,0);
491
492 if (ret < 0) {
493
494 if (errno == EAGAIN || errno == EWOULDBLOCK ||
495 errno == EINPROGRESS || errno == ENOTCONN)
496 continue;
497
498
499 so->so_state &= SS_PERSISTENT_MASK;
500 so->so_state |= SS_NOFDREF;
501
502
503 } else {
504 ret = send(so->s, &ret, 0,0);
505 if (ret < 0) {
506
507 if (errno == EAGAIN || errno == EWOULDBLOCK ||
508 errno == EINPROGRESS || errno == ENOTCONN)
509 continue;
510
511 so->so_state &= SS_PERSISTENT_MASK;
512 so->so_state |= SS_NOFDREF;
513 } else
514 so->so_state &= ~SS_ISFCONNECTING;
515
516 }
517 tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
518 }
519#endif
520 }
521
522
523
524
525
526
527 for (so = slirp->udb.so_next; so != &slirp->udb;
528 so = so_next) {
529 so_next = so->so_next;
530
531 if (so->s != -1 && FD_ISSET(so->s, readfds)) {
532 sorecvfrom(so);
533 }
534 }
535 }
536
537
538
539
540 if (slirp->if_queued) {
541 if_start(slirp);
542 }
543 }
544
545
546
547
548
549
550 global_readfds = NULL;
551 global_writefds = NULL;
552 global_xfds = NULL;
553}
554
555#define ETH_ALEN 6
556#define ETH_HLEN 14
557
558#define ETH_P_IP 0x0800
559#define ETH_P_ARP 0x0806
560
561#define ARPOP_REQUEST 1
562#define ARPOP_REPLY 2
563
564struct ethhdr
565{
566 unsigned char h_dest[ETH_ALEN];
567 unsigned char h_source[ETH_ALEN];
568 unsigned short h_proto;
569};
570
571struct arphdr
572{
573 unsigned short ar_hrd;
574 unsigned short ar_pro;
575 unsigned char ar_hln;
576 unsigned char ar_pln;
577 unsigned short ar_op;
578
579
580
581
582 unsigned char ar_sha[ETH_ALEN];
583 uint32_t ar_sip;
584 unsigned char ar_tha[ETH_ALEN];
585 uint32_t ar_tip ;
586} __attribute__((packed));
587
588static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
589{
590 struct ethhdr *eh = (struct ethhdr *)pkt;
591 struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
592 uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
593 struct ethhdr *reh = (struct ethhdr *)arp_reply;
594 struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
595 int ar_op;
596 struct ex_list *ex_ptr;
597
598 ar_op = ntohs(ah->ar_op);
599 switch(ar_op) {
600 case ARPOP_REQUEST:
601 if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
602 slirp->vnetwork_addr.s_addr) {
603 if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
604 ah->ar_tip == slirp->vhost_addr.s_addr)
605 goto arp_ok;
606 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
607 if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
608 goto arp_ok;
609 }
610 return;
611 arp_ok:
612
613 memcpy(slirp->client_ethaddr, eh->h_source, ETH_ALEN);
614
615
616 memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
617 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
618 memcpy(&reh->h_source[2], &ah->ar_tip, 4);
619 reh->h_proto = htons(ETH_P_ARP);
620
621 rah->ar_hrd = htons(1);
622 rah->ar_pro = htons(ETH_P_IP);
623 rah->ar_hln = ETH_ALEN;
624 rah->ar_pln = 4;
625 rah->ar_op = htons(ARPOP_REPLY);
626 memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
627 rah->ar_sip = ah->ar_tip;
628 memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
629 rah->ar_tip = ah->ar_sip;
630 slirp_output(slirp->opaque, arp_reply, sizeof(arp_reply));
631 }
632 break;
633 case ARPOP_REPLY:
634
635 if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN) &&
636 ah->ar_sip == slirp->client_ipaddr.s_addr) {
637 memcpy(slirp->client_ethaddr, ah->ar_sha, ETH_ALEN);
638 }
639 break;
640 default:
641 break;
642 }
643}
644
645void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
646{
647 struct mbuf *m;
648 int proto;
649
650 if (pkt_len < ETH_HLEN)
651 return;
652
653 proto = ntohs(*(uint16_t *)(pkt + 12));
654 switch(proto) {
655 case ETH_P_ARP:
656 arp_input(slirp, pkt, pkt_len);
657 break;
658 case ETH_P_IP:
659 m = m_get(slirp);
660 if (!m)
661 return;
662
663 if (M_FREEROOM(m) < pkt_len + 2) {
664 m_inc(m, pkt_len + 2);
665 }
666 m->m_len = pkt_len + 2;
667 memcpy(m->m_data + 2, pkt, pkt_len);
668
669 m->m_data += 2 + ETH_HLEN;
670 m->m_len -= 2 + ETH_HLEN;
671
672 ip_input(m);
673 break;
674 default:
675 break;
676 }
677}
678
679
680void if_encap(Slirp *slirp, const uint8_t *ip_data, int ip_data_len)
681{
682 uint8_t buf[1600];
683 struct ethhdr *eh = (struct ethhdr *)buf;
684
685 if (ip_data_len + ETH_HLEN > sizeof(buf))
686 return;
687
688 if (!memcmp(slirp->client_ethaddr, zero_ethaddr, ETH_ALEN)) {
689 uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
690 struct ethhdr *reh = (struct ethhdr *)arp_req;
691 struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
692 const struct ip *iph = (const struct ip *)ip_data;
693
694
695
696
697
698
699 memset(reh->h_dest, 0xff, ETH_ALEN);
700 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
701 memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
702 reh->h_proto = htons(ETH_P_ARP);
703 rah->ar_hrd = htons(1);
704 rah->ar_pro = htons(ETH_P_IP);
705 rah->ar_hln = ETH_ALEN;
706 rah->ar_pln = 4;
707 rah->ar_op = htons(ARPOP_REQUEST);
708
709 memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
710 memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
711
712 rah->ar_sip = slirp->vhost_addr.s_addr;
713
714 memset(rah->ar_tha, 0, ETH_ALEN);
715
716 rah->ar_tip = iph->ip_dst.s_addr;
717 slirp->client_ipaddr = iph->ip_dst;
718 slirp_output(slirp->opaque, arp_req, sizeof(arp_req));
719 } else {
720 memcpy(eh->h_dest, slirp->client_ethaddr, ETH_ALEN);
721 memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
722
723 memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
724 eh->h_proto = htons(ETH_P_IP);
725 memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
726 slirp_output(slirp->opaque, buf, ip_data_len + ETH_HLEN);
727 }
728}
729
730
731int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
732 int host_port)
733{
734 struct socket *so;
735 struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);
736 struct sockaddr_in addr;
737 int port = htons(host_port);
738 socklen_t addr_len;
739
740 for (so = head->so_next; so != head; so = so->so_next) {
741 addr_len = sizeof(addr);
742 if ((so->so_state & SS_HOSTFWD) &&
743 getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
744 addr.sin_addr.s_addr == host_addr.s_addr &&
745 addr.sin_port == port) {
746 close(so->s);
747 sofree(so);
748 return 0;
749 }
750 }
751
752 return -1;
753}
754
755int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
756 int host_port, struct in_addr guest_addr, int guest_port)
757{
758 if (!guest_addr.s_addr) {
759 guest_addr = slirp->vdhcp_startaddr;
760 }
761 if (is_udp) {
762 if (!udp_listen(slirp, host_addr.s_addr, htons(host_port),
763 guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
764 return -1;
765 } else {
766 if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port),
767 guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
768 return -1;
769 }
770 return 0;
771}
772
773int slirp_add_exec(Slirp *slirp, int do_pty, const void *args,
774 struct in_addr *guest_addr, int guest_port)
775{
776 if (!guest_addr->s_addr) {
777 guest_addr->s_addr = slirp->vnetwork_addr.s_addr |
778 (htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
779 }
780 if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) !=
781 slirp->vnetwork_addr.s_addr ||
782 guest_addr->s_addr == slirp->vhost_addr.s_addr ||
783 guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
784 return -1;
785 }
786 return add_exec(&slirp->exec_list, do_pty, (char *)args, *guest_addr,
787 htons(guest_port));
788}
789
790ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
791{
792 if (so->s == -1 && so->extra) {
793 qemu_chr_write(so->extra, buf, len);
794 return len;
795 }
796
797 return send(so->s, buf, len, flags);
798}
799
800static struct socket *
801slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, int guest_port)
802{
803 struct socket *so;
804
805 for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
806 if (so->so_faddr.s_addr == guest_addr.s_addr &&
807 htons(so->so_fport) == guest_port) {
808 return so;
809 }
810 }
811 return NULL;
812}
813
814size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
815 int guest_port)
816{
817 struct iovec iov[2];
818 struct socket *so;
819
820 so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
821
822 if (!so || so->so_state & SS_NOFDREF)
823 return 0;
824
825 if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
826 return 0;
827
828 return sopreprbuf(so, iov, NULL);
829}
830
831void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
832 const uint8_t *buf, int size)
833{
834 int ret;
835 struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
836
837 if (!so)
838 return;
839
840 ret = soreadbuf(so, (const char *)buf, size);
841
842 if (ret > 0)
843 tcp_output(sototcpcb(so));
844}
845
846static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
847{
848 int i;
849
850 qemu_put_sbe16(f, tp->t_state);
851 for (i = 0; i < TCPT_NTIMERS; i++)
852 qemu_put_sbe16(f, tp->t_timer[i]);
853 qemu_put_sbe16(f, tp->t_rxtshift);
854 qemu_put_sbe16(f, tp->t_rxtcur);
855 qemu_put_sbe16(f, tp->t_dupacks);
856 qemu_put_be16(f, tp->t_maxseg);
857 qemu_put_sbyte(f, tp->t_force);
858 qemu_put_be16(f, tp->t_flags);
859 qemu_put_be32(f, tp->snd_una);
860 qemu_put_be32(f, tp->snd_nxt);
861 qemu_put_be32(f, tp->snd_up);
862 qemu_put_be32(f, tp->snd_wl1);
863 qemu_put_be32(f, tp->snd_wl2);
864 qemu_put_be32(f, tp->iss);
865 qemu_put_be32(f, tp->snd_wnd);
866 qemu_put_be32(f, tp->rcv_wnd);
867 qemu_put_be32(f, tp->rcv_nxt);
868 qemu_put_be32(f, tp->rcv_up);
869 qemu_put_be32(f, tp->irs);
870 qemu_put_be32(f, tp->rcv_adv);
871 qemu_put_be32(f, tp->snd_max);
872 qemu_put_be32(f, tp->snd_cwnd);
873 qemu_put_be32(f, tp->snd_ssthresh);
874 qemu_put_sbe16(f, tp->t_idle);
875 qemu_put_sbe16(f, tp->t_rtt);
876 qemu_put_be32(f, tp->t_rtseq);
877 qemu_put_sbe16(f, tp->t_srtt);
878 qemu_put_sbe16(f, tp->t_rttvar);
879 qemu_put_be16(f, tp->t_rttmin);
880 qemu_put_be32(f, tp->max_sndwnd);
881 qemu_put_byte(f, tp->t_oobflags);
882 qemu_put_byte(f, tp->t_iobc);
883 qemu_put_sbe16(f, tp->t_softerror);
884 qemu_put_byte(f, tp->snd_scale);
885 qemu_put_byte(f, tp->rcv_scale);
886 qemu_put_byte(f, tp->request_r_scale);
887 qemu_put_byte(f, tp->requested_s_scale);
888 qemu_put_be32(f, tp->ts_recent);
889 qemu_put_be32(f, tp->ts_recent_age);
890 qemu_put_be32(f, tp->last_ack_sent);
891}
892
893static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
894{
895 uint32_t off;
896
897 qemu_put_be32(f, sbuf->sb_cc);
898 qemu_put_be32(f, sbuf->sb_datalen);
899 off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
900 qemu_put_sbe32(f, off);
901 off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
902 qemu_put_sbe32(f, off);
903 qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
904}
905
906static void slirp_socket_save(QEMUFile *f, struct socket *so)
907{
908 qemu_put_be32(f, so->so_urgc);
909 qemu_put_be32(f, so->so_faddr.s_addr);
910 qemu_put_be32(f, so->so_laddr.s_addr);
911 qemu_put_be16(f, so->so_fport);
912 qemu_put_be16(f, so->so_lport);
913 qemu_put_byte(f, so->so_iptos);
914 qemu_put_byte(f, so->so_emu);
915 qemu_put_byte(f, so->so_type);
916 qemu_put_be32(f, so->so_state);
917 slirp_sbuf_save(f, &so->so_rcv);
918 slirp_sbuf_save(f, &so->so_snd);
919 slirp_tcp_save(f, so->so_tcpcb);
920}
921
922static void slirp_bootp_save(QEMUFile *f, Slirp *slirp)
923{
924 int i;
925
926 for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
927 qemu_put_be16(f, slirp->bootp_clients[i].allocated);
928 qemu_put_buffer(f, slirp->bootp_clients[i].macaddr, 6);
929 }
930}
931
932static void slirp_state_save(QEMUFile *f, void *opaque)
933{
934 Slirp *slirp = opaque;
935 struct ex_list *ex_ptr;
936
937 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
938 if (ex_ptr->ex_pty == 3) {
939 struct socket *so;
940 so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
941 ntohs(ex_ptr->ex_fport));
942 if (!so)
943 continue;
944
945 qemu_put_byte(f, 42);
946 slirp_socket_save(f, so);
947 }
948 qemu_put_byte(f, 0);
949
950 qemu_put_be16(f, slirp->ip_id);
951
952 slirp_bootp_save(f, slirp);
953}
954
955static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
956{
957 int i;
958
959 tp->t_state = qemu_get_sbe16(f);
960 for (i = 0; i < TCPT_NTIMERS; i++)
961 tp->t_timer[i] = qemu_get_sbe16(f);
962 tp->t_rxtshift = qemu_get_sbe16(f);
963 tp->t_rxtcur = qemu_get_sbe16(f);
964 tp->t_dupacks = qemu_get_sbe16(f);
965 tp->t_maxseg = qemu_get_be16(f);
966 tp->t_force = qemu_get_sbyte(f);
967 tp->t_flags = qemu_get_be16(f);
968 tp->snd_una = qemu_get_be32(f);
969 tp->snd_nxt = qemu_get_be32(f);
970 tp->snd_up = qemu_get_be32(f);
971 tp->snd_wl1 = qemu_get_be32(f);
972 tp->snd_wl2 = qemu_get_be32(f);
973 tp->iss = qemu_get_be32(f);
974 tp->snd_wnd = qemu_get_be32(f);
975 tp->rcv_wnd = qemu_get_be32(f);
976 tp->rcv_nxt = qemu_get_be32(f);
977 tp->rcv_up = qemu_get_be32(f);
978 tp->irs = qemu_get_be32(f);
979 tp->rcv_adv = qemu_get_be32(f);
980 tp->snd_max = qemu_get_be32(f);
981 tp->snd_cwnd = qemu_get_be32(f);
982 tp->snd_ssthresh = qemu_get_be32(f);
983 tp->t_idle = qemu_get_sbe16(f);
984 tp->t_rtt = qemu_get_sbe16(f);
985 tp->t_rtseq = qemu_get_be32(f);
986 tp->t_srtt = qemu_get_sbe16(f);
987 tp->t_rttvar = qemu_get_sbe16(f);
988 tp->t_rttmin = qemu_get_be16(f);
989 tp->max_sndwnd = qemu_get_be32(f);
990 tp->t_oobflags = qemu_get_byte(f);
991 tp->t_iobc = qemu_get_byte(f);
992 tp->t_softerror = qemu_get_sbe16(f);
993 tp->snd_scale = qemu_get_byte(f);
994 tp->rcv_scale = qemu_get_byte(f);
995 tp->request_r_scale = qemu_get_byte(f);
996 tp->requested_s_scale = qemu_get_byte(f);
997 tp->ts_recent = qemu_get_be32(f);
998 tp->ts_recent_age = qemu_get_be32(f);
999 tp->last_ack_sent = qemu_get_be32(f);
1000 tcp_template(tp);
1001}
1002
1003static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
1004{
1005 uint32_t off, sb_cc, sb_datalen;
1006
1007 sb_cc = qemu_get_be32(f);
1008 sb_datalen = qemu_get_be32(f);
1009
1010 sbreserve(sbuf, sb_datalen);
1011
1012 if (sbuf->sb_datalen != sb_datalen)
1013 return -ENOMEM;
1014
1015 sbuf->sb_cc = sb_cc;
1016
1017 off = qemu_get_sbe32(f);
1018 sbuf->sb_wptr = sbuf->sb_data + off;
1019 off = qemu_get_sbe32(f);
1020 sbuf->sb_rptr = sbuf->sb_data + off;
1021 qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
1022
1023 return 0;
1024}
1025
1026static int slirp_socket_load(QEMUFile *f, struct socket *so)
1027{
1028 if (tcp_attach(so) < 0)
1029 return -ENOMEM;
1030
1031 so->so_urgc = qemu_get_be32(f);
1032 so->so_faddr.s_addr = qemu_get_be32(f);
1033 so->so_laddr.s_addr = qemu_get_be32(f);
1034 so->so_fport = qemu_get_be16(f);
1035 so->so_lport = qemu_get_be16(f);
1036 so->so_iptos = qemu_get_byte(f);
1037 so->so_emu = qemu_get_byte(f);
1038 so->so_type = qemu_get_byte(f);
1039 so->so_state = qemu_get_be32(f);
1040 if (slirp_sbuf_load(f, &so->so_rcv) < 0)
1041 return -ENOMEM;
1042 if (slirp_sbuf_load(f, &so->so_snd) < 0)
1043 return -ENOMEM;
1044 slirp_tcp_load(f, so->so_tcpcb);
1045
1046 return 0;
1047}
1048
1049static void slirp_bootp_load(QEMUFile *f, Slirp *slirp)
1050{
1051 int i;
1052
1053 for (i = 0; i < NB_BOOTP_CLIENTS; i++) {
1054 slirp->bootp_clients[i].allocated = qemu_get_be16(f);
1055 qemu_get_buffer(f, slirp->bootp_clients[i].macaddr, 6);
1056 }
1057}
1058
1059static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
1060{
1061 Slirp *slirp = opaque;
1062 struct ex_list *ex_ptr;
1063 int r;
1064
1065 while ((r = qemu_get_byte(f))) {
1066 int ret;
1067 struct socket *so = socreate(slirp);
1068
1069 if (!so)
1070 return -ENOMEM;
1071
1072 ret = slirp_socket_load(f, so);
1073
1074 if (ret < 0)
1075 return ret;
1076
1077 if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) !=
1078 slirp->vnetwork_addr.s_addr) {
1079 return -EINVAL;
1080 }
1081 for (ex_ptr = slirp->exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
1082 if (ex_ptr->ex_pty == 3 &&
1083 so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
1084 so->so_fport == ex_ptr->ex_fport) {
1085 break;
1086 }
1087 }
1088 if (!ex_ptr)
1089 return -EINVAL;
1090
1091 so->extra = (void *)ex_ptr->ex_exec;
1092 }
1093
1094 if (version_id >= 2) {
1095 slirp->ip_id = qemu_get_be16(f);
1096 }
1097
1098 if (version_id >= 3) {
1099 slirp_bootp_load(f, slirp);
1100 }
1101
1102 return 0;
1103}
1104