slirp.c 28.9 KB
Newer Older
B
bellard 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * libslirp glue
 *
 * Copyright (c) 2004-2008 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
24
#include "qemu-common.h"
B
blueswir1 已提交
25
#include "qemu-char.h"
B
bellard 已提交
26
#include "slirp.h"
27
#include "hw/hw.h"
B
bellard 已提交
28 29 30 31 32 33 34 35

/* host address */
struct in_addr our_addr;
/* host dns address */
struct in_addr dns_addr;
/* host loopback address */
struct in_addr loopback_addr;

36 37 38 39 40 41 42 43
/* virtual network configuration */
struct in_addr vnetwork_addr;
struct in_addr vnetwork_mask;
struct in_addr vhost_addr;
struct in_addr vdhcp_startaddr;
struct in_addr vnameserver_addr;

/* 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
B
bellard 已提交
46 47
};

48
/* ARP cache for the guest IP addresses (XXX: allow many entries) */
B
bellard 已提交
49
uint8_t client_ethaddr[6];
50 51 52
static struct in_addr client_ipaddr;

static const uint8_t zero_ethaddr[6] = { 0, 0, 0, 0, 0, 0 };
B
bellard 已提交
53

54
int slirp_restrict;
B
bellard 已提交
55
int link_up;
B
bellard 已提交
56
struct ex_list *exec_list;
B
bellard 已提交
57 58 59 60

/* XXX: suppress those select globals */
fd_set *global_readfds, *global_writefds, *global_xfds;

61 62 63 64
u_int curtime;
static u_int time_fasttimo, last_slowtimo;
static int do_slowtimo;

B
bellard 已提交
65
char slirp_hostname[33];
P
pbrook 已提交
66

B
bellard 已提交
67 68 69 70
#ifdef _WIN32

static int get_dns_addr(struct in_addr *pdns_addr)
{
B
bellard 已提交
71 72 73 74 75
    FIXED_INFO *FixedInfo=NULL;
    ULONG    BufLen;
    DWORD    ret;
    IP_ADDR_STRING *pIPAddr;
    struct in_addr tmp_addr;
76

B
bellard 已提交
77 78
    FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
    BufLen = sizeof(FIXED_INFO);
79

B
bellard 已提交
80 81 82 83 84 85 86
    if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
        if (FixedInfo) {
            GlobalFree(FixedInfo);
            FixedInfo = NULL;
        }
        FixedInfo = GlobalAlloc(GPTR, BufLen);
    }
87

B
bellard 已提交
88 89 90 91 92 93 94 95
    if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
        printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
        if (FixedInfo) {
            GlobalFree(FixedInfo);
            FixedInfo = NULL;
        }
        return -1;
    }
96

B
bellard 已提交
97 98 99 100 101 102 103 104
    pIPAddr = &(FixedInfo->DnsServerList);
    inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
    *pdns_addr = tmp_addr;
    if (FixedInfo) {
        GlobalFree(FixedInfo);
        FixedInfo = NULL;
    }
    return 0;
B
bellard 已提交
105 106
}

107 108 109 110 111
static void winsock_cleanup(void)
{
    WSACleanup();
}

B
bellard 已提交
112 113 114 115 116
#else

static int get_dns_addr(struct in_addr *pdns_addr)
{
    char buff[512];
B
blueswir1 已提交
117
    char buff2[257];
B
bellard 已提交
118 119 120
    FILE *f;
    int found = 0;
    struct in_addr tmp_addr;
121

B
bellard 已提交
122 123 124 125
    f = fopen("/etc/resolv.conf", "r");
    if (!f)
        return -1;

126
#ifdef DEBUG
B
bellard 已提交
127
    lprint("IP address of your DNS(s): ");
128
#endif
B
bellard 已提交
129 130 131 132 133 134 135 136 137
    while (fgets(buff, 512, f) != NULL) {
        if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
            if (!inet_aton(buff2, &tmp_addr))
                continue;
            if (tmp_addr.s_addr == loopback_addr.s_addr)
                tmp_addr = our_addr;
            /* If it's the first one, set it to dns_addr */
            if (!found)
                *pdns_addr = tmp_addr;
138
#ifdef DEBUG
B
bellard 已提交
139 140
            else
                lprint(", ");
141
#endif
B
bellard 已提交
142
            if (++found > 3) {
143
#ifdef DEBUG
B
bellard 已提交
144
                lprint("(more)");
145
#endif
B
bellard 已提交
146
                break;
147 148 149
            }
#ifdef DEBUG
            else
B
bellard 已提交
150
                lprint("%s", inet_ntoa(tmp_addr));
151
#endif
B
bellard 已提交
152 153
        }
    }
B
bellard 已提交
154
    fclose(f);
B
bellard 已提交
155 156 157 158 159 160 161
    if (!found)
        return -1;
    return 0;
}

#endif

162
static void slirp_init_once(void)
B
bellard 已提交
163
{
164 165 166 167 168
    static int initialized;
    struct hostent *he;
    char our_name[256];
#ifdef _WIN32
    WSADATA Data;
B
bellard 已提交
169 170
#endif

171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
    if (initialized) {
        return;
    }
    initialized = 1;

#ifdef _WIN32
    WSAStartup(MAKEWORD(2,0), &Data);
    atexit(winsock_cleanup);
#endif

    loopback_addr.s_addr = htonl(INADDR_LOOPBACK);

    /* FIXME: This address may change during runtime */
    if (gethostname(our_name, sizeof(our_name)) == 0) {
        he = gethostbyname(our_name);
        if (he) {
            our_addr = *(struct in_addr *)he->h_addr;
        }
    }
    if (our_addr.s_addr == 0) {
        our_addr = loopback_addr;
    }

    /* FIXME: This address may change during runtime */
    if (get_dns_addr(&dns_addr) < 0) {
        dns_addr = loopback_addr;
    }
}

200 201 202
static void slirp_state_save(QEMUFile *f, void *opaque);
static int slirp_state_load(QEMUFile *f, void *opaque, int version_id);

203 204 205 206 207
void slirp_init(int restricted, struct in_addr vnetwork,
                struct in_addr vnetmask, struct in_addr vhost,
                const char *vhostname, const char *tftp_path,
                const char *bootfile, struct in_addr vdhcp_start,
                struct in_addr vnameserver)
B
bellard 已提交
208
{
209
    slirp_init_once();
B
bellard 已提交
210

B
bellard 已提交
211
    link_up = 1;
212
    slirp_restrict = restricted;
B
bellard 已提交
213 214 215 216 217 218 219

    if_init();
    ip_init();

    /* Initialise mbufs *after* setting the MTU */
    m_init();

220 221 222 223 224
    vnetwork_addr = vnetwork;
    vnetwork_mask = vnetmask;
    vhost_addr = vhost;
    if (vhostname) {
        pstrcpy(slirp_hostname, sizeof(slirp_hostname), vhostname);
225
    }
226 227 228 229 230 231 232 233 234 235
    qemu_free(tftp_prefix);
    tftp_prefix = NULL;
    if (tftp_path) {
        tftp_prefix = qemu_strdup(tftp_path);
    }
    qemu_free(bootp_filename);
    bootp_filename = NULL;
    if (bootfile) {
        bootp_filename = qemu_strdup(bootfile);
    }
236 237
    vdhcp_startaddr = vdhcp_start;
    vnameserver_addr = vnameserver;
238

J
Jan Kiszka 已提交
239
    register_savevm("slirp", 0, 2, slirp_state_save, slirp_state_load, NULL);
B
bellard 已提交
240 241 242 243 244 245 246 247 248
}

#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)

/*
 * curtime kept to an accuracy of 1ms
 */
B
bellard 已提交
249 250 251 252 253 254
#ifdef _WIN32
static void updtime(void)
{
    struct _timeb tb;

    _ftime(&tb);
J
Jan Kiszka 已提交
255 256

    curtime = tb.time * 1000 + tb.millitm;
B
bellard 已提交
257 258
}
#else
B
bellard 已提交
259 260
static void updtime(void)
{
J
Jan Kiszka 已提交
261
    struct timeval tv;
262

J
Jan Kiszka 已提交
263
    gettimeofday(&tv, NULL);
264

J
Jan Kiszka 已提交
265
    curtime = tv.tv_sec * 1000 + tv.tv_usec / 1000;
B
bellard 已提交
266
}
B
bellard 已提交
267
#endif
B
bellard 已提交
268

269
void slirp_select_fill(int *pnfds,
B
bellard 已提交
270 271 272 273 274
                       fd_set *readfds, fd_set *writefds, fd_set *xfds)
{
    struct socket *so, *so_next;
    int nfds;

J
Jan Kiszka 已提交
275 276 277 278
    if (!link_up) {
        return;
    }

B
bellard 已提交
279 280 281 282
    /* fail safe */
    global_readfds = NULL;
    global_writefds = NULL;
    global_xfds = NULL;
283

B
bellard 已提交
284 285 286 287 288
    nfds = *pnfds;
	/*
	 * First, TCP sockets
	 */
	do_slowtimo = 0;
J
Jan Kiszka 已提交
289

290
		/*
B
bellard 已提交
291 292 293 294
		 * *_slowtimo needs calling if there are IP fragments
		 * in the fragment queue, or there are TCP connections active
		 */
		do_slowtimo = ((tcb.so_next != &tcb) ||
B
blueswir1 已提交
295
                (&ipq.ip_link != ipq.ip_link.next));
296

B
bellard 已提交
297 298
		for (so = tcb.so_next; so != &tcb; so = so_next) {
			so_next = so->so_next;
299

B
bellard 已提交
300 301 302 303 304
			/*
			 * See if we need a tcp_fasttimo
			 */
			if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
			   time_fasttimo = curtime; /* Flag when we want a fasttimo */
305

B
bellard 已提交
306 307 308 309 310 311
			/*
			 * NOFDREF can include still connecting to local-host,
			 * newly socreated() sockets etc. Don't want to select these.
	 		 */
			if (so->so_state & SS_NOFDREF || so->s == -1)
			   continue;
312

B
bellard 已提交
313 314 315 316 317 318 319 320
			/*
			 * Set for reading sockets which are accepting
			 */
			if (so->so_state & SS_FACCEPTCONN) {
                                FD_SET(so->s, readfds);
				UPD_NFDS(so->s);
				continue;
			}
321

B
bellard 已提交
322 323 324 325 326 327 328 329
			/*
			 * Set for writing sockets which are connecting
			 */
			if (so->so_state & SS_ISFCONNECTING) {
				FD_SET(so->s, writefds);
				UPD_NFDS(so->s);
				continue;
			}
330

B
bellard 已提交
331 332 333 334 335 336 337 338
			/*
			 * Set for writing if we are connected, can send more, and
			 * we have something to send
			 */
			if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
				FD_SET(so->s, writefds);
				UPD_NFDS(so->s);
			}
339

B
bellard 已提交
340 341 342 343 344 345 346 347 348 349
			/*
			 * Set for reading (and urgent data) if we are connected, can
			 * receive more, and we have room for it XXX /2 ?
			 */
			if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
				FD_SET(so->s, readfds);
				FD_SET(so->s, xfds);
				UPD_NFDS(so->s);
			}
		}
350

B
bellard 已提交
351 352 353 354 355
		/*
		 * UDP sockets
		 */
		for (so = udb.so_next; so != &udb; so = so_next) {
			so_next = so->so_next;
356

B
bellard 已提交
357 358 359 360 361 362 363 364 365 366
			/*
			 * See if it's timed out
			 */
			if (so->so_expire) {
				if (so->so_expire <= curtime) {
					udp_detach(so);
					continue;
				} else
					do_slowtimo = 1; /* Let socket expire */
			}
367

B
bellard 已提交
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
			/*
			 * When UDP packets are received from over the
			 * link, they're sendto()'d straight away, so
			 * no need for setting for writing
			 * Limit the number of packets queued by this session
			 * to 4.  Note that even though we try and limit this
			 * to 4 packets, the session could have more queued
			 * if the packets needed to be fragmented
			 * (XXX <= 4 ?)
			 */
			if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
				FD_SET(so->s, readfds);
				UPD_NFDS(so->s);
			}
		}
383

B
bellard 已提交
384
        *pnfds = nfds;
385
}
B
bellard 已提交
386

J
Jan Kiszka 已提交
387 388
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds,
                       int select_error)
B
bellard 已提交
389 390 391 392
{
    struct socket *so, *so_next;
    int ret;

J
Jan Kiszka 已提交
393 394 395 396
    if (!link_up) {
        return;
    }

B
bellard 已提交
397 398 399 400 401 402
    global_readfds = readfds;
    global_writefds = writefds;
    global_xfds = xfds;

	/* Update time */
	updtime();
403

B
bellard 已提交
404
	/*
405
	 * See if anything has timed out
B
bellard 已提交
406
	 */
B
bellard 已提交
407
		if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
B
bellard 已提交
408 409 410 411 412 413 414 415
			tcp_fasttimo();
			time_fasttimo = 0;
		}
		if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
			ip_slowtimo();
			tcp_slowtimo();
			last_slowtimo = curtime;
		}
416

B
bellard 已提交
417 418 419
	/*
	 * Check sockets
	 */
J
Jan Kiszka 已提交
420
	if (!select_error) {
B
bellard 已提交
421 422 423 424 425
		/*
		 * Check TCP sockets
		 */
		for (so = tcb.so_next; so != &tcb; so = so_next) {
			so_next = so->so_next;
426

B
bellard 已提交
427 428 429 430 431 432
			/*
			 * FD_ISSET is meaningless on these sockets
			 * (and they can crash the program)
			 */
			if (so->so_state & SS_NOFDREF || so->s == -1)
			   continue;
433

B
bellard 已提交
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
			/*
			 * Check for URG data
			 * This will soread as well, so no need to
			 * test for readfds below if this succeeds
			 */
			if (FD_ISSET(so->s, xfds))
			   sorecvoob(so);
			/*
			 * Check sockets for reading
			 */
			else if (FD_ISSET(so->s, readfds)) {
				/*
				 * Check for incoming connections
				 */
				if (so->so_state & SS_FACCEPTCONN) {
					tcp_connect(so);
					continue;
				} /* else */
				ret = soread(so);
453

B
bellard 已提交
454 455 456 457
				/* Output it if we read something */
				if (ret > 0)
				   tcp_output(sototcpcb(so));
			}
458

B
bellard 已提交
459 460 461 462 463 464 465 466 467 468
			/*
			 * Check sockets for writing
			 */
			if (FD_ISSET(so->s, writefds)) {
			  /*
			   * Check for non-blocking, still-connecting sockets
			   */
			  if (so->so_state & SS_ISFCONNECTING) {
			    /* Connected */
			    so->so_state &= ~SS_ISFCONNECTING;
469

470
			    ret = send(so->s, (const void *) &ret, 0, 0);
B
bellard 已提交
471 472 473 474 475
			    if (ret < 0) {
			      /* XXXXX Must fix, zero bytes is a NOP */
			      if (errno == EAGAIN || errno == EWOULDBLOCK ||
				  errno == EINPROGRESS || errno == ENOTCONN)
				continue;
476

B
bellard 已提交
477
			      /* else failed */
478 479
			      so->so_state &= SS_PERSISTENT_MASK;
			      so->so_state |= SS_NOFDREF;
B
bellard 已提交
480 481
			    }
			    /* else so->so_state &= ~SS_ISFCONNECTING; */
482

B
bellard 已提交
483 484 485 486 487 488 489 490
			    /*
			     * Continue tcp_input
			     */
			    tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
			    /* continue; */
			  } else
			    ret = sowrite(so);
			  /*
491
			   * XXXXX If we wrote something (a lot), there
B
bellard 已提交
492 493 494 495 496
			   * could be a need for a window update.
			   * In the worst case, the remote will send
			   * a window probe to get things going again
			   */
			}
497

B
bellard 已提交
498 499 500 501 502 503
			/*
			 * Probe a still-connecting, non-blocking socket
			 * to check if it's still alive
	 	 	 */
#ifdef PROBE_CONN
			if (so->so_state & SS_ISFCONNECTING) {
B
bellard 已提交
504
			  ret = recv(so->s, (char *)&ret, 0,0);
505

B
bellard 已提交
506 507 508 509 510
			  if (ret < 0) {
			    /* XXX */
			    if (errno == EAGAIN || errno == EWOULDBLOCK ||
				errno == EINPROGRESS || errno == ENOTCONN)
			      continue; /* Still connecting, continue */
511

B
bellard 已提交
512
			    /* else failed */
513 514
			    so->so_state &= SS_PERSISTENT_MASK;
			    so->so_state |= SS_NOFDREF;
515

B
bellard 已提交
516 517
			    /* tcp_input will take care of it */
			  } else {
B
bellard 已提交
518
			    ret = send(so->s, &ret, 0,0);
B
bellard 已提交
519 520 521 522 523 524
			    if (ret < 0) {
			      /* XXX */
			      if (errno == EAGAIN || errno == EWOULDBLOCK ||
				  errno == EINPROGRESS || errno == ENOTCONN)
				continue;
			      /* else failed */
525 526
			      so->so_state &= SS_PERSISTENT_MASK;
			      so->so_state |= SS_NOFDREF;
B
bellard 已提交
527 528
			    } else
			      so->so_state &= ~SS_ISFCONNECTING;
529

B
bellard 已提交
530 531 532 533 534
			  }
			  tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
			} /* SS_ISFCONNECTING */
#endif
		}
535

B
bellard 已提交
536 537 538 539 540 541 542
		/*
		 * Now UDP sockets.
		 * Incoming packets are sent straight away, they're not buffered.
		 * Incoming UDP data isn't buffered either.
		 */
		for (so = udb.so_next; so != &udb; so = so_next) {
			so_next = so->so_next;
543

B
bellard 已提交
544 545 546 547 548
			if (so->s != -1 && FD_ISSET(so->s, readfds)) {
                            sorecvfrom(so);
                        }
		}
	}
549

B
bellard 已提交
550 551 552
	/*
	 * See if we can start outputting
	 */
J
Jan Kiszka 已提交
553
	if (if_queued)
B
bellard 已提交
554
	   if_start();
B
bellard 已提交
555 556 557 558 559 560 561 562 563

	/* clear global file descriptor sets.
	 * these reside on the stack in vl.c
	 * so they're unusable if we're not in
	 * slirp_select_fill or slirp_select_poll.
	 */
	 global_readfds = NULL;
	 global_writefds = NULL;
	 global_xfds = NULL;
B
bellard 已提交
564 565 566 567 568 569 570 571 572 573 574
}

#define ETH_ALEN 6
#define ETH_HLEN 14

#define ETH_P_IP	0x0800		/* Internet Protocol packet	*/
#define ETH_P_ARP	0x0806		/* Address Resolution packet	*/

#define	ARPOP_REQUEST	1		/* ARP request			*/
#define	ARPOP_REPLY	2		/* ARP reply			*/

575
struct ethhdr
B
bellard 已提交
576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
{
	unsigned char	h_dest[ETH_ALEN];	/* destination eth addr	*/
	unsigned char	h_source[ETH_ALEN];	/* source ether addr	*/
	unsigned short	h_proto;		/* packet type ID field	*/
};

struct arphdr
{
	unsigned short	ar_hrd;		/* format of hardware address	*/
	unsigned short	ar_pro;		/* format of protocol address	*/
	unsigned char	ar_hln;		/* length of hardware address	*/
	unsigned char	ar_pln;		/* length of protocol address	*/
	unsigned short	ar_op;		/* ARP opcode (command)		*/

	 /*
	  *	 Ethernet looks like this : This bit is variable sized however...
	  */
	unsigned char		ar_sha[ETH_ALEN];	/* sender hardware address	*/
594
	uint32_t		ar_sip;			/* sender IP address		*/
B
bellard 已提交
595
	unsigned char		ar_tha[ETH_ALEN];	/* target hardware address	*/
596 597
	uint32_t		ar_tip	;		/* target IP address		*/
} __attribute__((packed));
B
bellard 已提交
598

599
static void arp_input(const uint8_t *pkt, int pkt_len)
B
bellard 已提交
600 601 602 603 604 605 606
{
    struct ethhdr *eh = (struct ethhdr *)pkt;
    struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
    uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
    struct ethhdr *reh = (struct ethhdr *)arp_reply;
    struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
    int ar_op;
B
bellard 已提交
607
    struct ex_list *ex_ptr;
B
bellard 已提交
608 609 610 611

    ar_op = ntohs(ah->ar_op);
    switch(ar_op) {
    case ARPOP_REQUEST:
612 613 614
        if ((ah->ar_tip & vnetwork_mask.s_addr) == vnetwork_addr.s_addr) {
            if (ah->ar_tip == vnameserver_addr.s_addr ||
                ah->ar_tip == vhost_addr.s_addr)
B
bellard 已提交
615 616
                goto arp_ok;
            for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
617
                if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
B
bellard 已提交
618 619 620 621
                    goto arp_ok;
            }
            return;
        arp_ok:
B
bellard 已提交
622 623 624 625 626
            /* XXX: make an ARP request to have the client address */
            memcpy(client_ethaddr, eh->h_source, ETH_ALEN);

            /* ARP request for alias/dns mac address */
            memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
627 628
            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
            memcpy(&reh->h_source[2], &ah->ar_tip, 4);
B
bellard 已提交
629 630 631 632 633 634 635 636
            reh->h_proto = htons(ETH_P_ARP);

            rah->ar_hrd = htons(1);
            rah->ar_pro = htons(ETH_P_IP);
            rah->ar_hln = ETH_ALEN;
            rah->ar_pln = 4;
            rah->ar_op = htons(ARPOP_REPLY);
            memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
637
            rah->ar_sip = ah->ar_tip;
B
bellard 已提交
638
            memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
639
            rah->ar_tip = ah->ar_sip;
B
bellard 已提交
640 641 642
            slirp_output(arp_reply, sizeof(arp_reply));
        }
        break;
643 644 645
    case ARPOP_REPLY:
        /* reply to request of client mac address ? */
        if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN) &&
646
            ah->ar_sip == client_ipaddr.s_addr) {
647 648 649
            memcpy(client_ethaddr, ah->ar_sha, ETH_ALEN);
        }
        break;
B
bellard 已提交
650 651 652 653 654 655 656 657 658 659 660 661
    default:
        break;
    }
}

void slirp_input(const uint8_t *pkt, int pkt_len)
{
    struct mbuf *m;
    int proto;

    if (pkt_len < ETH_HLEN)
        return;
662

B
bellard 已提交
663 664 665 666 667 668 669 670 671
    proto = ntohs(*(uint16_t *)(pkt + 12));
    switch(proto) {
    case ETH_P_ARP:
        arp_input(pkt, pkt_len);
        break;
    case ETH_P_IP:
        m = m_get();
        if (!m)
            return;
B
bellard 已提交
672
        /* Note: we add to align the IP header */
A
aurel32 已提交
673 674 675
        if (M_FREEROOM(m) < pkt_len + 2) {
            m_inc(m, pkt_len + 2);
        }
B
bellard 已提交
676 677
        m->m_len = pkt_len + 2;
        memcpy(m->m_data + 2, pkt, pkt_len);
B
bellard 已提交
678

B
bellard 已提交
679 680
        m->m_data += 2 + ETH_HLEN;
        m->m_len -= 2 + ETH_HLEN;
B
bellard 已提交
681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696

        ip_input(m);
        break;
    default:
        break;
    }
}

/* output the IP packet to the ethernet device */
void if_encap(const uint8_t *ip_data, int ip_data_len)
{
    uint8_t buf[1600];
    struct ethhdr *eh = (struct ethhdr *)buf;

    if (ip_data_len + ETH_HLEN > sizeof(buf))
        return;
697 698 699 700 701 702 703 704 705 706 707 708 709
    
    if (!memcmp(client_ethaddr, zero_ethaddr, ETH_ALEN)) {
        uint8_t arp_req[ETH_HLEN + sizeof(struct arphdr)];
        struct ethhdr *reh = (struct ethhdr *)arp_req;
        struct arphdr *rah = (struct arphdr *)(arp_req + ETH_HLEN);
        const struct ip *iph = (const struct ip *)ip_data;

        /* If the client addr is not known, there is no point in
           sending the packet to it. Normally the sender should have
           done an ARP request to get its MAC address. Here we do it
           in place of sending the packet and we hope that the sender
           will retry sending its packet. */
        memset(reh->h_dest, 0xff, ETH_ALEN);
710 711
        memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
        memcpy(&reh->h_source[2], &vhost_addr, 4);
712 713 714 715 716 717 718
        reh->h_proto = htons(ETH_P_ARP);
        rah->ar_hrd = htons(1);
        rah->ar_pro = htons(ETH_P_IP);
        rah->ar_hln = ETH_ALEN;
        rah->ar_pln = 4;
        rah->ar_op = htons(ARPOP_REQUEST);
        /* source hw addr */
719 720
        memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
        memcpy(&rah->ar_sha[2], &vhost_addr, 4);
721
        /* source IP */
722
        rah->ar_sip = vhost_addr.s_addr;
723 724 725
        /* target hw addr (none) */
        memset(rah->ar_tha, 0, ETH_ALEN);
        /* target IP */
726
        rah->ar_tip = iph->ip_dst.s_addr;
727 728 729 730
        client_ipaddr = iph->ip_dst;
        slirp_output(arp_req, sizeof(arp_req));
    } else {
        memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
731
        memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
732
        /* XXX: not correct */
733
        memcpy(&eh->h_source[2], &vhost_addr, 4);
734 735 736 737
        eh->h_proto = htons(ETH_P_IP);
        memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
        slirp_output(buf, ip_data_len + ETH_HLEN);
    }
B
bellard 已提交
738
}
B
bellard 已提交
739

740
/* Drop host forwarding rule, return 0 if found. */
741
int slirp_remove_hostfwd(int is_udp, struct in_addr host_addr, int host_port)
742 743 744
{
    struct socket *so;
    struct socket *head = (is_udp ? &udb : &tcb);
745 746 747
    struct sockaddr_in addr;
    int port = htons(host_port);
    socklen_t addr_len;
748 749

    for (so = head->so_next; so != head; so = so->so_next) {
750
        addr_len = sizeof(addr);
751 752
        if ((so->so_state & SS_HOSTFWD) &&
            getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
753
            addr.sin_addr.s_addr == host_addr.s_addr &&
754
            addr.sin_port == port) {
755 756
            close(so->s);
            sofree(so);
757
            return 0;
758 759 760
        }
    }

761
    return -1;
762 763
}

764
int slirp_add_hostfwd(int is_udp, struct in_addr host_addr, int host_port,
765
                      struct in_addr guest_addr, int guest_port)
B
bellard 已提交
766
{
767 768 769
    if (!guest_addr.s_addr) {
        guest_addr = vdhcp_startaddr;
    }
B
bellard 已提交
770
    if (is_udp) {
771
        if (!udp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
772
                        htons(guest_port), SS_HOSTFWD))
B
bellard 已提交
773 774
            return -1;
    } else {
775
        if (!tcp_listen(host_addr.s_addr, htons(host_port), guest_addr.s_addr,
776
                        htons(guest_port), SS_HOSTFWD))
B
bellard 已提交
777 778 779 780
            return -1;
    }
    return 0;
}
B
bellard 已提交
781

782 783
int slirp_add_exec(int do_pty, const void *args, struct in_addr guest_addr,
                   int guest_port)
B
bellard 已提交
784
{
785 786 787 788
    if (!guest_addr.s_addr) {
        guest_addr.s_addr =
            vnetwork_addr.s_addr | (htonl(0x0204) & ~vnetwork_mask.s_addr);
    }
789 790 791 792 793 794 795
    if ((guest_addr.s_addr & vnetwork_mask.s_addr) != vnetwork_addr.s_addr ||
        guest_addr.s_addr == vhost_addr.s_addr ||
        guest_addr.s_addr == vnameserver_addr.s_addr) {
        return -1;
    }
    return add_exec(&exec_list, do_pty, (char *)args, guest_addr,
                    htons(guest_port));
B
bellard 已提交
796
}
797 798 799 800 801 802 803 804 805 806 807

ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
{
	if (so->s == -1 && so->extra) {
		qemu_chr_write(so->extra, buf, len);
		return len;
	}

	return send(so->s, buf, len, flags);
}

808 809
static struct socket *
slirp_find_ctl_socket(struct in_addr guest_addr, int guest_port)
810
{
811
    struct socket *so;
812

813 814 815 816 817 818 819
    for (so = tcb.so_next; so != &tcb; so = so->so_next) {
        if (so->so_faddr.s_addr == guest_addr.s_addr &&
            htons(so->so_fport) == guest_port) {
            return so;
        }
    }
    return NULL;
820 821
}

822
size_t slirp_socket_can_recv(struct in_addr guest_addr, int guest_port)
823 824 825 826 827 828 829
{
	struct iovec iov[2];
	struct socket *so;

    if (!link_up)
        return 0;

830
	so = slirp_find_ctl_socket(guest_addr, guest_port);
831 832 833 834 835 836 837 838 839 840

	if (!so || so->so_state & SS_NOFDREF)
		return 0;

	if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
		return 0;

	return sopreprbuf(so, iov, NULL);
}

841 842
void slirp_socket_recv(struct in_addr guest_addr, int guest_port,
                       const uint8_t *buf, int size)
