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