Revision 5fafdf24 slirp/slirp.c
b/slirp/slirp.c | ||
---|---|---|
12 | 12 |
/* virtual address alias for host */ |
13 | 13 |
struct in_addr alias_addr; |
14 | 14 |
|
15 |
const uint8_t special_ethaddr[6] = {
|
|
15 |
const uint8_t special_ethaddr[6] = { |
|
16 | 16 |
0x52, 0x54, 0x00, 0x12, 0x35, 0x00 |
17 | 17 |
}; |
18 | 18 |
|
... | ... | |
38 | 38 |
DWORD ret; |
39 | 39 |
IP_ADDR_STRING *pIPAddr; |
40 | 40 |
struct in_addr tmp_addr; |
41 |
|
|
41 |
|
|
42 | 42 |
FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO)); |
43 | 43 |
BufLen = sizeof(FIXED_INFO); |
44 |
|
|
44 |
|
|
45 | 45 |
if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) { |
46 | 46 |
if (FixedInfo) { |
47 | 47 |
GlobalFree(FixedInfo); |
... | ... | |
49 | 49 |
} |
50 | 50 |
FixedInfo = GlobalAlloc(GPTR, BufLen); |
51 | 51 |
} |
52 |
|
|
52 |
|
|
53 | 53 |
if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) { |
54 | 54 |
printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret ); |
55 | 55 |
if (FixedInfo) { |
... | ... | |
58 | 58 |
} |
59 | 59 |
return -1; |
60 | 60 |
} |
61 |
|
|
61 |
|
|
62 | 62 |
pIPAddr = &(FixedInfo->DnsServerList); |
63 | 63 |
inet_aton(pIPAddr->IpAddress.String, &tmp_addr); |
64 | 64 |
*pdns_addr = tmp_addr; |
65 | 65 |
#if 0 |
66 | 66 |
printf( "DNS Servers:\n" ); |
67 | 67 |
printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String ); |
68 |
|
|
68 |
|
|
69 | 69 |
pIPAddr = FixedInfo -> DnsServerList.Next; |
70 | 70 |
while ( pIPAddr ) { |
71 | 71 |
printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String ); |
... | ... | |
88 | 88 |
FILE *f; |
89 | 89 |
int found = 0; |
90 | 90 |
struct in_addr tmp_addr; |
91 |
|
|
91 |
|
|
92 | 92 |
f = fopen("/etc/resolv.conf", "r"); |
93 | 93 |
if (!f) |
94 | 94 |
return -1; |
... | ... | |
130 | 130 |
void slirp_init(void) |
131 | 131 |
{ |
132 | 132 |
// debug_init("/tmp/slirp.log", DEBUG_DEFAULT); |
133 |
|
|
133 |
|
|
134 | 134 |
#ifdef _WIN32 |
135 | 135 |
{ |
136 | 136 |
WSADATA Data; |
... | ... | |
180 | 180 |
static void updtime(void) |
181 | 181 |
{ |
182 | 182 |
gettimeofday(&tt, 0); |
183 |
|
|
183 |
|
|
184 | 184 |
curtime = (u_int)tt.tv_sec * (u_int)1000; |
185 | 185 |
curtime += (u_int)tt.tv_usec / (u_int)1000; |
186 |
|
|
186 |
|
|
187 | 187 |
if ((tt.tv_usec % 1000) >= 500) |
188 | 188 |
curtime++; |
189 | 189 |
} |
190 | 190 |
#endif |
191 | 191 |
|
192 |
void slirp_select_fill(int *pnfds,
|
|
192 |
void slirp_select_fill(int *pnfds, |
|
193 | 193 |
fd_set *readfds, fd_set *writefds, fd_set *xfds) |
194 | 194 |
{ |
195 | 195 |
struct socket *so, *so_next; |
... | ... | |
201 | 201 |
global_readfds = NULL; |
202 | 202 |
global_writefds = NULL; |
203 | 203 |
global_xfds = NULL; |
204 |
|
|
204 |
|
|
205 | 205 |
nfds = *pnfds; |
206 | 206 |
/* |
207 | 207 |
* First, TCP sockets |
208 | 208 |
*/ |
209 | 209 |
do_slowtimo = 0; |
210 | 210 |
if (link_up) { |
211 |
/*
|
|
211 |
/* |
|
212 | 212 |
* *_slowtimo needs calling if there are IP fragments |
213 | 213 |
* in the fragment queue, or there are TCP connections active |
214 | 214 |
*/ |
215 | 215 |
do_slowtimo = ((tcb.so_next != &tcb) || |
216 | 216 |
((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next)); |
217 |
|
|
217 |
|
|
218 | 218 |
for (so = tcb.so_next; so != &tcb; so = so_next) { |
219 | 219 |
so_next = so->so_next; |
220 |
|
|
220 |
|
|
221 | 221 |
/* |
222 | 222 |
* See if we need a tcp_fasttimo |
223 | 223 |
*/ |
224 | 224 |
if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) |
225 | 225 |
time_fasttimo = curtime; /* Flag when we want a fasttimo */ |
226 |
|
|
226 |
|
|
227 | 227 |
/* |
228 | 228 |
* NOFDREF can include still connecting to local-host, |
229 | 229 |
* newly socreated() sockets etc. Don't want to select these. |
230 | 230 |
*/ |
231 | 231 |
if (so->so_state & SS_NOFDREF || so->s == -1) |
232 | 232 |
continue; |
233 |
|
|
233 |
|
|
234 | 234 |
/* |
235 | 235 |
* Set for reading sockets which are accepting |
236 | 236 |
*/ |
... | ... | |
239 | 239 |
UPD_NFDS(so->s); |
240 | 240 |
continue; |
241 | 241 |
} |
242 |
|
|
242 |
|
|
243 | 243 |
/* |
244 | 244 |
* Set for writing sockets which are connecting |
245 | 245 |
*/ |
... | ... | |
248 | 248 |
UPD_NFDS(so->s); |
249 | 249 |
continue; |
250 | 250 |
} |
251 |
|
|
251 |
|
|
252 | 252 |
/* |
253 | 253 |
* Set for writing if we are connected, can send more, and |
254 | 254 |
* we have something to send |
... | ... | |
257 | 257 |
FD_SET(so->s, writefds); |
258 | 258 |
UPD_NFDS(so->s); |
259 | 259 |
} |
260 |
|
|
260 |
|
|
261 | 261 |
/* |
262 | 262 |
* Set for reading (and urgent data) if we are connected, can |
263 | 263 |
* receive more, and we have room for it XXX /2 ? |
... | ... | |
268 | 268 |
UPD_NFDS(so->s); |
269 | 269 |
} |
270 | 270 |
} |
271 |
|
|
271 |
|
|
272 | 272 |
/* |
273 | 273 |
* UDP sockets |
274 | 274 |
*/ |
275 | 275 |
for (so = udb.so_next; so != &udb; so = so_next) { |
276 | 276 |
so_next = so->so_next; |
277 |
|
|
277 |
|
|
278 | 278 |
/* |
279 | 279 |
* See if it's timed out |
280 | 280 |
*/ |
... | ... | |
285 | 285 |
} else |
286 | 286 |
do_slowtimo = 1; /* Let socket expire */ |
287 | 287 |
} |
288 |
|
|
288 |
|
|
289 | 289 |
/* |
290 | 290 |
* When UDP packets are received from over the |
291 | 291 |
* link, they're sendto()'d straight away, so |
... | ... | |
302 | 302 |
} |
303 | 303 |
} |
304 | 304 |
} |
305 |
|
|
305 |
|
|
306 | 306 |
/* |
307 | 307 |
* Setup timeout to use minimum CPU usage, especially when idle |
308 | 308 |
*/ |
309 |
|
|
310 |
/*
|
|
309 |
|
|
310 |
/* |
|
311 | 311 |
* First, see the timeout needed by *timo |
312 | 312 |
*/ |
313 | 313 |
timeout.tv_sec = 0; |
... | ... | |
324 | 324 |
timeout.tv_usec = 0; |
325 | 325 |
else if (timeout.tv_usec > 510000) |
326 | 326 |
timeout.tv_usec = 510000; |
327 |
|
|
327 |
|
|
328 | 328 |
/* Can only fasttimo if we also slowtimo */ |
329 | 329 |
if (time_fasttimo) { |
330 | 330 |
tmp_time = (200 - (curtime - time_fasttimo)) * 1000; |
331 | 331 |
if (tmp_time < 0) |
332 | 332 |
tmp_time = 0; |
333 |
|
|
333 |
|
|
334 | 334 |
/* Choose the smallest of the 2 */ |
335 | 335 |
if (tmp_time < timeout.tv_usec) |
336 | 336 |
timeout.tv_usec = (u_int)tmp_time; |
337 | 337 |
} |
338 | 338 |
} |
339 | 339 |
*pnfds = nfds; |
340 |
}
|
|
340 |
} |
|
341 | 341 |
|
342 | 342 |
void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds) |
343 | 343 |
{ |
... | ... | |
350 | 350 |
|
351 | 351 |
/* Update time */ |
352 | 352 |
updtime(); |
353 |
|
|
353 |
|
|
354 | 354 |
/* |
355 |
* See if anything has timed out
|
|
355 |
* See if anything has timed out |
|
356 | 356 |
*/ |
357 | 357 |
if (link_up) { |
358 | 358 |
if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) { |
... | ... | |
365 | 365 |
last_slowtimo = curtime; |
366 | 366 |
} |
367 | 367 |
} |
368 |
|
|
368 |
|
|
369 | 369 |
/* |
370 | 370 |
* Check sockets |
371 | 371 |
*/ |
... | ... | |
375 | 375 |
*/ |
376 | 376 |
for (so = tcb.so_next; so != &tcb; so = so_next) { |
377 | 377 |
so_next = so->so_next; |
378 |
|
|
378 |
|
|
379 | 379 |
/* |
380 | 380 |
* FD_ISSET is meaningless on these sockets |
381 | 381 |
* (and they can crash the program) |
382 | 382 |
*/ |
383 | 383 |
if (so->so_state & SS_NOFDREF || so->s == -1) |
384 | 384 |
continue; |
385 |
|
|
385 |
|
|
386 | 386 |
/* |
387 | 387 |
* Check for URG data |
388 | 388 |
* This will soread as well, so no need to |
... | ... | |
402 | 402 |
continue; |
403 | 403 |
} /* else */ |
404 | 404 |
ret = soread(so); |
405 |
|
|
405 |
|
|
406 | 406 |
/* Output it if we read something */ |
407 | 407 |
if (ret > 0) |
408 | 408 |
tcp_output(sototcpcb(so)); |
409 | 409 |
} |
410 |
|
|
410 |
|
|
411 | 411 |
/* |
412 | 412 |
* Check sockets for writing |
413 | 413 |
*/ |
... | ... | |
418 | 418 |
if (so->so_state & SS_ISFCONNECTING) { |
419 | 419 |
/* Connected */ |
420 | 420 |
so->so_state &= ~SS_ISFCONNECTING; |
421 |
|
|
421 |
|
|
422 | 422 |
ret = send(so->s, &ret, 0, 0); |
423 | 423 |
if (ret < 0) { |
424 | 424 |
/* XXXXX Must fix, zero bytes is a NOP */ |
425 | 425 |
if (errno == EAGAIN || errno == EWOULDBLOCK || |
426 | 426 |
errno == EINPROGRESS || errno == ENOTCONN) |
427 | 427 |
continue; |
428 |
|
|
428 |
|
|
429 | 429 |
/* else failed */ |
430 | 430 |
so->so_state = SS_NOFDREF; |
431 | 431 |
} |
432 | 432 |
/* else so->so_state &= ~SS_ISFCONNECTING; */ |
433 |
|
|
433 |
|
|
434 | 434 |
/* |
435 | 435 |
* Continue tcp_input |
436 | 436 |
*/ |
... | ... | |
439 | 439 |
} else |
440 | 440 |
ret = sowrite(so); |
441 | 441 |
/* |
442 |
* XXXXX If we wrote something (a lot), there
|
|
442 |
* XXXXX If we wrote something (a lot), there |
|
443 | 443 |
* could be a need for a window update. |
444 | 444 |
* In the worst case, the remote will send |
445 | 445 |
* a window probe to get things going again |
446 | 446 |
*/ |
447 | 447 |
} |
448 |
|
|
448 |
|
|
449 | 449 |
/* |
450 | 450 |
* Probe a still-connecting, non-blocking socket |
451 | 451 |
* to check if it's still alive |
... | ... | |
453 | 453 |
#ifdef PROBE_CONN |
454 | 454 |
if (so->so_state & SS_ISFCONNECTING) { |
455 | 455 |
ret = recv(so->s, (char *)&ret, 0,0); |
456 |
|
|
456 |
|
|
457 | 457 |
if (ret < 0) { |
458 | 458 |
/* XXX */ |
459 | 459 |
if (errno == EAGAIN || errno == EWOULDBLOCK || |
460 | 460 |
errno == EINPROGRESS || errno == ENOTCONN) |
461 | 461 |
continue; /* Still connecting, continue */ |
462 |
|
|
462 |
|
|
463 | 463 |
/* else failed */ |
464 | 464 |
so->so_state = SS_NOFDREF; |
465 |
|
|
465 |
|
|
466 | 466 |
/* tcp_input will take care of it */ |
467 | 467 |
} else { |
468 | 468 |
ret = send(so->s, &ret, 0,0); |
... | ... | |
475 | 475 |
so->so_state = SS_NOFDREF; |
476 | 476 |
} else |
477 | 477 |
so->so_state &= ~SS_ISFCONNECTING; |
478 |
|
|
478 |
|
|
479 | 479 |
} |
480 | 480 |
tcp_input((struct mbuf *)NULL, sizeof(struct ip),so); |
481 | 481 |
} /* SS_ISFCONNECTING */ |
482 | 482 |
#endif |
483 | 483 |
} |
484 |
|
|
484 |
|
|
485 | 485 |
/* |
486 | 486 |
* Now UDP sockets. |
487 | 487 |
* Incoming packets are sent straight away, they're not buffered. |
... | ... | |
489 | 489 |
*/ |
490 | 490 |
for (so = udb.so_next; so != &udb; so = so_next) { |
491 | 491 |
so_next = so->so_next; |
492 |
|
|
492 |
|
|
493 | 493 |
if (so->s != -1 && FD_ISSET(so->s, readfds)) { |
494 | 494 |
sorecvfrom(so); |
495 | 495 |
} |
496 | 496 |
} |
497 | 497 |
} |
498 |
|
|
498 |
|
|
499 | 499 |
/* |
500 | 500 |
* See if we can start outputting |
501 | 501 |
*/ |
... | ... | |
521 | 521 |
#define ARPOP_REQUEST 1 /* ARP request */ |
522 | 522 |
#define ARPOP_REPLY 2 /* ARP reply */ |
523 | 523 |
|
524 |
struct ethhdr
|
|
524 |
struct ethhdr |
|
525 | 525 |
{ |
526 | 526 |
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ |
527 | 527 |
unsigned char h_source[ETH_ALEN]; /* source ether addr */ |
... | ... | |
559 | 559 |
switch(ar_op) { |
560 | 560 |
case ARPOP_REQUEST: |
561 | 561 |
if (!memcmp(ah->ar_tip, &special_addr, 3)) { |
562 |
if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
|
|
562 |
if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS) |
|
563 | 563 |
goto arp_ok; |
564 | 564 |
for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { |
565 | 565 |
if (ex_ptr->ex_addr == ah->ar_tip[3]) |
... | ... | |
600 | 600 |
|
601 | 601 |
if (pkt_len < ETH_HLEN) |
602 | 602 |
return; |
603 |
|
|
603 |
|
|
604 | 604 |
proto = ntohs(*(uint16_t *)(pkt + 12)); |
605 | 605 |
switch(proto) { |
606 | 606 |
case ETH_P_ARP: |
... | ... | |
642 | 642 |
slirp_output(buf, ip_data_len + ETH_HLEN); |
643 | 643 |
} |
644 | 644 |
|
645 |
int slirp_redir(int is_udp, int host_port,
|
|
645 |
int slirp_redir(int is_udp, int host_port, |
|
646 | 646 |
struct in_addr guest_addr, int guest_port) |
647 | 647 |
{ |
648 | 648 |
if (is_udp) { |
649 |
if (!udp_listen(htons(host_port), guest_addr.s_addr,
|
|
649 |
if (!udp_listen(htons(host_port), guest_addr.s_addr, |
|
650 | 650 |
htons(guest_port), 0)) |
651 | 651 |
return -1; |
652 | 652 |
} else { |
653 |
if (!solisten(htons(host_port), guest_addr.s_addr,
|
|
653 |
if (!solisten(htons(host_port), guest_addr.s_addr, |
|
654 | 654 |
htons(guest_port), 0)) |
655 | 655 |
return -1; |
656 | 656 |
} |
657 | 657 |
return 0; |
658 | 658 |
} |
659 | 659 |
|
660 |
int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
|
|
660 |
int slirp_add_exec(int do_pty, const char *args, int addr_low_byte, |
|
661 | 661 |
int guest_port) |
662 | 662 |
{ |
663 |
return add_exec(&exec_list, do_pty, (char *)args,
|
|
663 |
return add_exec(&exec_list, do_pty, (char *)args, |
|
664 | 664 |
addr_low_byte, htons(guest_port)); |
665 | 665 |
} |
Also available in: Unified diff