|
|
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;
1.1.1.2 root 12: /* virtual address alias for host */
13: struct in_addr alias_addr;
1.1 root 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:
1.1.1.2 root 30: char slirp_hostname[33];
31:
1.1 root 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: void 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) {
1.1.1.2 root 154: dns_addr = loopback_addr;
155: fprintf (stderr, "Warning: No DNS servers found\n");
1.1 root 156: }
157:
158: inet_aton(CTL_SPECIAL, &special_addr);
1.1.1.2 root 159: alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);
160: getouraddr();
1.1 root 161: }
162:
163: #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
164: #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
165: #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
166:
167: /*
168: * curtime kept to an accuracy of 1ms
169: */
170: #ifdef _WIN32
171: static void updtime(void)
172: {
173: struct _timeb tb;
174:
175: _ftime(&tb);
176: curtime = (u_int)tb.time * (u_int)1000;
177: curtime += (u_int)tb.millitm;
178: }
179: #else
180: static void updtime(void)
181: {
182: gettimeofday(&tt, 0);
183:
184: curtime = (u_int)tt.tv_sec * (u_int)1000;
185: curtime += (u_int)tt.tv_usec / (u_int)1000;
186:
187: if ((tt.tv_usec % 1000) >= 500)
188: curtime++;
189: }
190: #endif
191:
192: void slirp_select_fill(int *pnfds,
193: fd_set *readfds, fd_set *writefds, fd_set *xfds)
194: {
195: struct socket *so, *so_next;
196: struct timeval timeout;
197: int nfds;
198: int tmp_time;
199:
200: /* fail safe */
201: global_readfds = NULL;
202: global_writefds = NULL;
203: global_xfds = NULL;
204:
205: nfds = *pnfds;
206: /*
207: * First, TCP sockets
208: */
209: do_slowtimo = 0;
210: if (link_up) {
211: /*
212: * *_slowtimo needs calling if there are IP fragments
213: * in the fragment queue, or there are TCP connections active
214: */
215: do_slowtimo = ((tcb.so_next != &tcb) ||
216: ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
217:
218: for (so = tcb.so_next; so != &tcb; so = so_next) {
219: so_next = so->so_next;
220:
221: /*
222: * See if we need a tcp_fasttimo
223: */
224: if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
225: time_fasttimo = curtime; /* Flag when we want a fasttimo */
226:
227: /*
228: * NOFDREF can include still connecting to local-host,
229: * newly socreated() sockets etc. Don't want to select these.
230: */
231: if (so->so_state & SS_NOFDREF || so->s == -1)
232: continue;
233:
234: /*
235: * Set for reading sockets which are accepting
236: */
237: if (so->so_state & SS_FACCEPTCONN) {
238: FD_SET(so->s, readfds);
239: UPD_NFDS(so->s);
240: continue;
241: }
242:
243: /*
244: * Set for writing sockets which are connecting
245: */
246: if (so->so_state & SS_ISFCONNECTING) {
247: FD_SET(so->s, writefds);
248: UPD_NFDS(so->s);
249: continue;
250: }
251:
252: /*
253: * Set for writing if we are connected, can send more, and
254: * we have something to send
255: */
256: if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
257: FD_SET(so->s, writefds);
258: UPD_NFDS(so->s);
259: }
260:
261: /*
262: * Set for reading (and urgent data) if we are connected, can
263: * receive more, and we have room for it XXX /2 ?
264: */
265: if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
266: FD_SET(so->s, readfds);
267: FD_SET(so->s, xfds);
268: UPD_NFDS(so->s);
269: }
270: }
271:
272: /*
273: * UDP sockets
274: */
275: for (so = udb.so_next; so != &udb; so = so_next) {
276: so_next = so->so_next;
277:
278: /*
279: * See if it's timed out
280: */
281: if (so->so_expire) {
282: if (so->so_expire <= curtime) {
283: udp_detach(so);
284: continue;
285: } else
286: do_slowtimo = 1; /* Let socket expire */
287: }
288:
289: /*
290: * When UDP packets are received from over the
291: * link, they're sendto()'d straight away, so
292: * no need for setting for writing
293: * Limit the number of packets queued by this session
294: * to 4. Note that even though we try and limit this
295: * to 4 packets, the session could have more queued
296: * if the packets needed to be fragmented
297: * (XXX <= 4 ?)
298: */
299: if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
300: FD_SET(so->s, readfds);
301: UPD_NFDS(so->s);
302: }
303: }
304: }
305:
306: /*
307: * Setup timeout to use minimum CPU usage, especially when idle
308: */
309:
310: /*
311: * First, see the timeout needed by *timo
312: */
313: timeout.tv_sec = 0;
314: timeout.tv_usec = -1;
315: /*
316: * If a slowtimo is needed, set timeout to 500ms from the last
317: * slow timeout. If a fast timeout is needed, set timeout within
318: * 200ms of when it was requested.
319: */
320: if (do_slowtimo) {
321: /* XXX + 10000 because some select()'s aren't that accurate */
322: timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
323: if (timeout.tv_usec < 0)
324: timeout.tv_usec = 0;
325: else if (timeout.tv_usec > 510000)
326: timeout.tv_usec = 510000;
327:
328: /* Can only fasttimo if we also slowtimo */
329: if (time_fasttimo) {
330: tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
331: if (tmp_time < 0)
332: tmp_time = 0;
333:
334: /* Choose the smallest of the 2 */
335: if (tmp_time < timeout.tv_usec)
336: timeout.tv_usec = (u_int)tmp_time;
337: }
338: }
339: *pnfds = nfds;
340: }
341:
342: void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
343: {
344: struct socket *so, *so_next;
345: int ret;
346:
347: global_readfds = readfds;
348: global_writefds = writefds;
349: global_xfds = xfds;
350:
351: /* Update time */
352: updtime();
353:
354: /*
355: * See if anything has timed out
356: */
357: if (link_up) {
358: if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {
359: tcp_fasttimo();
360: time_fasttimo = 0;
361: }
362: if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
363: ip_slowtimo();
364: tcp_slowtimo();
365: last_slowtimo = curtime;
366: }
367: }
368:
369: /*
370: * Check sockets
371: */
372: if (link_up) {
373: /*
374: * Check TCP sockets
375: */
376: for (so = tcb.so_next; so != &tcb; so = so_next) {
377: so_next = so->so_next;
378:
379: /*
380: * FD_ISSET is meaningless on these sockets
381: * (and they can crash the program)
382: */
383: if (so->so_state & SS_NOFDREF || so->s == -1)
384: continue;
385:
386: /*
387: * Check for URG data
388: * This will soread as well, so no need to
389: * test for readfds below if this succeeds
390: */
391: if (FD_ISSET(so->s, xfds))
392: sorecvoob(so);
393: /*
394: * Check sockets for reading
395: */
396: else if (FD_ISSET(so->s, readfds)) {
397: /*
398: * Check for incoming connections
399: */
400: if (so->so_state & SS_FACCEPTCONN) {
401: tcp_connect(so);
402: continue;
403: } /* else */
404: ret = soread(so);
405:
406: /* Output it if we read something */
407: if (ret > 0)
408: tcp_output(sototcpcb(so));
409: }
410:
411: /*
412: * Check sockets for writing
413: */
414: if (FD_ISSET(so->s, writefds)) {
415: /*
416: * Check for non-blocking, still-connecting sockets
417: */
418: if (so->so_state & SS_ISFCONNECTING) {
419: /* Connected */
420: so->so_state &= ~SS_ISFCONNECTING;
421:
422: ret = send(so->s, &ret, 0, 0);
423: if (ret < 0) {
424: /* XXXXX Must fix, zero bytes is a NOP */
425: if (errno == EAGAIN || errno == EWOULDBLOCK ||
426: errno == EINPROGRESS || errno == ENOTCONN)
427: continue;
428:
429: /* else failed */
430: so->so_state = SS_NOFDREF;
431: }
432: /* else so->so_state &= ~SS_ISFCONNECTING; */
433:
434: /*
435: * Continue tcp_input
436: */
437: tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
438: /* continue; */
439: } else
440: ret = sowrite(so);
441: /*
442: * XXXXX If we wrote something (a lot), there
443: * could be a need for a window update.
444: * In the worst case, the remote will send
445: * a window probe to get things going again
446: */
447: }
448:
449: /*
450: * Probe a still-connecting, non-blocking socket
451: * to check if it's still alive
452: */
453: #ifdef PROBE_CONN
454: if (so->so_state & SS_ISFCONNECTING) {
455: ret = recv(so->s, (char *)&ret, 0,0);
456:
457: if (ret < 0) {
458: /* XXX */
459: if (errno == EAGAIN || errno == EWOULDBLOCK ||
460: errno == EINPROGRESS || errno == ENOTCONN)
461: continue; /* Still connecting, continue */
462:
463: /* else failed */
464: so->so_state = SS_NOFDREF;
465:
466: /* tcp_input will take care of it */
467: } else {
468: ret = send(so->s, &ret, 0,0);
469: if (ret < 0) {
470: /* XXX */
471: if (errno == EAGAIN || errno == EWOULDBLOCK ||
472: errno == EINPROGRESS || errno == ENOTCONN)
473: continue;
474: /* else failed */
475: so->so_state = SS_NOFDREF;
476: } else
477: so->so_state &= ~SS_ISFCONNECTING;
478:
479: }
480: tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
481: } /* SS_ISFCONNECTING */
482: #endif
483: }
484:
485: /*
486: * Now UDP sockets.
487: * Incoming packets are sent straight away, they're not buffered.
488: * Incoming UDP data isn't buffered either.
489: */
490: for (so = udb.so_next; so != &udb; so = so_next) {
491: so_next = so->so_next;
492:
493: if (so->s != -1 && FD_ISSET(so->s, readfds)) {
494: sorecvfrom(so);
495: }
496: }
497: }
498:
499: /*
500: * See if we can start outputting
501: */
502: if (if_queued && link_up)
503: if_start();
504:
505: /* clear global file descriptor sets.
506: * these reside on the stack in vl.c
507: * so they're unusable if we're not in
508: * slirp_select_fill or slirp_select_poll.
509: */
510: global_readfds = NULL;
511: global_writefds = NULL;
512: global_xfds = NULL;
513: }
514:
515: #define ETH_ALEN 6
516: #define ETH_HLEN 14
517:
518: #define ETH_P_IP 0x0800 /* Internet Protocol packet */
519: #define ETH_P_ARP 0x0806 /* Address Resolution packet */
520:
521: #define ARPOP_REQUEST 1 /* ARP request */
522: #define ARPOP_REPLY 2 /* ARP reply */
523:
524: struct ethhdr
525: {
526: unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
527: unsigned char h_source[ETH_ALEN]; /* source ether addr */
528: unsigned short h_proto; /* packet type ID field */
529: };
530:
531: struct arphdr
532: {
533: unsigned short ar_hrd; /* format of hardware address */
534: unsigned short ar_pro; /* format of protocol address */
535: unsigned char ar_hln; /* length of hardware address */
536: unsigned char ar_pln; /* length of protocol address */
537: unsigned short ar_op; /* ARP opcode (command) */
538:
539: /*
540: * Ethernet looks like this : This bit is variable sized however...
541: */
542: unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
543: unsigned char ar_sip[4]; /* sender IP address */
544: unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
545: unsigned char ar_tip[4]; /* target IP address */
546: };
547:
548: void arp_input(const uint8_t *pkt, int pkt_len)
549: {
550: struct ethhdr *eh = (struct ethhdr *)pkt;
551: struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
552: uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
553: struct ethhdr *reh = (struct ethhdr *)arp_reply;
554: struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
555: int ar_op;
556: struct ex_list *ex_ptr;
557:
558: ar_op = ntohs(ah->ar_op);
559: switch(ar_op) {
560: case ARPOP_REQUEST:
561: if (!memcmp(ah->ar_tip, &special_addr, 3)) {
562: if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)
563: goto arp_ok;
564: for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
565: if (ex_ptr->ex_addr == ah->ar_tip[3])
566: goto arp_ok;
567: }
568: return;
569: arp_ok:
570: /* XXX: make an ARP request to have the client address */
571: memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
572:
573: /* ARP request for alias/dns mac address */
574: memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
575: memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
576: reh->h_source[5] = ah->ar_tip[3];
577: reh->h_proto = htons(ETH_P_ARP);
578:
579: rah->ar_hrd = htons(1);
580: rah->ar_pro = htons(ETH_P_IP);
581: rah->ar_hln = ETH_ALEN;
582: rah->ar_pln = 4;
583: rah->ar_op = htons(ARPOP_REPLY);
584: memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
585: memcpy(rah->ar_sip, ah->ar_tip, 4);
586: memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
587: memcpy(rah->ar_tip, ah->ar_sip, 4);
588: slirp_output(arp_reply, sizeof(arp_reply));
589: }
590: break;
591: default:
592: break;
593: }
594: }
595:
596: void slirp_input(const uint8_t *pkt, int pkt_len)
597: {
598: struct mbuf *m;
599: int proto;
600:
601: if (pkt_len < ETH_HLEN)
602: return;
603:
604: proto = ntohs(*(uint16_t *)(pkt + 12));
605: switch(proto) {
606: case ETH_P_ARP:
607: arp_input(pkt, pkt_len);
608: break;
609: case ETH_P_IP:
610: m = m_get();
611: if (!m)
612: return;
1.1.1.3 ! root 613: /* Note: we add to align the IP header */
! 614: m->m_len = pkt_len + 2;
! 615: memcpy(m->m_data + 2, pkt, pkt_len);
1.1 root 616:
1.1.1.3 ! root 617: m->m_data += 2 + ETH_HLEN;
! 618: m->m_len -= 2 + ETH_HLEN;
1.1 root 619:
620: ip_input(m);
621: break;
622: default:
623: break;
624: }
625: }
626:
627: /* output the IP packet to the ethernet device */
628: void if_encap(const uint8_t *ip_data, int ip_data_len)
629: {
630: uint8_t buf[1600];
631: struct ethhdr *eh = (struct ethhdr *)buf;
632:
633: if (ip_data_len + ETH_HLEN > sizeof(buf))
634: return;
635:
636: memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
637: memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
638: /* XXX: not correct */
639: eh->h_source[5] = CTL_ALIAS;
640: eh->h_proto = htons(ETH_P_IP);
641: memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
642: slirp_output(buf, ip_data_len + ETH_HLEN);
643: }
644:
645: int slirp_redir(int is_udp, int host_port,
646: struct in_addr guest_addr, int guest_port)
647: {
648: if (is_udp) {
649: if (!udp_listen(htons(host_port), guest_addr.s_addr,
650: htons(guest_port), 0))
651: return -1;
652: } else {
653: if (!solisten(htons(host_port), guest_addr.s_addr,
654: htons(guest_port), 0))
655: return -1;
656: }
657: return 0;
658: }
659:
660: int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
661: int guest_port)
662: {
663: return add_exec(&exec_list, do_pty, (char *)args,
664: addr_low_byte, htons(guest_port));
665: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.