⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slirp.c

📁 一个Windows下的Linux专用虚拟机
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "slirp.h"#if 0/* host address */struct in_addr our_addr;#endif/* host dns address */static struct in_addr dns_addr;/* host loopback address */struct in_addr loopback_addr;	/* 127.0.0.1 *//* address for slirp virtual addresses */struct in_addr special_addr;	/* 10.0.2.0 *//* virtual address alias for host */struct in_addr alias_addr;	/* 10.0.2.2  windows */struct in_addr client_addr;	/* 10.0.2.15 Linux */const uint8_t special_ethaddr[6] = {     0x52, 0x54, 0x00, 0x12, 0x35, 0x00};uint8_t client_ethaddr[6] = {     0xff, 0xff, 0xff, 0xff, 0xff, 0xff};const uint8_t bcast_ethaddr[6] = {     0xff, 0xff, 0xff, 0xff, 0xff, 0xff};int do_slowtimo;int link_up;struct timeval tt;FILE *lfd;struct ex_list *exec_list;/* XXX: suppress those select globals */fd_set *global_readfds, *global_writefds, *global_xfds;char slirp_hostname[33];#ifdef _WIN32static int get_dns_addr(struct in_addr *pdns_addr){    FIXED_INFO *FixedInfo;    ULONG    BufLen;    DWORD    ret;    IP_ADDR_STRING *pIPAddr;    struct in_addr tmp_addr;        FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));    if (!FixedInfo)	return -1;    BufLen = sizeof(FIXED_INFO);       if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {        GlobalFree(FixedInfo);        FixedInfo = GlobalAlloc(GPTR, BufLen);	if (!FixedInfo)	    return -1;    }	    if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {        printf("GetNetworkParams failed. ret = %08x\n", (u_int)ret );        GlobalFree(FixedInfo);        return -1;    }         pIPAddr = &(FixedInfo->DnsServerList);    inet_aton(pIPAddr->IpAddress.String, &tmp_addr);    *pdns_addr = tmp_addr;#if 0    printf( "DNS Servers:\n" );    printf( "DNS Addr:%s\n", pIPAddr->IpAddress.String );        pIPAddr = FixedInfo -> DnsServerList.Next;    while ( pIPAddr ) {            printf( "DNS Addr:%s\n", pIPAddr ->IpAddress.String );            pIPAddr = pIPAddr ->Next;    }#endif    GlobalFree(FixedInfo);    return 0;}#elsestatic int get_dns_addr(struct in_addr *pdns_addr){    char buff[512];    char buff2[256];    FILE *f;    int found = 0;    struct in_addr tmp_addr;        f = fopen("/etc/resolv.conf", "r");    if (!f)        return -1;    lprint("IP address of your DNS(s): ");    while (fgets(buff, 512, f) != NULL) {        if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {            if (!inet_aton(buff2, &tmp_addr))                continue;            if (is_localhost(tmp_addr))                tmp_addr = alias_addr;            /* If it's the first one, set it to dns_addr */            if (!found)                *pdns_addr = tmp_addr;            else                lprint(", ");            if (++found > 3) {                lprint("(more)");                break;            } else                lprint("%s", inet_ntoa(tmp_addr));        }    }    fclose(f);    if (!found)        return -1;    return 0;}#endif/* Get DNS-Address from host, cached for 10 Seconds (SO_EXPIREFAST) */struct in_addr cached_dns_addr (void){    static long dns_expire;        if (!dns_addr.s_addr || curtime > dns_expire) {        if (get_dns_addr(&dns_addr) < 0) {            fprintf(stderr, "Could not get DNS address\n");            return (dns_addr);        }        dns_expire = curtime + SO_EXPIREFAST;    }    return (dns_addr);}#ifdef _WIN32static void slirp_cleanup(void){    WSACleanup();}#endifvoid slirp_init(void){#ifdef DEBUG    debug_init("slirp.log", DEBUG_DEFAULT);#endif    #ifdef _WIN32    {        WSADATA Data;        WSAStartup(MAKEWORD(2,0), &Data);	atexit(slirp_cleanup);    }#endif    link_up = 1;    if_init();    ip_init();    /* Initialise mbufs *after* setting the MTU */    m_init();    /* set default addresses */    inet_aton("127.0.0.1", &loopback_addr);    inet_aton(CTL_SPECIAL, &special_addr);    alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS);    client_addr.s_addr = special_addr.s_addr | htonl(CTL_CLIENT);#if 0    getouraddr();#endif}#define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)#define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)#define UPD_NFDS(x) if (nfds < (x)) nfds = (x)/* * curtime kept to an accuracy of 1ms */#ifdef _WIN32static void updtime(void){    struct _timeb tb;    _ftime(&tb);    curtime = (u_int)tb.time * (u_int)1000;    curtime += (u_int)tb.millitm;}#elsestatic void updtime(void){	gettimeofday(&tt, 0);		curtime = (u_int)tt.tv_sec * (u_int)1000;	curtime += (u_int)tt.tv_usec / (u_int)1000;		if ((tt.tv_usec % 1000) >= 500)	   curtime++;}#endifvoid slirp_select_fill(int *pnfds,                        fd_set *readfds, fd_set *writefds, fd_set *xfds){    struct socket *so, *so_next;    struct timeval timeout;    int nfds;    int tmp_time;    /* fail safe */    global_readfds = NULL;    global_writefds = NULL;    global_xfds = NULL;        nfds = *pnfds;	/*	 * First, TCP sockets	 */	do_slowtimo = 0;	if (link_up) {		/* 		 * *_slowtimo needs calling if there are IP fragments		 * in the fragment queue, or there are TCP connections active		 */		do_slowtimo = ((tcb.so_next != &tcb) ||			       ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));				for (so = tcb.so_next; so != &tcb; so = so_next) {			so_next = so->so_next;						/*			 * See if we need a tcp_fasttimo			 */			if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)			   time_fasttimo = curtime; /* Flag when we want a fasttimo */						/*			 * NOFDREF can include still connecting to local-host,			 * newly socreated() sockets etc. Don't want to select these.	 		 */			if (so->so_state & SS_NOFDREF || so->s == -1)			   continue;						/*			 * Set for reading sockets which are accepting			 */			if (so->so_state & SS_FACCEPTCONN) {                                FD_SET(so->s, readfds);				UPD_NFDS(so->s);				continue;			}						/*			 * Set for writing sockets which are connecting			 */			if (so->so_state & SS_ISFCONNECTING) {				FD_SET(so->s, writefds);				UPD_NFDS(so->s);				continue;			}						/*			 * Set for writing if we are connected, can send more, and			 * we have something to send			 */			if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {				FD_SET(so->s, writefds);				UPD_NFDS(so->s);			}						/*			 * Set for reading (and urgent data) if we are connected, can			 * receive more, and we have room for it XXX /2 ?			 */			if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {				FD_SET(so->s, readfds);				FD_SET(so->s, xfds);				UPD_NFDS(so->s);			}		}				/*		 * UDP sockets		 */		for (so = udb.so_next; so != &udb; so = so_next) {			so_next = so->so_next;						/*			 * See if it's timed out			 */			if (so->so_expire) {				if (so->so_expire <= curtime) {					udp_detach(so);					continue;				} else					do_slowtimo = 1; /* Let socket expire */			}						/*			 * When UDP packets are received from over the			 * link, they're sendto()'d straight away, so			 * no need for setting for writing			 * Limit the number of packets queued by this session			 * to 4.  Note that even though we try and limit this			 * to 4 packets, the session could have more queued			 * if the packets needed to be fragmented			 * (XXX <= 4 ?)			 */			if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {				FD_SET(so->s, readfds);				UPD_NFDS(so->s);			}		}	}		/*	 * Setup timeout to use minimum CPU usage, especially when idle	 */		/* 	 * First, see the timeout needed by *timo	 */	timeout.tv_sec = 0;	timeout.tv_usec = -1;	/*	 * If a slowtimo is needed, set timeout to 500ms from the last	 * slow timeout. If a fast timeout is needed, set timeout within	 * 200ms of when it was requested.	 */	if (do_slowtimo) {		/* XXX + 10000 because some select()'s aren't that accurate */		timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;		if (timeout.tv_usec < 0)		   timeout.tv_usec = 0;		else if (timeout.tv_usec > 510000)		   timeout.tv_usec = 510000;				/* Can only fasttimo if we also slowtimo */		if (time_fasttimo) {			tmp_time = (200 - (curtime - time_fasttimo)) * 1000;			if (tmp_time < 0)			   tmp_time = 0;						/* Choose the smallest of the 2 */			if (tmp_time < timeout.tv_usec)			   timeout.tv_usec = (u_int)tmp_time;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -