|
|
1.1 root 1: #include "slirp.h"
2:
3: /* host address */
4: struct in_addr our_addr;
5: /* host dns address */
6: struct in_addr dns_addr;
7: /* host loopback address */
8: struct in_addr loopback_addr;
9:
10: /* address for slirp virtual addresses */
11: struct in_addr special_addr;
12: /* virtual address alias for host */
13: struct in_addr alias_addr;
14:
15: const uint8_t special_ethaddr[6] = {
16: 0x52, 0x54, 0x00, 0x12, 0x35, 0x00
17: };
18:
19: uint8_t client_ethaddr[6];
20:
21: int do_slowtimo;
22: int link_up;
23: struct timeval tt;
24: FILE *lfd;
25: struct ex_list *exec_list;
26:
27: /* XXX: suppress those select globals */
28: fd_set *global_readfds, *global_writefds, *global_xfds;
29:
30: char slirp_hostname[33];
31:
32: #ifdef _WIN32
33:
34: static int get_dns_addr(struct in_addr *pdns_addr)
35: {
36: FIXED_INFO *FixedInfo=NULL;
37: ULONG BufLen;
38: DWORD ret;
39: IP_ADDR_STRING *pIPAddr;
40: struct in_addr tmp_addr;
41:
42: FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
43: BufLen = sizeof(FIXED_INFO);
44:
45: if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
46: if (FixedInfo) {
47: GlobalFree(FixedInfo);
48: FixedInfo = NULL;
49: }
50: FixedInfo = GlobalAlloc(GPTR, BufLen);
51: }
52:
53: if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
54: printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );
55: if (FixedInfo) {
56: GlobalFree(FixedInfo);
57: FixedInfo = NULL;
58: }
59: return -1;
60: }
61:
62: pIPAddr = &(FixedInfo->DnsServerList);
63: inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
64: *pdns_addr = tmp_addr;
65: #if 0
66: printf( "DNS Servers:\n" );
67: printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );
68:
69: pIPAddr = FixedInfo -> DnsServerList.Next;
70: while ( pIPAddr ) {
71: printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );
72: pIPAddr = pIPAddr ->Next;
73: }
74: #endif
75: if (FixedInfo) {
76: GlobalFree(FixedInfo);
77: FixedInfo = NULL;
78: }
79: return 0;
80: }
81:
82: #else
83:
84: static int get_dns_addr(struct in_addr *pdns_addr)
85: {
86: char buff[512];
1.1.1.2 root 87: char buff2[256+1];
1.1 root 88: FILE *f;
89: int found = 0;
90: struct in_addr tmp_addr;
91:
92: f = fopen("/etc/resolv.conf", "r");
93: if (!f)
94: return -1;
95:
96: lprint("IP address of your DNS(s): ");
97: while (fgets(buff, 512, f) != NULL) {
98: if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
99: if (!inet_aton(buff2, &tmp_addr))
100: continue;
101: if (tmp_addr.s_addr == loopback_addr.s_addr)
102: tmp_addr = our_addr;
103: /* If it's the first one, set it to dns_addr */
104: if (!found)
105: *pdns_addr = tmp_addr;
106: else
107: lprint(", ");
108: if (++found > 3) {
109: lprint("(more)");
110: break;
111: } else
112: lprint("%s", inet_ntoa(tmp_addr));
113: }
114: }
115: fclose(f);
116: if (!found)
117: return -1;
118: return 0;
119: }
120:
121: #endif
122:
123: #ifdef _WIN32
1.1.1.3 ! root 124: static void slirp_cleanup(void)
1.1 root 125: {
126: WSACleanup();
127: }
128: #endif
129:
130: int slirp_init(void)
131: {
132: // debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
133:
134: #ifdef _WIN32
135: {
136: WSADATA Data;
137: WSAStartup(MAKEWORD(2,0), &Data);
138: atexit(slirp_cleanup);
139: }
140: #endif
141:
142: link_up = 1;
143:
144: if_init();
145: ip_init();
146:
147: /* Initialise mbufs *after* setting the MTU */
148: m_init();
149:
150: /* set default addresses */
151: inet_aton("127.0.0.1", &loopback_addr);
152:
153: if (get_dns_addr(&dns_addr) < 0)
154: return -1;
155:
156: inet_aton(CTL_SPECIAL, &special_addr);
157: alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
158: getouraddr();
159: return 0;
160: }
161:
162: #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
163: #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
164: #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
165:
166: /*
167: * curtime kept to an accuracy of 1ms
168: */
169: #ifdef _WIN32
170: static void updtime(void)
171: {
172: struct _timeb tb;
173:
174: _ftime(&tb);
175: curtime = (u_int)tb.time * (u_int)1000;
176: curtime += (u_int)tb.millitm;
177: }
178: #else
179: static void updtime(void)
180: {
181: gettimeofday(&tt, 0);
182:
183: curtime = (u_int)tt.tv_sec * (u_int)1000;
184: curtime += (u_int)tt.tv_usec / (u_int)1000;
185:
186: if ((tt.tv_usec % 1000) >= 500)
187: curtime++;
188: }
189: #endif
190:
191: int slirp_select_fill(int *pnfds,
192: fd_set *readfds, fd_set *writefds, fd_set *xfds)
193: {
194: struct socket *so, *so_next;
195: int nfds;
196: int timeout, tmp_time;
197:
198: /* fail safe */
199: global_readfds = NULL;
200: global_writefds = NULL;
201: global_xfds = NULL;
202:
203: nfds = *pnfds;
204: /*
205: * First, TCP sockets
206: */
207: do_slowtimo = 0;
208: if (link_up) {
209: /*
210: * *_slowtimo needs calling if there are IP fragments
211: * in the fragment queue, or there are TCP connections active
212: */
213: do_slowtimo = ((tcb.so_next != &tcb) ||
214: (&ipq.ip_link != ipq.ip_link.next));
215:
216: for (so = tcb.so_next; so != &tcb; so = so_next) {
217: so_next = so->so_next;
218:
219: /*
220: * See if we need a tcp_fasttimo
221: */
222: if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
1.1.1.2 root 223: time_fasttimo = curtime; /* Flag when we want a fasttimo */
1.1 root 224:
225: /*
226: * NOFDREF can include still connecting to local-host,
227: * newly socreated() sockets etc. Don't want to select these.
228: */
229: if (so->so_state & SS_NOFDREF || so->s == -1)
1.1.1.2 root 230: continue;
1.1 root 231:
232: /*
233: * Set for reading sockets which are accepting
234: */
235: if (so->so_state & SS_FACCEPTCONN) {
236: FD_SET(so->s, readfds);
237: UPD_NFDS(so->s);
238: continue;
239: }
240:
241: /*
242: * Set for writing sockets which are connecting
243: */
244: if (so->so_state & SS_ISFCONNECTING) {
245: FD_SET(so->s, writefds);
246: UPD_NFDS(so->s);
247: continue;
248: }
249:
250: /*
251: * Set for writing if we are connected, can send more, and
252: * we have something to send
253: */
254: if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
255: FD_SET(so->s, writefds);
256: UPD_NFDS(so->s);
257: }
258:
259: /*
260: * Set for reading (and urgent data) if we are connected, can
261: * receive more, and we have room for it XXX /2 ?
262: */
263: if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
264: FD_SET(so->s, readfds);
265: FD_SET(so->s, xfds);
266: UPD_NFDS(so->s);
267: }
268: }
269:
270: /*
271: * UDP sockets
272: */
273: for (so = udb.so_next; so != &udb; so = so_next) {
274: so_next = so->so_next;
275:
276: /*
277: * See if it's timed out
278: */
279: if (so->so_expire) {
280: if (so->so_expire <= curtime) {
281: udp_detach(so);
282: continue;
283: } else
284: do_slowtimo = 1; /* Let socket expire */
285: }
286:
287: /*
288: * When UDP packets are received from over the
289: * link, they're sendto()'d straight away, so
290: * no need for setting for writing
291: * Limit the number of packets queued by this session
292: * to 4. Note that even though we try and limit this
293: * to 4 packets, the session could have more queued
294: * if the packets needed to be fragmented
295: * (XXX <= 4 ?)
296: */
297: if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
298: FD_SET(so->s, readfds);
299: UPD_NFDS(so->s);
300: }
301: }
302: }
303:
304: /*
305: * Setup timeout to use minimum CPU usage, especially when idle
306: */
307:
308: timeout = -1;
309:
310: /*
311: * If a slowtimo is needed, set timeout to 5ms from the last
312: * slow timeout. If a fast timeout is needed, set timeout within
313: * 2ms of when it was requested.
314: */
315: # define SLOW_TIMO 5
316: # define FAST_TIMO 2
317: if (do_slowtimo) {
318: timeout = (SLOW_TIMO - (curtime - last_slowtimo)) * 1000;
319: if (timeout < 0)
320: timeout = 0;
321: else if (timeout > (SLOW_TIMO * 1000))
322: timeout = SLOW_TIMO * 1000;
323:
324: /* Can only fasttimo if we also slowtimo */
325: if (time_fasttimo) {
326: tmp_time = (FAST_TIMO - (curtime - time_fasttimo)) * 1000;
327: if (tmp_time < 0)
328: tmp_time = 0;
329:
330: /* Choose the smallest of the 2 */
331: if (tmp_time < timeout)
332: timeout = tmp_time;
333: }
334: }
335: *pnfds = nfds;
336:
337: /*
338: * Adjust the timeout to make the minimum timeout
339: * 2ms (XXX?) to lessen the CPU load
340: */
341: if (timeout < (FAST_TIMO * 1000))
342: timeout = FAST_TIMO * 1000;
343:
344: return timeout;
345: }
346:
347: void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
348: {
1.1.1.2 root 349: struct socket *so, *so_next;
350: int ret;
1.1 root 351:
1.1.1.2 root 352: global_readfds = readfds;
353: global_writefds = writefds;
354: global_xfds = xfds;
1.1 root 355:
356: /* Update time */
357: updtime();
1.1.1.2 root 358:
1.1 root 359: /*
1.1.1.2 root 360: * See if anything has timed out
1.1 root 361: */
362: if (link_up) {
363: if (time_fasttimo && ((curtime - time_fasttimo) >= FAST_TIMO)) {
364: tcp_fasttimo();
365: time_fasttimo = 0;
366: }
367: if (do_slowtimo && ((curtime - last_slowtimo) >= SLOW_TIMO)) {
368: ip_slowtimo();
369: tcp_slowtimo();
370: last_slowtimo = curtime;
371: }
372: }
1.1.1.2 root 373:
1.1 root 374: /*
375: * Check sockets
376: */
377: if (link_up) {
378: /*
379: * Check TCP sockets
380: */
381: for (so = tcb.so_next; so != &tcb; so = so_next) {
382: so_next = so->so_next;
1.1.1.2 root 383:
1.1 root 384: /*
385: * FD_ISSET is meaningless on these sockets
386: * (and they can crash the program)
387: */
388: if (so->so_state & SS_NOFDREF || so->s == -1)
1.1.1.2 root 389: continue;
390:
1.1 root 391: /*
392: * Check for URG data
393: * This will soread as well, so no need to
394: * test for readfds below if this succeeds
395: */
396: if (FD_ISSET(so->s, xfds))
1.1.1.2 root 397: sorecvoob(so);
1.1 root 398: /*
399: * Check sockets for reading
400: */
401: else if (FD_ISSET(so->s, readfds)) {
402: /*
403: * Check for incoming connections
404: */
405: if (so->so_state & SS_FACCEPTCONN) {
406: tcp_connect(so);
407: continue;
408: } /* else */
409: ret = soread(so);
1.1.1.2 root 410:
1.1 root 411: /* Output it if we read something */
412: if (ret > 0)
1.1.1.2 root 413: tcp_output(sototcpcb(so));
1.1 root 414: }
1.1.1.2 root 415:
1.1 root 416: /*
417: * Check sockets for writing
418: */
419: if (FD_ISSET(so->s, writefds)) {
1.1.1.2 root 420: /*
421: * Check for non-blocking, still-connecting sockets
422: */
423: if (so->so_state & SS_ISFCONNECTING) {
424: /* Connected */
425: so->so_state &= ~SS_ISFCONNECTING;
426:
427: ret = send(so->s, (char*)&ret, 0, 0);
428: if (ret < 0) {
429: /* XXXXX Must fix, zero bytes is a NOP */
430: int error = WSAGetLastError();
431: if (error == EAGAIN || error == WSAEWOULDBLOCK ||
432: error == WSAEINPROGRESS || error == WSAENOTCONN)
433: continue;
434:
435: /* else failed */
436: so->so_state = SS_NOFDREF;
437: }
438: /* else so->so_state &= ~SS_ISFCONNECTING; */
439:
440: /*
441: * Continue tcp_input
442: */
443: tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
444: /* continue; */
445: }
446: else
447: ret = sowrite(so);
448: /*
449: * XXXXX If we wrote something (a lot), there
450: * could be a need for a window update.
451: * In the worst case, the remote will send
452: * a window probe to get things going again
453: */
1.1 root 454: }
1.1.1.2 root 455:
1.1 root 456: /*
457: * Probe a still-connecting, non-blocking socket
458: * to check if it's still alive
1.1.1.2 root 459: */
1.1 root 460: #ifdef PROBE_CONN
461: if (so->so_state & SS_ISFCONNECTING) {
1.1.1.2 root 462: ret = recv(so->s, (char *)&ret, 0, 0);
463:
464: if (ret < 0) {
465: /* XXX */
466: int error = WSAGetLastError();
467: if (error == EAGAIN || error == WSAEWOULDBLOCK ||
468: error == WSAEINPROGRESS || error == WSAENOTCONN)
469: continue; /* Still connecting, continue */
470:
471: /* else failed */
472: so->so_state = SS_NOFDREF;
473:
474: /* tcp_input will take care of it */
475: }
476: else {
477: ret = send(so->s, &ret, 0, 0);
478: if (ret < 0) {
479: /* XXX */
480: int error = WSAGetLastError();
481: if (error == EAGAIN || error == WSAEWOULDBLOCK ||
482: error == WSAEINPROGRESS || error == WSAENOTCONN)
483: continue;
484: /* else failed */
485: so->so_state = SS_NOFDREF;
486: }
487: else
488: so->so_state &= ~SS_ISFCONNECTING;
489:
490: }
491: tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
492: } /* SS_ISFCONNECTING */
1.1 root 493: #endif
1.1.1.2 root 494: }
495:
1.1 root 496: /*
497: * Now UDP sockets.
498: * Incoming packets are sent straight away, they're not buffered.
499: * Incoming UDP data isn't buffered either.
500: */
501: for (so = udb.so_next; so != &udb; so = so_next) {
502: so_next = so->so_next;
1.1.1.2 root 503:
1.1 root 504: if (so->s != -1 && FD_ISSET(so->s, readfds)) {
1.1.1.2 root 505: sorecvfrom(so);
506: }
1.1 root 507: }
1.1.1.2 root 508: }
509:
1.1 root 510: /*
511: * See if we can start outputting
512: */
513: if (if_queued && link_up)
1.1.1.2 root 514: if_start();
1.1 root 515:
516: /* clear global file descriptor sets.
517: * these reside on the stack in vl.c
518: * so they're unusable if we're not in
519: * slirp_select_fill or slirp_select_poll.
520: */
1.1.1.2 root 521: global_readfds = NULL;
522: global_writefds = NULL;
523: global_xfds = NULL;
1.1 root 524: }
525:
526: #define ETH_ALEN 6
527: #define ETH_HLEN 14
528:
529: #define ETH_P_IP 0x0800 /* Internet Protocol packet */
530: #define ETH_P_ARP 0x0806 /* Address Resolution packet */
531:
532: #define ARPOP_REQUEST 1 /* ARP request */
533: #define ARPOP_REPLY 2 /* ARP reply */
534:
535: struct ethhdr
536: {
537: unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
538: unsigned char h_source[ETH_ALEN]; /* source ether addr */
539: unsigned short h_proto; /* packet type ID field */
540: };
541:
542: struct arphdr
543: {
544: unsigned short ar_hrd; /* format of hardware address */
545: unsigned short ar_pro; /* format of protocol address */
546: unsigned char ar_hln; /* length of hardware address */
547: unsigned char ar_pln; /* length of protocol address */
548: unsigned short ar_op; /* ARP opcode (command) */
549:
550: /*
551: * Ethernet looks like this : This bit is variable sized however...
552: */
553: unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
554: unsigned char ar_sip[4]; /* sender IP address */
555: unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
556: unsigned char ar_tip[4]; /* target IP address */
557: };
558:
1.1.1.3 ! root 559: static void arp_input(const uint8_t *pkt, int pkt_len)
1.1 root 560: {
1.1.1.3 ! root 561: const struct ethhdr *eh = (const struct ethhdr *)pkt;
! 562: const struct arphdr *ah = (const struct arphdr *)(pkt + ETH_HLEN);
1.1 root 563: uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
564: struct ethhdr *reh = (struct ethhdr *)arp_reply;
565: struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
566: int ar_op;
567: struct ex_list *ex_ptr;
568:
569: ar_op = ntohs(ah->ar_op);
570: switch(ar_op) {
571: case ARPOP_REQUEST:
572: if (!memcmp(ah->ar_tip, &special_addr, 3)) {
573: if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
574: goto arp_ok;
575: for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
576: if (ex_ptr->ex_addr == ah->ar_tip[3])
577: goto arp_ok;
578: }
579: return;
580: arp_ok:
581: /* XXX: make an ARP request to have the client address */
582: memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
583:
584: /* ARP request for alias/dns mac address */
585: memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
586: memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
587: reh->h_source[5] = ah->ar_tip[3];
588: reh->h_proto = htons(ETH_P_ARP);
589:
590: rah->ar_hrd = htons(1);
591: rah->ar_pro = htons(ETH_P_IP);
592: rah->ar_hln = ETH_ALEN;
593: rah->ar_pln = 4;
594: rah->ar_op = htons(ARPOP_REPLY);
595: memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
596: memcpy(rah->ar_sip, ah->ar_tip, 4);
597: memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
598: memcpy(rah->ar_tip, ah->ar_sip, 4);
599: slirp_output(arp_reply, sizeof(arp_reply));
600: }
601: break;
602: default:
603: break;
604: }
605: }
606:
607: void slirp_input(const uint8_t *pkt, int pkt_len)
608: {
609: struct mbuf *m;
610: int proto;
611:
612: if (pkt_len < ETH_HLEN)
613: return;
614:
615: proto = (pkt[12] << 8) | pkt[13];
616: switch(proto) {
617: case ETH_P_ARP:
618: arp_input(pkt, pkt_len);
619: break;
620: case ETH_P_IP:
621: m = m_get();
622: if (!m)
623: return;
624: /* Note: we add to align the IP header */
625: m->m_len = pkt_len + 2;
626: memcpy(m->m_data + 2, pkt, pkt_len);
627:
628: m->m_data += 2 + ETH_HLEN;
629: m->m_len -= 2 + ETH_HLEN;
630:
631: ip_input(m);
632: break;
633: default:
634: break;
635: }
636: }
637:
638: /* output the IP packet to the ethernet device */
639: void if_encap(const uint8_t *ip_data, int ip_data_len)
640: {
641: uint8_t buf[1600];
642: struct ethhdr *eh = (struct ethhdr *)buf;
643:
644: if (ip_data_len + ETH_HLEN > sizeof(buf))
645: return;
646:
647: memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
648: memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
649: /* XXX: not correct */
650: eh->h_source[5] = CTL_ALIAS;
651: eh->h_proto = htons(ETH_P_IP);
652: memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
653: slirp_output(buf, ip_data_len + ETH_HLEN);
654: }
655:
656: int slirp_redir(int is_udp, int host_port,
657: struct in_addr guest_addr, int guest_port)
658: {
659: if (is_udp) {
660: if (!udp_listen(htons(host_port), guest_addr.s_addr,
661: htons(guest_port), 0))
662: return -1;
663: } else {
664: if (!solisten(htons(host_port), guest_addr.s_addr,
665: htons(guest_port), 0))
666: return -1;
667: }
668: return 0;
669: }
670:
671: int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
672: int guest_port)
673: {
1.1.1.3 ! root 674: return add_exec(&exec_list, do_pty, args,
1.1 root 675: addr_low_byte, htons(guest_port));
676: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.