843 844
{
    int ret;
845 846
    struct socket *so = slirp_find_ctl_socket(guest_addr, guest_port);

847 848 849
    if (!so)
        return;

B
blueswir1 已提交
850
    ret = soreadbuf(so, (const char *)buf, size);
851 852 853 854

    if (ret > 0)
        tcp_output(sototcpcb(so));
}
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946

static void slirp_tcp_save(QEMUFile *f, struct tcpcb *tp)
{
    int i;

    qemu_put_sbe16(f, tp->t_state);
    for (i = 0; i < TCPT_NTIMERS; i++)
        qemu_put_sbe16(f, tp->t_timer[i]);
    qemu_put_sbe16(f, tp->t_rxtshift);
    qemu_put_sbe16(f, tp->t_rxtcur);
    qemu_put_sbe16(f, tp->t_dupacks);
    qemu_put_be16(f, tp->t_maxseg);
    qemu_put_sbyte(f, tp->t_force);
    qemu_put_be16(f, tp->t_flags);
    qemu_put_be32(f, tp->snd_una);
    qemu_put_be32(f, tp->snd_nxt);
    qemu_put_be32(f, tp->snd_up);
    qemu_put_be32(f, tp->snd_wl1);
    qemu_put_be32(f, tp->snd_wl2);
    qemu_put_be32(f, tp->iss);
    qemu_put_be32(f, tp->snd_wnd);
    qemu_put_be32(f, tp->rcv_wnd);
    qemu_put_be32(f, tp->rcv_nxt);
    qemu_put_be32(f, tp->rcv_up);
    qemu_put_be32(f, tp->irs);
    qemu_put_be32(f, tp->rcv_adv);
    qemu_put_be32(f, tp->snd_max);
    qemu_put_be32(f, tp->snd_cwnd);
    qemu_put_be32(f, tp->snd_ssthresh);
    qemu_put_sbe16(f, tp->t_idle);
    qemu_put_sbe16(f, tp->t_rtt);
    qemu_put_be32(f, tp->t_rtseq);
    qemu_put_sbe16(f, tp->t_srtt);
    qemu_put_sbe16(f, tp->t_rttvar);
    qemu_put_be16(f, tp->t_rttmin);
    qemu_put_be32(f, tp->max_sndwnd);
    qemu_put_byte(f, tp->t_oobflags);
    qemu_put_byte(f, tp->t_iobc);
    qemu_put_sbe16(f, tp->t_softerror);
    qemu_put_byte(f, tp->snd_scale);
    qemu_put_byte(f, tp->rcv_scale);
    qemu_put_byte(f, tp->request_r_scale);
    qemu_put_byte(f, tp->requested_s_scale);
    qemu_put_be32(f, tp->ts_recent);
    qemu_put_be32(f, tp->ts_recent_age);
    qemu_put_be32(f, tp->last_ack_sent);
}

static void slirp_sbuf_save(QEMUFile *f, struct sbuf *sbuf)
{
    uint32_t off;

    qemu_put_be32(f, sbuf->sb_cc);
    qemu_put_be32(f, sbuf->sb_datalen);
    off = (uint32_t)(sbuf->sb_wptr - sbuf->sb_data);
    qemu_put_sbe32(f, off);
    off = (uint32_t)(sbuf->sb_rptr - sbuf->sb_data);
    qemu_put_sbe32(f, off);
    qemu_put_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);
}

static void slirp_socket_save(QEMUFile *f, struct socket *so)
{
    qemu_put_be32(f, so->so_urgc);
    qemu_put_be32(f, so->so_faddr.s_addr);
    qemu_put_be32(f, so->so_laddr.s_addr);
    qemu_put_be16(f, so->so_fport);
    qemu_put_be16(f, so->so_lport);
    qemu_put_byte(f, so->so_iptos);
    qemu_put_byte(f, so->so_emu);
    qemu_put_byte(f, so->so_type);
    qemu_put_be32(f, so->so_state);
    slirp_sbuf_save(f, &so->so_rcv);
    slirp_sbuf_save(f, &so->so_snd);
    slirp_tcp_save(f, so->so_tcpcb);
}

static void slirp_state_save(QEMUFile *f, void *opaque)
{
    struct ex_list *ex_ptr;

    for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
        if (ex_ptr->ex_pty == 3) {
            struct socket *so;
            so = slirp_find_ctl_socket(ex_ptr->ex_addr, ntohs(ex_ptr->ex_fport));
            if (!so)
                continue;

            qemu_put_byte(f, 42);
            slirp_socket_save(f, so);
        }
    qemu_put_byte(f, 0);
J
Jan Kiszka 已提交
947 948

    qemu_put_be16(f, ip_id);
949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061
}

