|
|
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];
87: char buff2[256];
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
124: void slirp_cleanup(void)
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)
223: time_fasttimo = curtime; /* Flag when we want a fasttimo */
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)
230: continue;
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: {
349: struct socket *so, *so_next;
350: int ret;
351:
352: global_readfds = readfds;
353: global_writefds = writefds;
354: global_xfds = xfds;
355:
356: /* Update time */
357: updtime();
358:
359: /*
360: * See if anything has timed out
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: }
373:
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;
383:
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)
389: continue;
390:
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))
397: sorecvoob(so);
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);
410:
411: /* Output it if we read something */
412: if (ret > 0)
413: tcp_output(sototcpcb(so));
414: }
415:
416: /*
417: * Check sockets for writing
418: */
419: if (FD_ISSET(so->s, writefds)) {
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, &ret, 0, 0);
428: if (ret < 0) {
429: /* XXXXX Must fix, zero bytes is a NOP */
430: if (errno == EAGAIN || errno == EWOULDBLOCK ||
431: errno == EINPROGRESS || errno == ENOTCONN)
432: continue;
433:
434: /* else failed */
435: so->so_state = SS_NOFDREF;
436: }
437: /* else so->so_state &= ~SS_ISFCONNECTING; */
438:
439: /*
440: * Continue tcp_input
441: */
442: tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
443: /* continue; */
444: } else
445: ret = sowrite(so);
446: /*
447: * XXXXX If we wrote something (a lot), there
448: * could be a need for a window update.
449: * In the worst case, the remote will send
450: * a window probe to get things going again
451: */
452: }
453:
454: /*
455: * Probe a still-connecting, non-blocking socket
456: * to check if it's still alive
457: */
458: #ifdef PROBE_CONN
459: if (so->so_state & SS_ISFCONNECTING) {
460: ret = recv(so->s, (char *)&ret, 0,0);
461:
462: if (ret < 0) {
463: /* XXX */
464: if (errno == EAGAIN || errno == EWOULDBLOCK ||
465: errno == EINPROGRESS || errno == ENOTCONN)
466: continue; /* Still connecting, continue */
467:
468: /* else failed */
469: so->so_state = SS_NOFDREF;
470:
471: /* tcp_input will take care of it */
472: } else {
473: ret = send(so->s, &ret, 0,0);
474: if (ret < 0) {
475: /* XXX */
476: if (errno == EAGAIN || errno == EWOULDBLOCK ||
477: errno == EINPROGRESS || errno == ENOTCONN)
478: continue;
479: /* else failed */
480: so->so_state = SS_NOFDREF;
481: } else
482: so->so_state &= ~SS_ISFCONNECTING;
483:
484: }
485: tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
486: } /* SS_ISFCONNECTING */
487: #endif
488: }
489:
490: /*
491: * Now UDP sockets.
492: * Incoming packets are sent straight away, they're not buffered.
493: * Incoming UDP data isn't buffered either.
494: */
495: for (so = udb.so_next; so != &udb; so = so_next) {
496: so_next = so->so_next;
497:
498: if (so->s != -1 && FD_ISSET(so->s, readfds)) {
499: sorecvfrom(so);
500: }
501: }
502: }
503:
504: /*
505: * See if we can start outputting
506: */
507: if (if_queued && link_up)
508: if_start();
509:
510: /* clear global file descriptor sets.
511: * these reside on the stack in vl.c
512: * so they're unusable if we're not in
513: * slirp_select_fill or slirp_select_poll.
514: */
515: global_readfds = NULL;
516: global_writefds = NULL;
517: global_xfds = NULL;
518: }
519:
520: #define ETH_ALEN 6
521: #define ETH_HLEN 14
522:
523: #define ETH_P_IP 0x0800 /* Internet Protocol packet */
524: #define ETH_P_ARP 0x0806 /* Address Resolution packet */
525:
526: #define ARPOP_REQUEST 1 /* ARP request */
527: #define ARPOP_REPLY 2 /* ARP reply */
528:
529: struct ethhdr
530: {
531: unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
532: unsigned char h_source[ETH_ALEN]; /* source ether addr */
533: unsigned short h_proto; /* packet type ID field */
534: };
535:
536: struct arphdr
537: {
538: unsigned short ar_hrd; /* format of hardware address */
539: unsigned short ar_pro; /* format of protocol address */
540: unsigned char ar_hln; /* length of hardware address */
541: unsigned char ar_pln; /* length of protocol address */
542: unsigned short ar_op; /* ARP opcode (command) */
543:
544: /*
545: * Ethernet looks like this : This bit is variable sized however...
546: */
547: unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
548: unsigned char ar_sip[4]; /* sender IP address */
549: unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
550: unsigned char ar_tip[4]; /* target IP address */
551: };
552:
553: void arp_input(const uint8_t *pkt, int pkt_len)
554: {
555: struct ethhdr *eh = (struct ethhdr *)pkt;
556: struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
557: uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
558: struct ethhdr *reh = (struct ethhdr *)arp_reply;
559: struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
560: int ar_op;
561: struct ex_list *ex_ptr;
562:
563: ar_op = ntohs(ah->ar_op);
564: switch(ar_op) {
565: case ARPOP_REQUEST:
566: if (!memcmp(ah->ar_tip, &special_addr, 3)) {
567: if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
568: goto arp_ok;
569: for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
570: if (ex_ptr->ex_addr == ah->ar_tip[3])
571: goto arp_ok;
572: }
573: return;
574: arp_ok:
575: /* XXX: make an ARP request to have the client address */
576: memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
577:
578: /* ARP request for alias/dns mac address */
579: memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
580: memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
581: reh->h_source[5] = ah->ar_tip[3];
582: reh->h_proto = htons(ETH_P_ARP);
583:
584: rah->ar_hrd = htons(1);
585: rah->ar_pro = htons(ETH_P_IP);
586: rah->ar_hln = ETH_ALEN;
587: rah->ar_pln = 4;
588: rah->ar_op = htons(ARPOP_REPLY);
589: memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
590: memcpy(rah->ar_sip, ah->ar_tip, 4);
591: memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
592: memcpy(rah->ar_tip, ah->ar_sip, 4);
593: slirp_output(arp_reply, sizeof(arp_reply));
594: }
595: break;
596: default:
597: break;
598: }
599: }
600:
601: void slirp_input(const uint8_t *pkt, int pkt_len)
602: {
603: struct mbuf *m;
604: int proto;
605:
606: if (pkt_len < ETH_HLEN)
607: return;
608:
609: proto = (pkt[12] << 8) | pkt[13];
610: switch(proto) {
611: case ETH_P_ARP:
612: arp_input(pkt, pkt_len);
613: break;
614: case ETH_P_IP:
615: m = m_get();
616: if (!m)
617: return;
618: /* Note: we add to align the IP header */
619: m->m_len = pkt_len + 2;
620: memcpy(m->m_data + 2, pkt, pkt_len);
621:
622: m->m_data += 2 + ETH_HLEN;
623: m->m_len -= 2 + ETH_HLEN;
624:
625: ip_input(m);
626: break;
627: default:
628: break;
629: }
630: }
631:
632: /* output the IP packet to the ethernet device */
633: void if_encap(const uint8_t *ip_data, int ip_data_len)
634: {
635: uint8_t buf[1600];
636: struct ethhdr *eh = (struct ethhdr *)buf;
637:
638: if (ip_data_len + ETH_HLEN > sizeof(buf))
639: return;
640:
641: memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
642: memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
643: /* XXX: not correct */
644: eh->h_source[5] = CTL_ALIAS;
645: eh->h_proto = htons(ETH_P_IP);
646: memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
647: slirp_output(buf, ip_data_len + ETH_HLEN);
648: }
649:
650: int slirp_redir(int is_udp, int host_port,
651: struct in_addr guest_addr, int guest_port)
652: {
653: if (is_udp) {
654: if (!udp_listen(htons(host_port), guest_addr.s_addr,
655: htons(guest_port), 0))
656: return -1;
657: } else {
658: if (!solisten(htons(host_port), guest_addr.s_addr,
659: htons(guest_port), 0))
660: return -1;
661: }
662: return 0;
663: }
664:
665: int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
666: int guest_port)
667: {
668: return add_exec(&exec_list, do_pty, (char *)args,
669: addr_low_byte, htons(guest_port));
670: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.