📄 slirp.c
字号:
#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 + -