static void slirp_tcp_load(QEMUFile *f, struct tcpcb *tp)
{
    int i;

    tp->t_state = qemu_get_sbe16(f);
    for (i = 0; i < TCPT_NTIMERS; i++)
        tp->t_timer[i] = qemu_get_sbe16(f);
    tp->t_rxtshift = qemu_get_sbe16(f);
    tp->t_rxtcur = qemu_get_sbe16(f);
    tp->t_dupacks = qemu_get_sbe16(f);
    tp->t_maxseg = qemu_get_be16(f);
    tp->t_force = qemu_get_sbyte(f);
    tp->t_flags = qemu_get_be16(f);
    tp->snd_una = qemu_get_be32(f);
    tp->snd_nxt = qemu_get_be32(f);
    tp->snd_up = qemu_get_be32(f);
    tp->snd_wl1 = qemu_get_be32(f);
    tp->snd_wl2 = qemu_get_be32(f);
    tp->iss = qemu_get_be32(f);
    tp->snd_wnd = qemu_get_be32(f);
    tp->rcv_wnd = qemu_get_be32(f);
    tp->rcv_nxt = qemu_get_be32(f);
    tp->rcv_up = qemu_get_be32(f);
    tp->irs = qemu_get_be32(f);
    tp->rcv_adv = qemu_get_be32(f);
    tp->snd_max = qemu_get_be32(f);
    tp->snd_cwnd = qemu_get_be32(f);
    tp->snd_ssthresh = qemu_get_be32(f);
    tp->t_idle = qemu_get_sbe16(f);
    tp->t_rtt = qemu_get_sbe16(f);
    tp->t_rtseq = qemu_get_be32(f);
    tp->t_srtt = qemu_get_sbe16(f);
    tp->t_rttvar = qemu_get_sbe16(f);
    tp->t_rttmin = qemu_get_be16(f);
    tp->max_sndwnd = qemu_get_be32(f);
    tp->t_oobflags = qemu_get_byte(f);
    tp->t_iobc = qemu_get_byte(f);
    tp->t_softerror = qemu_get_sbe16(f);
    tp->snd_scale = qemu_get_byte(f);
    tp->rcv_scale = qemu_get_byte(f);
    tp->request_r_scale = qemu_get_byte(f);
    tp->requested_s_scale = qemu_get_byte(f);
    tp->ts_recent = qemu_get_be32(f);
    tp->ts_recent_age = qemu_get_be32(f);
    tp->last_ack_sent = qemu_get_be32(f);
    tcp_template(tp);
}

static int slirp_sbuf_load(QEMUFile *f, struct sbuf *sbuf)
{
    uint32_t off, sb_cc, sb_datalen;

    sb_cc = qemu_get_be32(f);
    sb_datalen = qemu_get_be32(f);

    sbreserve(sbuf, sb_datalen);

    if (sbuf->sb_datalen != sb_datalen)
        return -ENOMEM;

    sbuf->sb_cc = sb_cc;

    off = qemu_get_sbe32(f);
    sbuf->sb_wptr = sbuf->sb_data + off;
    off = qemu_get_sbe32(f);
    sbuf->sb_rptr = sbuf->sb_data + off;
    qemu_get_buffer(f, (unsigned char*)sbuf->sb_data, sbuf->sb_datalen);

    return 0;
}

static int slirp_socket_load(QEMUFile *f, struct socket *so)
{
    if (tcp_attach(so) < 0)
        return -ENOMEM;

    so->so_urgc = qemu_get_be32(f);
    so->so_faddr.s_addr = qemu_get_be32(f);
    so->so_laddr.s_addr = qemu_get_be32(f);
    so->so_fport = qemu_get_be16(f);
    so->so_lport = qemu_get_be16(f);
    so->so_iptos = qemu_get_byte(f);
    so->so_emu = qemu_get_byte(f);
    so->so_type = qemu_get_byte(f);
    so->so_state = qemu_get_be32(f);
    if (slirp_sbuf_load(f, &so->so_rcv) < 0)
        return -ENOMEM;
    if (slirp_sbuf_load(f, &so->so_snd) < 0)
        return -ENOMEM;
    slirp_tcp_load(f, so->so_tcpcb);

    return 0;
}

static int slirp_state_load(QEMUFile *f, void *opaque, int version_id)
{
    struct ex_list *ex_ptr;
    int r;

    while ((r = qemu_get_byte(f))) {
        int ret;
        struct socket *so = socreate();

        if (!so)
            return -ENOMEM;

        ret = slirp_socket_load(f, so);

        if (ret < 0)
            return ret;

1062 1063
        if ((so->so_faddr.s_addr & vnetwork_mask.s_addr) !=
            vnetwork_addr.s_addr) {
1064
            return -EINVAL;
1065 1066
        }
        for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
1067
            if (ex_ptr->ex_pty == 3 &&
1068 1069
                so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
                so->so_fport == ex_ptr->ex_fport) {
1070
                break;
1071 1072
            }
        }
1073 1074 1075
        if (!ex_ptr)
            return -EINVAL;

B
blueswir1 已提交
1076
        so->extra = (void *)ex_ptr->ex_exec;
1077 1078
    }

J
Jan Kiszka 已提交
1079 1080 1081 1082
    if (version_id >= 2) {
        ip_id = qemu_get_be16(f);
    }

1083 1084
    return 0;
}