]> git.proxmox.com Git - mirror_qemu.git/blame - slirp/slirp.c
Use ESCC for PowerMac serial
[mirror_qemu.git] / slirp / slirp.c
CommitLineData
d75a0b97
FB
1/*
2 * libslirp glue
3 *
4 * Copyright (c) 2004-2008 Fabrice Bellard
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
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.
23 */
e1c5a2b3 24#include "qemu-common.h"
f0cbd3ec 25#include "slirp.h"
062e5527 26#include "hw/hw.h"
f0cbd3ec
FB
27
28/* host address */
29struct in_addr our_addr;
30/* host dns address */
31struct in_addr dns_addr;
32/* host loopback address */
33struct in_addr loopback_addr;
34
35/* address for slirp virtual addresses */
36struct in_addr special_addr;
8dbca8dd
FB
37/* virtual address alias for host */
38struct in_addr alias_addr;
f0cbd3ec 39
9634d903 40static const uint8_t special_ethaddr[6] = {
f0cbd3ec
FB
41 0x52, 0x54, 0x00, 0x12, 0x35, 0x00
42};
43
de806f07 44/* ARP cache for the guest IP addresses (XXX: allow many entries) */
f0cbd3ec 45uint8_t client_ethaddr[6];
de806f07
FB
46static struct in_addr client_ipaddr;
47
48static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
f0cbd3ec 49
a9ba3a85
AL
50char *slirp_special_ip = CTL_SPECIAL;
51int slirp_restrict;
f0cbd3ec
FB
52int do_slowtimo;
53int link_up;
54struct timeval tt;
55FILE *lfd;
a3d4af03 56struct ex_list *exec_list;
f0cbd3ec
FB
57
58/* XXX: suppress those select globals */
59fd_set *global_readfds, *global_writefds, *global_xfds;
60
3f423c9c 61char slirp_hostname[33];
115defd1 62
f0cbd3ec
FB
63#ifdef _WIN32
64
65static int get_dns_addr(struct in_addr *pdns_addr)
66{
379ff53d
FB
67 FIXED_INFO *FixedInfo=NULL;
68 ULONG BufLen;
69 DWORD ret;
70 IP_ADDR_STRING *pIPAddr;
71 struct in_addr tmp_addr;
3b46e624 72
379ff53d
FB
73 FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
74 BufLen = sizeof(FIXED_INFO);
3b46e624 75
379ff53d
FB
76 if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
77 if (FixedInfo) {
78 GlobalFree(FixedInfo);
79 FixedInfo = NULL;
80 }
81 FixedInfo = GlobalAlloc(GPTR, BufLen);
82 }
5fafdf24 83
379ff53d
FB
84 if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
85 printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
86 if (FixedInfo) {
87 GlobalFree(FixedInfo);
88 FixedInfo = NULL;
89 }
90 return -1;
91 }
3b46e624 92
379ff53d
FB
93 pIPAddr = &(FixedInfo->DnsServerList);
94 inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
95 *pdns_addr = tmp_addr;
96#if 0
97 printf( "DNS Servers:\n" );
98 printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
3b46e624 99
379ff53d
FB
100 pIPAddr = FixedInfo -> DnsServerList.Next;
101 while ( pIPAddr ) {
102 printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
103 pIPAddr = pIPAddr ->Next;
104 }
105#endif
106 if (FixedInfo) {
107 GlobalFree(FixedInfo);
108 FixedInfo = NULL;
109 }
110 return 0;
f0cbd3ec
FB
111}
112
113#else
114
115static int get_dns_addr(struct in_addr *pdns_addr)
116{
117 char buff[512];
363a37d5 118 char buff2[257];
f0cbd3ec
FB
119 FILE *f;
120 int found = 0;
121 struct in_addr tmp_addr;
3b46e624 122
f0cbd3ec
FB
123 f = fopen("/etc/resolv.conf", "r");
124 if (!f)
125 return -1;
126
31a60e22 127#ifdef DEBUG
f0cbd3ec 128 lprint("IP address of your DNS(s): ");
31a60e22 129#endif
f0cbd3ec
FB
130 while (fgets(buff, 512, f) != NULL) {
131 if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
132 if (!inet_aton(buff2, &tmp_addr))
133 continue;
134 if (tmp_addr.s_addr == loopback_addr.s_addr)
135 tmp_addr = our_addr;
136 /* If it's the first one, set it to dns_addr */
137 if (!found)
138 *pdns_addr = tmp_addr;
31a60e22 139#ifdef DEBUG
f0cbd3ec
FB
140 else
141 lprint(", ");
31a60e22 142#endif
f0cbd3ec 143 if (++found > 3) {
31a60e22 144#ifdef DEBUG
f0cbd3ec 145 lprint("(more)");
31a60e22 146#endif
f0cbd3ec 147 break;
31a60e22
BS
148 }
149#ifdef DEBUG
150 else
f0cbd3ec 151 lprint("%s", inet_ntoa(tmp_addr));
31a60e22 152#endif
f0cbd3ec
FB
153 }
154 }
1d43a717 155 fclose(f);
f0cbd3ec
FB
156 if (!found)
157 return -1;
158 return 0;
159}
160
161#endif
162
379ff53d 163#ifdef _WIN32
9634d903 164static void slirp_cleanup(void)
379ff53d
FB
165{
166 WSACleanup();
167}
168#endif
169
062e5527
AL
170static void slirp_state_save(QEMUFile *f, void *opaque);
171static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);
172
a9ba3a85 173void slirp_init(int restrict, char *special_ip)
f0cbd3ec 174{
512176db 175 // debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
3b46e624 176
379ff53d
FB
177#ifdef _WIN32
178 {
179 WSADATA Data;
180 WSAStartup(MAKEWORD(2,0), &Data);
181 atexit(slirp_cleanup);
182 }
183#endif
184
f0cbd3ec 185 link_up = 1;
a9ba3a85 186 slirp_restrict = restrict;
f0cbd3ec
FB
187
188 if_init();
189 ip_init();
190
191 /* Initialise mbufs *after* setting the MTU */
192 m_init();
193
194 /* set default addresses */
f0cbd3ec
FB
195 inet_aton("127.0.0.1", &loopback_addr);
196
197 if (get_dns_addr(&dns_addr) < 0) {
0f8134bf
PB
198 dns_addr = loopback_addr;
199 fprintf (stderr, "Warning: No DNS servers found\n");
f0cbd3ec
FB
200 }
201
a9ba3a85
AL
202 if (special_ip)
203 slirp_special_ip = special_ip;
204
205 inet_aton(slirp_special_ip, &special_addr);
8dbca8dd 206 alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
f4e15b4b 207 getouraddr();
062e5527 208 register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL);
f0cbd3ec
FB
209}
210
211#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
212#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
213#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
214
215/*
216 * curtime kept to an accuracy of 1ms
217 */
379ff53d
FB
218#ifdef _WIN32
219static void updtime(void)
220{
221 struct _timeb tb;
222
223 _ftime(&tb);
224 curtime = (u_int)tb.time * (u_int)1000;
225 curtime += (u_int)tb.millitm;
226}
227#else
f0cbd3ec
FB
228static void updtime(void)
229{
230 gettimeofday(&tt, 0);
5fafdf24 231
f0cbd3ec
FB
232 curtime = (u_int)tt.tv_sec * (u_int)1000;
233 curtime += (u_int)tt.tv_usec / (u_int)1000;
5fafdf24 234
f0cbd3ec
FB
235 if ((tt.tv_usec % 1000) >= 500)
236 curtime++;
237}
379ff53d 238#endif
f0cbd3ec 239
5fafdf24 240void slirp_select_fill(int *pnfds,
f0cbd3ec
FB
241 fd_set *readfds, fd_set *writefds, fd_set *xfds)
242{
243 struct socket *so, *so_next;
244 struct timeval timeout;
245 int nfds;
246 int tmp_time;
247
248 /* fail safe */
249 global_readfds = NULL;
250 global_writefds = NULL;
251 global_xfds = NULL;
3b46e624 252
f0cbd3ec
FB
253 nfds = *pnfds;
254 /*
255 * First, TCP sockets
256 */
257 do_slowtimo = 0;
258 if (link_up) {
5fafdf24 259 /*
f0cbd3ec
FB
260 * *_slowtimo needs calling if there are IP fragments
261 * in the fragment queue, or there are TCP connections active
262 */
263 do_slowtimo = ((tcb.so_next != &tcb) ||
264 ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
3b46e624 265
f0cbd3ec
FB
266 for (so = tcb.so_next; so != &tcb; so = so_next) {
267 so_next = so->so_next;
3b46e624 268
f0cbd3ec
FB
269 /*
270 * See if we need a tcp_fasttimo
271 */
272 if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
273 time_fasttimo = curtime; /* Flag when we want a fasttimo */
3b46e624 274
f0cbd3ec
FB
275 /*
276 * NOFDREF can include still connecting to local-host,
277 * newly socreated() sockets etc. Don't want to select these.
278 */
279 if (so->so_state & SS_NOFDREF || so->s == -1)
280 continue;
3b46e624 281
f0cbd3ec
FB
282 /*
283 * Set for reading sockets which are accepting
284 */
285 if (so->so_state & SS_FACCEPTCONN) {
286 FD_SET(so->s, readfds);
287 UPD_NFDS(so->s);
288 continue;
289 }
3b46e624 290
f0cbd3ec
FB
291 /*
292 * Set for writing sockets which are connecting
293 */
294 if (so->so_state & SS_ISFCONNECTING) {
295 FD_SET(so->s, writefds);
296 UPD_NFDS(so->s);
297 continue;
298 }
3b46e624 299
f0cbd3ec
FB
300 /*
301 * Set for writing if we are connected, can send more, and
302 * we have something to send
303 */
304 if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
305 FD_SET(so->s, writefds);
306 UPD_NFDS(so->s);
307 }
3b46e624 308
f0cbd3ec
FB
309 /*
310 * Set for reading (and urgent data) if we are connected, can
311 * receive more, and we have room for it XXX /2 ?
312 */
313 if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
314 FD_SET(so->s, readfds);
315 FD_SET(so->s, xfds);
316 UPD_NFDS(so->s);
317 }
318 }
3b46e624 319
f0cbd3ec
FB
320 /*
321 * UDP sockets
322 */
323 for (so = udb.so_next; so != &udb; so = so_next) {
324 so_next = so->so_next;
3b46e624 325
f0cbd3ec
FB
326 /*
327 * See if it's timed out
328 */
329 if (so->so_expire) {
330 if (so->so_expire <= curtime) {
331 udp_detach(so);
332 continue;
333 } else
334 do_slowtimo = 1; /* Let socket expire */
335 }
3b46e624 336
f0cbd3ec
FB
337 /*
338 * When UDP packets are received from over the
339 * link, they're sendto()'d straight away, so
340 * no need for setting for writing
341 * Limit the number of packets queued by this session
342 * to 4. Note that even though we try and limit this
343 * to 4 packets, the session could have more queued
344 * if the packets needed to be fragmented
345 * (XXX <= 4 ?)
346 */
347 if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
348 FD_SET(so->s, readfds);
349 UPD_NFDS(so->s);
350 }
351 }
352 }
5fafdf24 353
f0cbd3ec
FB
354 /*
355 * Setup timeout to use minimum CPU usage, especially when idle
356 */
5fafdf24
TS
357
358 /*
f0cbd3ec
FB
359 * First, see the timeout needed by *timo
360 */
361 timeout.tv_sec = 0;
362 timeout.tv_usec = -1;
363 /*
364 * If a slowtimo is needed, set timeout to 500ms from the last
365 * slow timeout. If a fast timeout is needed, set timeout within
366 * 200ms of when it was requested.
367 */
368 if (do_slowtimo) {
369 /* XXX + 10000 because some select()'s aren't that accurate */
370 timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
371 if (timeout.tv_usec < 0)
372 timeout.tv_usec = 0;
373 else if (timeout.tv_usec > 510000)
374 timeout.tv_usec = 510000;
3b46e624 375
f0cbd3ec
FB
376 /* Can only fasttimo if we also slowtimo */
377 if (time_fasttimo) {
378 tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
379 if (tmp_time < 0)
380 tmp_time = 0;
3b46e624 381
f0cbd3ec
FB
382 /* Choose the smallest of the 2 */
383 if (tmp_time < timeout.tv_usec)
384 timeout.tv_usec = (u_int)tmp_time;
385 }
386 }
387 *pnfds = nfds;
5fafdf24 388}
f0cbd3ec
FB
389
390void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
391{
392 struct socket *so, *so_next;
393 int ret;
394
395 global_readfds = readfds;
396 global_writefds = writefds;
397 global_xfds = xfds;
398
399 /* Update time */
400 updtime();
5fafdf24 401
f0cbd3ec 402 /*
5fafdf24 403 * See if anything has timed out
f0cbd3ec
FB
404 */
405 if (link_up) {
df5f8956 406 if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
f0cbd3ec
FB
407 tcp_fasttimo();
408 time_fasttimo = 0;
409 }
410 if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
411 ip_slowtimo();
412 tcp_slowtimo();
413 last_slowtimo = curtime;
414 }
415 }
5fafdf24 416
f0cbd3ec
FB
417 /*
418 * Check sockets
419 */
420 if (link_up) {
421 /*
422 * Check TCP sockets
423 */
424 for (so = tcb.so_next; so != &tcb; so = so_next) {
425 so_next = so->so_next;
3b46e624 426
f0cbd3ec
FB
427 /*
428 * FD_ISSET is meaningless on these sockets
429 * (and they can crash the program)
430 */
431 if (so->so_state & SS_NOFDREF || so->s == -1)
432 continue;
3b46e624 433
f0cbd3ec
FB
434 /*
435 * Check for URG data
436 * This will soread as well, so no need to
437 * test for readfds below if this succeeds
438 */
439 if (FD_ISSET(so->s, xfds))
440 sorecvoob(so);
441 /*
442 * Check sockets for reading
443 */
444 else if (FD_ISSET(so->s, readfds)) {
445 /*
446 * Check for incoming connections
447 */
448 if (so->so_state & SS_FACCEPTCONN) {
449 tcp_connect(so);
450 continue;
451 } /* else */
452 ret = soread(so);
3b46e624 453
f0cbd3ec
FB
454 /* Output it if we read something */
455 if (ret > 0)
456 tcp_output(sototcpcb(so));
457 }
3b46e624 458
f0cbd3ec
FB
459 /*
460 * Check sockets for writing
461 */
462 if (FD_ISSET(so->s, writefds)) {
463 /*
464 * Check for non-blocking, still-connecting sockets
465 */
466 if (so->so_state & SS_ISFCONNECTING) {
467 /* Connected */
468 so->so_state &= ~SS_ISFCONNECTING;
3b46e624 469
02d2c54c 470 ret = send(so->s, &ret, 0, 0);
f0cbd3ec
FB
471 if (ret < 0) {
472 /* XXXXX Must fix, zero bytes is a NOP */
473 if (errno == EAGAIN || errno == EWOULDBLOCK ||
474 errno == EINPROGRESS || errno == ENOTCONN)
475 continue;
3b46e624 476
f0cbd3ec
FB
477 /* else failed */
478 so->so_state = SS_NOFDREF;
479 }
480 /* else so->so_state &= ~SS_ISFCONNECTING; */
3b46e624 481
f0cbd3ec
FB
482 /*
483 * Continue tcp_input
484 */
485 tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
486 /* continue; */
487 } else
488 ret = sowrite(so);
489 /*
5fafdf24 490 * XXXXX If we wrote something (a lot), there
f0cbd3ec
FB
491 * could be a need for a window update.
492 * In the worst case, the remote will send
493 * a window probe to get things going again
494 */
495 }
3b46e624 496
f0cbd3ec
FB
497 /*
498 * Probe a still-connecting, non-blocking socket
499 * to check if it's still alive
500 */
501#ifdef PROBE_CONN
502 if (so->so_state & SS_ISFCONNECTING) {
02d2c54c 503 ret = recv(so->s, (char *)&ret, 0,0);
3b46e624 504
f0cbd3ec
FB
505 if (ret < 0) {
506 /* XXX */
507 if (errno == EAGAIN || errno == EWOULDBLOCK ||
508 errno == EINPROGRESS || errno == ENOTCONN)
509 continue; /* Still connecting, continue */
3b46e624 510
f0cbd3ec
FB
511 /* else failed */
512 so->so_state = SS_NOFDREF;
3b46e624 513
f0cbd3ec
FB
514 /* tcp_input will take care of it */
515 } else {
02d2c54c 516 ret = send(so->s, &ret, 0,0);
f0cbd3ec
FB
517 if (ret < 0) {
518 /* XXX */
519 if (errno == EAGAIN || errno == EWOULDBLOCK ||
520 errno == EINPROGRESS || errno == ENOTCONN)
521 continue;
522 /* else failed */
523 so->so_state = SS_NOFDREF;
524 } else
525 so->so_state &= ~SS_ISFCONNECTING;
3b46e624 526
f0cbd3ec
FB
527 }
528 tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
529 } /* SS_ISFCONNECTING */
530#endif
531 }
3b46e624 532
f0cbd3ec
FB
533 /*
534 * Now UDP sockets.
535 * Incoming packets are sent straight away, they're not buffered.
536 * Incoming UDP data isn't buffered either.
537 */
538 for (so = udb.so_next; so != &udb; so = so_next) {
539 so_next = so->so_next;
3b46e624 540
f0cbd3ec
FB
541 if (so->s != -1 && FD_ISSET(so->s, readfds)) {
542 sorecvfrom(so);
543 }
544 }
545 }
5fafdf24 546
f0cbd3ec
FB
547 /*
548 * See if we can start outputting
549 */
550 if (if_queued && link_up)
551 if_start();
02d2c54c
FB
552
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.
557 */
558 global_readfds = NULL;
559 global_writefds = NULL;
560 global_xfds = NULL;
f0cbd3ec
FB
561}
562
563#define ETH_ALEN 6
564#define ETH_HLEN 14
565
566#define ETH_P_IP 0x0800 /* Internet Protocol packet */
567#define ETH_P_ARP 0x0806 /* Address Resolution packet */
568
569#define ARPOP_REQUEST 1 /* ARP request */
570#define ARPOP_REPLY 2 /* ARP reply */
571
5fafdf24 572struct ethhdr
f0cbd3ec
FB
573{
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 */
577};
578
579struct arphdr
580{
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) */
586
587 /*
588 * Ethernet looks like this : This bit is variable sized however...
589 */
590 unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
591 unsigned char ar_sip[4]; /* sender IP address */
592 unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
593 unsigned char ar_tip[4]; /* target IP address */
594};
595
8fcd3692 596static void arp_input(const uint8_t *pkt, int pkt_len)
f0cbd3ec
FB
597{
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;
a3d4af03 604 struct ex_list *ex_ptr;
f0cbd3ec
FB
605
606 ar_op = ntohs(ah->ar_op);
607 switch(ar_op) {
608 case ARPOP_REQUEST:
a3d4af03 609 if (!memcmp(ah->ar_tip, &special_addr, 3)) {
5fafdf24 610 if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
a3d4af03
FB
611 goto arp_ok;
612 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
613 if (ex_ptr->ex_addr == ah->ar_tip[3])
614 goto arp_ok;
615 }
616 return;
617 arp_ok:
f0cbd3ec
FB
618 /* XXX: make an ARP request to have the client address */
619 memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
620
621 /* ARP request for alias/dns mac address */
622 memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
623 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
624 reh->h_source[5] = ah->ar_tip[3];
625 reh->h_proto = htons(ETH_P_ARP);
626
627 rah->ar_hrd = htons(1);
628 rah->ar_pro = htons(ETH_P_IP);
629 rah->ar_hln = ETH_ALEN;
630 rah->ar_pln = 4;
631 rah->ar_op = htons(ARPOP_REPLY);
632 memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
633 memcpy(rah->ar_sip, ah->ar_tip, 4);
634 memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
635 memcpy(rah->ar_tip, ah->ar_sip, 4);
636 slirp_output(arp_reply, sizeof(arp_reply));
637 }
638 break;
de806f07
FB
639 case ARPOP_REPLY:
640 /* reply to request of client mac address ? */
641 if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) &&
642 !memcmp(ah->ar_sip, &client_ipaddr.s_addr, 4)) {
643 memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN);
644 }
645 break;
f0cbd3ec
FB
646 default:
647 break;
648 }
649}
650
651void slirp_input(const uint8_t *pkt, int pkt_len)
652{
653 struct mbuf *m;
654 int proto;
655
656 if (pkt_len < ETH_HLEN)
657 return;
3b46e624 658
f0cbd3ec
FB
659 proto = ntohs(*(uint16_t *)(pkt + 12));
660 switch(proto) {
661 case ETH_P_ARP:
662 arp_input(pkt, pkt_len);
663 break;
664 case ETH_P_IP:
665 m = m_get();
666 if (!m)
667 return;
38f3e7c2 668 /* Note: we add to align the IP header */
e8e880a7
AJ
669 if (M_FREEROOM(m) < pkt_len + 2) {
670 m_inc(m, pkt_len + 2);
671 }
38f3e7c2
FB
672 m->m_len = pkt_len + 2;
673 memcpy(m->m_data + 2, pkt, pkt_len);
f0cbd3ec 674
38f3e7c2
FB
675 m->m_data += 2 + ETH_HLEN;
676 m->m_len -= 2 + ETH_HLEN;
f0cbd3ec
FB
677
678 ip_input(m);
679 break;
680 default:
681 break;
682 }
683}
684
685/* output the IP packet to the ethernet device */
686void if_encap(const uint8_t *ip_data, int ip_data_len)
687{
688 uint8_t buf[1600];
689 struct ethhdr *eh = (struct ethhdr *)buf;
690
691 if (ip_data_len + ETH_HLEN > sizeof(buf))
692 return;
de806f07
FB
693
694 if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN)) {
695 uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
696 struct ethhdr *reh = (struct ethhdr *)arp_req;
697 struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
698 const struct ip *iph = (const struct ip *)ip_data;
699
700 /* If the client addr is not known, there is no point in
701 sending the packet to it. Normally the sender should have
702 done an ARP request to get its MAC address. Here we do it
703 in place of sending the packet and we hope that the sender
704 will retry sending its packet. */
705 memset(reh->h_dest, 0xff, ETH_ALEN);
706 memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
707 reh->h_source[5] = CTL_ALIAS;
708 reh->h_proto = htons(ETH_P_ARP);
709 rah->ar_hrd = htons(1);
710 rah->ar_pro = htons(ETH_P_IP);
711 rah->ar_hln = ETH_ALEN;
712 rah->ar_pln = 4;
713 rah->ar_op = htons(ARPOP_REQUEST);
714 /* source hw addr */
715 memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 1);
716 rah->ar_sha[5] = CTL_ALIAS;
717 /* source IP */
718 memcpy(rah->ar_sip, &alias_addr, 4);
719 /* target hw addr (none) */
720 memset(rah->ar_tha, 0, ETH_ALEN);
721 /* target IP */
722 memcpy(rah->ar_tip, &iph->ip_dst, 4);
723 client_ipaddr = iph->ip_dst;
724 slirp_output(arp_req, sizeof(arp_req));
725 } else {
726 memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
727 memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
728 /* XXX: not correct */
729 eh->h_source[5] = CTL_ALIAS;
730 eh->h_proto = htons(ETH_P_IP);
731 memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
732 slirp_output(buf, ip_data_len + ETH_HLEN);
733 }
f0cbd3ec 734}
9bf05444 735
5fafdf24 736int slirp_redir(int is_udp, int host_port,
9bf05444
FB
737 struct in_addr guest_addr, int guest_port)
738{
739 if (is_udp) {
5fafdf24 740 if (!udp_listen(htons(host_port), guest_addr.s_addr,
9bf05444
FB
741 htons(guest_port), 0))
742 return -1;
743 } else {
5fafdf24 744 if (!solisten(htons(host_port), guest_addr.s_addr,
9bf05444
FB
745 htons(guest_port), 0))
746 return -1;
747 }
748 return 0;
749}
a3d4af03 750
e1c5a2b3 751int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
a3d4af03
FB
752 int guest_port)
753{
5fafdf24 754 return add_exec(&exec_list, do_pty, (char *)args,
a3d4af03
FB
755 addr_low_byte, htons(guest_port));
756}
e1c5a2b3
AL
757
758ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
759{
760 if (so->s == -1 && so->extra) {
761 qemu_chr_write(so->extra, buf, len);
762 return len;
763 }
764
765 return send(so->s, buf, len, flags);
766}
767
768static struct socket *slirp_find_ctl_socket(int addr_low_byte, int guest_port)
769{
770 struct socket *so;
771
772 for (so = tcb.so_next; so != &tcb; so = so->so_next) {
773 if ((so->so_faddr.s_addr & htonl(0xffffff00)) ==
774 special_addr.s_addr
775 && (ntohl(so->so_faddr.s_addr) & 0xff) ==
776 addr_low_byte
777 && htons(so->so_fport) == guest_port)
778 return so;
779 }
780
781 return NULL;
782}
783
784size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
785{
786 struct iovec iov[2];
787 struct socket *so;
788
789 if (!link_up)
790 return 0;
791
792 so = slirp_find_ctl_socket(addr_low_byte, guest_port);
793
794 if (!so || so->so_state & SS_NOFDREF)
795 return 0;
796
797 if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
798 return 0;
799
800 return sopreprbuf(so, iov, NULL);
801}
802
803void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
804 int size)
805{
806 int ret;
807 struct socket *so = slirp_find_ctl_socket(addr_low_byte, guest_port);
808
809 if (!so)
810 return;
811
812 ret = soreadbuf(so, buf, size);
813
814 if (ret > 0)
815 tcp_output(sototcpcb(so));
816}
062e5527
AL
817
818static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
819{
820 int i;
821
822 qemu_put_sbe16(f, tp->t_state);
823 for (i = 0; i < TCPT_NTIMERS; i++)
824 qemu_put_sbe16(f, tp->t_timer[i]);
825 qemu_put_sbe16(f, tp->t_rxtshift);
826 qemu_put_sbe16(f, tp->t_rxtcur);
827 qemu_put_sbe16(f, tp->t_dupacks);
828 qemu_put_be16(f, tp->t_maxseg);
829 qemu_put_sbyte(f, tp->t_force);
830 qemu_put_be16(f, tp->t_flags);
831 qemu_put_be32(f, tp->snd_una);
832 qemu_put_be32(f, tp->snd_nxt);
833 qemu_put_be32(f, tp->snd_up);
834 qemu_put_be32(f, tp->snd_wl1);
835 qemu_put_be32(f, tp->snd_wl2);
836 qemu_put_be32(f, tp->iss);
837 qemu_put_be32(f, tp->snd_wnd);
838 qemu_put_be32(f, tp->rcv_wnd);
839 qemu_put_be32(f, tp->rcv_nxt);
840 qemu_put_be32(f, tp->rcv_up);
841 qemu_put_be32(f, tp->irs);
842 qemu_put_be32(f, tp->rcv_adv);
843 qemu_put_be32(f, tp->snd_max);
844 qemu_put_be32(f, tp->snd_cwnd);
845 qemu_put_be32(f, tp->snd_ssthresh);
846 qemu_put_sbe16(f, tp->t_idle);
847 qemu_put_sbe16(f, tp->t_rtt);
848 qemu_put_be32(f, tp->t_rtseq);
849 qemu_put_sbe16(f, tp->t_srtt);
850 qemu_put_sbe16(f, tp->t_rttvar);
851 qemu_put_be16(f, tp->t_rttmin);
852 qemu_put_be32(f, tp->max_sndwnd);
853 qemu_put_byte(f, tp->t_oobflags);
854 qemu_put_byte(f, tp->t_iobc);
855 qemu_put_sbe16(f, tp->t_softerror);
856 qemu_put_byte(f, tp->snd_scale);
857 qemu_put_byte(f, tp->rcv_scale);
858 qemu_put_byte(f, tp->request_r_scale);
859 qemu_put_byte(f, tp->requested_s_scale);
860 qemu_put_be32(f, tp->ts_recent);
861 qemu_put_be32(f, tp->ts_recent_age);
862 qemu_put_be32(f, tp->last_ack_sent);
863}
864
865static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
866{
867 uint32_t off;
868
869 qemu_put_be32(f, sbuf->sb_cc);
870 qemu_put_be32(f, sbuf->sb_datalen);
871 off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
872 qemu_put_sbe32(f, off);
873 off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
874 qemu_put_sbe32(f, off);
875 qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
876}
877
878static void slirp_socket_save(QEMUFile *f, struct socket *so)
879{
880 qemu_put_be32(f, so->so_urgc);
881 qemu_put_be32(f, so->so_faddr.s_addr);
882 qemu_put_be32(f, so->so_laddr.s_addr);
883 qemu_put_be16(f, so->so_fport);
884 qemu_put_be16(f, so->so_lport);
885 qemu_put_byte(f, so->so_iptos);
886 qemu_put_byte(f, so->so_emu);
887 qemu_put_byte(f, so->so_type);
888 qemu_put_be32(f, so->so_state);
889 slirp_sbuf_save(f, &so->so_rcv);
890 slirp_sbuf_save(f, &so->so_snd);
891 slirp_tcp_save(f, so->so_tcpcb);
892}
893
894static void slirp_state_save(QEMUFile *f, void *opaque)
895{
896 struct ex_list *ex_ptr;
897
898 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
899 if (ex_ptr->ex_pty == 3) {
900 struct socket *so;
901 so = slirp_find_ctl_socket(ex_ptr->ex_addr, ntohs(ex_ptr->ex_fport));
902 if (!so)
903 continue;
904
905 qemu_put_byte(f, 42);
906 slirp_socket_save(f, so);
907 }
908 qemu_put_byte(f, 0);
909}
910
911static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
912{
913 int i;
914
915 tp->t_state = qemu_get_sbe16(f);
916 for (i = 0; i < TCPT_NTIMERS; i++)
917 tp->t_timer[i] = qemu_get_sbe16(f);
918 tp->t_rxtshift = qemu_get_sbe16(f);
919 tp->t_rxtcur = qemu_get_sbe16(f);
920 tp->t_dupacks = qemu_get_sbe16(f);
921 tp->t_maxseg = qemu_get_be16(f);
922 tp->t_force = qemu_get_sbyte(f);
923 tp->t_flags = qemu_get_be16(f);
924 tp->snd_una = qemu_get_be32(f);
925 tp->snd_nxt = qemu_get_be32(f);
926 tp->snd_up = qemu_get_be32(f);
927 tp->snd_wl1 = qemu_get_be32(f);
928 tp->snd_wl2 = qemu_get_be32(f);
929 tp->iss = qemu_get_be32(f);
930 tp->snd_wnd = qemu_get_be32(f);
931 tp->rcv_wnd = qemu_get_be32(f);
932 tp->rcv_nxt = qemu_get_be32(f);
933 tp->rcv_up = qemu_get_be32(f);
934 tp->irs = qemu_get_be32(f);
935 tp->rcv_adv = qemu_get_be32(f);
936 tp->snd_max = qemu_get_be32(f);
937 tp->snd_cwnd = qemu_get_be32(f);
938 tp->snd_ssthresh = qemu_get_be32(f);
939 tp->t_idle = qemu_get_sbe16(f);
940 tp->t_rtt = qemu_get_sbe16(f);
941 tp->t_rtseq = qemu_get_be32(f);
942 tp->t_srtt = qemu_get_sbe16(f);
943 tp->t_rttvar = qemu_get_sbe16(f);
944 tp->t_rttmin = qemu_get_be16(f);
945 tp->max_sndwnd = qemu_get_be32(f);
946 tp->t_oobflags = qemu_get_byte(f);
947 tp->t_iobc = qemu_get_byte(f);
948 tp->t_softerror = qemu_get_sbe16(f);
949 tp->snd_scale = qemu_get_byte(f);
950 tp->rcv_scale = qemu_get_byte(f);
951 tp->request_r_scale = qemu_get_byte(f);
952 tp->requested_s_scale = qemu_get_byte(f);
953 tp->ts_recent = qemu_get_be32(f);
954 tp->ts_recent_age = qemu_get_be32(f);
955 tp->last_ack_sent = qemu_get_be32(f);
956 tcp_template(tp);
957}
958
959static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
960{
961 uint32_t off, sb_cc, sb_datalen;
962
963 sb_cc = qemu_get_be32(f);
964 sb_datalen = qemu_get_be32(f);
965
966 sbreserve(sbuf, sb_datalen);
967
968 if (sbuf->sb_datalen != sb_datalen)
969 return -ENOMEM;
970
971 sbuf->sb_cc = sb_cc;
972
973 off = qemu_get_sbe32(f);
974 sbuf->sb_wptr = sbuf->sb_data + off;
975 off = qemu_get_sbe32(f);
976 sbuf->sb_rptr = sbuf->sb_data + off;
977 qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
978
979 return 0;
980}
981
982static int slirp_socket_load(QEMUFile *f, struct socket *so)
983{
984 if (tcp_attach(so) < 0)
985 return -ENOMEM;
986
987 so->so_urgc = qemu_get_be32(f);
988 so->so_faddr.s_addr = qemu_get_be32(f);
989 so->so_laddr.s_addr = qemu_get_be32(f);
990 so->so_fport = qemu_get_be16(f);
991 so->so_lport = qemu_get_be16(f);
992 so->so_iptos = qemu_get_byte(f);
993 so->so_emu = qemu_get_byte(f);
994 so->so_type = qemu_get_byte(f);
995 so->so_state = qemu_get_be32(f);
996 if (slirp_sbuf_load(f, &so->so_rcv) < 0)
997 return -ENOMEM;
998 if (slirp_sbuf_load(f, &so->so_snd) < 0)
999 return -ENOMEM;
1000 slirp_tcp_load(f, so->so_tcpcb);
1001
1002 return 0;
1003}
1004
1005static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
1006{
1007 struct ex_list *ex_ptr;
1008 int r;
1009
1010 while ((r = qemu_get_byte(f))) {
1011 int ret;
1012 struct socket *so = socreate();
1013
1014 if (!so)
1015 return -ENOMEM;
1016
1017 ret = slirp_socket_load(f, so);
1018
1019 if (ret < 0)
1020 return ret;
1021
1022 if ((so->so_faddr.s_addr & htonl(0xffffff00)) != special_addr.s_addr)
1023 return -EINVAL;
1024
1025 for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
1026 if (ex_ptr->ex_pty == 3 &&
1027 (ntohl(so->so_faddr.s_addr) & 0xff) == ex_ptr->ex_addr &&
1028 so->so_fport == ex_ptr->ex_fport)
1029 break;
1030
1031 if (!ex_ptr)
1032 return -EINVAL;
1033
1034 so->extra = ex_ptr->ex_exec;
1035 }
1036
1037 return 0;
1038}