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