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

📄 slirp.c

📁 一个Windows下的Linux专用虚拟机
💻 C
📖 第 1 页 / 共 2 页
字号:
		}	}        *pnfds = nfds;}	void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds){    struct socket *so, *so_next;    int ret;    global_readfds = readfds;    global_writefds = writefds;    global_xfds = xfds;	/* Update time */	updtime();		/*	 * See if anything has timed out 	 */	if (link_up) {		if (time_fasttimo && ((curtime - time_fasttimo) >= 2)) {			tcp_fasttimo();			time_fasttimo = 0;		}		if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {			ip_slowtimo();			tcp_slowtimo();			last_slowtimo = curtime;		}	}		/*	 * Check sockets	 */	if (link_up) {		/*		 * Check TCP sockets		 */		for (so = tcb.so_next; so != &tcb; so = so_next) {			so_next = so->so_next;						/*			 * FD_ISSET is meaningless on these sockets			 * (and they can crash the program)			 */			if (so->so_state & SS_NOFDREF || so->s == -1)			   continue;						/*			 * Check for URG data			 * This will soread as well, so no need to			 * test for readfds below if this succeeds			 */			if (FD_ISSET(so->s, xfds))			   sorecvoob(so);			/*			 * Check sockets for reading			 */			else if (FD_ISSET(so->s, readfds)) {				/*				 * Check for incoming connections				 */				if (so->so_state & SS_FACCEPTCONN) {					tcp_connect(so);					continue;				} /* else */				ret = soread(so);								/* Output it if we read something */				if (ret > 0)				   tcp_output(sototcpcb(so));			}						/*			 * Check sockets for writing			 */			if (FD_ISSET(so->s, writefds)) {			  /*			   * Check for non-blocking, still-connecting sockets			   */			  if (so->so_state & SS_ISFCONNECTING) {			    /* Connected */			    so->so_state &= ~SS_ISFCONNECTING;			    			    ret = send(so->s, (void*)&ret, 0, 0);			    if (ret < 0) {			      /* XXXXX Must fix, zero bytes is a NOP */			      if (errno == EAGAIN || errno == EWOULDBLOCK ||				  errno == EINPROGRESS || errno == ENOTCONN)				continue;			      			      /* else failed */			      so->so_state = SS_NOFDREF;			    }			    /* else so->so_state &= ~SS_ISFCONNECTING; */			    			    /*			     * Continue tcp_input			     */			    tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);			    /* continue; */			  } else			    ret = sowrite(so);			  /*			   * XXXXX If we wrote something (a lot), there 			   * could be a need for a window update.			   * In the worst case, the remote will send			   * a window probe to get things going again			   */			}						/*			 * Probe a still-connecting, non-blocking socket			 * to check if it's still alive	 	 	 */#ifdef PROBE_CONN			if (so->so_state & SS_ISFCONNECTING) {			  ret = recv(so->s, (char *)&ret, 0,0);			  			  if (ret < 0) {			    /* XXX */			    if (errno == EAGAIN || errno == EWOULDBLOCK ||				errno == EINPROGRESS || errno == ENOTCONN)			      continue; /* Still connecting, continue */			    			    /* else failed */			    so->so_state = SS_NOFDREF;			    			    /* tcp_input will take care of it */			  } else {			    ret = send(so->s, &ret, 0,0);			    if (ret < 0) {			      /* XXX */			      if (errno == EAGAIN || errno == EWOULDBLOCK ||				  errno == EINPROGRESS || errno == ENOTCONN)				continue;			      /* else failed */			      so->so_state = SS_NOFDREF;			    } else			      so->so_state &= ~SS_ISFCONNECTING;			    			  }			  tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);			} /* SS_ISFCONNECTING */#endif		}				/*		 * Now UDP sockets.		 * Incoming packets are sent straight away, they're not buffered.		 * Incoming UDP data isn't buffered either.		 */		for (so = udb.so_next; so != &udb; so = so_next) {			so_next = so->so_next;						if (so->s != -1 && FD_ISSET(so->s, readfds)) {                            sorecvfrom(so);                        }		}	}		/*	 * See if we can start outputting	 */	if (if_queued && link_up)	   if_start();	/* clear global file descriptor sets.	 * these reside on the stack in vl.c	 * so they're unusable if we're not in	 * slirp_select_fill or slirp_select_poll.	 */	 global_readfds = NULL;	 global_writefds = NULL;	 global_xfds = NULL;}#define ETH_ALEN 6#define ETH_HLEN 14#define ETH_P_IP	0x0800		/* Internet Protocol packet	*/#define ETH_P_ARP	0x0806		/* Address Resolution packet	*/#define	ARPOP_REQUEST	1		/* ARP request			*/#define	ARPOP_REPLY	2		/* ARP reply			*/struct ethhdr {	unsigned char	h_dest[ETH_ALEN];	/* destination eth addr	*/	unsigned char	h_source[ETH_ALEN];	/* source ether addr	*/	unsigned short	h_proto;		/* packet type ID field	*/};struct arphdr{	unsigned short	ar_hrd;		/* format of hardware address	*/	unsigned short	ar_pro;		/* format of protocol address	*/	unsigned char	ar_hln;		/* length of hardware address	*/	unsigned char	ar_pln;		/* length of protocol address	*/	unsigned short	ar_op;		/* ARP opcode (command)		*/	 /*	  *	 Ethernet looks like this : This bit is variable sized however...	  */	unsigned char		ar_sha[ETH_ALEN];	/* sender hardware address	*/	unsigned char		ar_sip[4];		/* sender IP address		*/	unsigned char		ar_tha[ETH_ALEN];	/* target hardware address	*/	unsigned char		ar_tip[4];		/* target IP address		*/};void arp_input(const uint8_t *pkt, int pkt_len){    struct ethhdr *eh = (struct ethhdr *)pkt;    struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);    uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];    struct ethhdr *reh = (struct ethhdr *)arp_reply;    struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);    int ar_op;    struct ex_list *ex_ptr;    ar_op = ntohs(ah->ar_op);    switch(ar_op) {    case ARPOP_REQUEST:        if (!memcmp(ah->ar_tip, &special_addr, 3)) {            if (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)                 goto arp_ok;            for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {                if (ex_ptr->ex_addr == ah->ar_tip[3])                    goto arp_ok;            }            return;        arp_ok:            /* ARP request for alias/dns mac address */            memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);            memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);            reh->h_source[5] = ah->ar_tip[3];            reh->h_proto = htons(ETH_P_ARP);            rah->ar_hrd = htons(1);            rah->ar_pro = htons(ETH_P_IP);            rah->ar_hln = ETH_ALEN;            rah->ar_pln = 4;            rah->ar_op = htons(ARPOP_REPLY);            memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);            memcpy(rah->ar_sip, ah->ar_tip, 4);            memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);            memcpy(rah->ar_tip, ah->ar_sip, 4);            slirp_output(arp_reply, sizeof(arp_reply));        }        break;    case ARPOP_REPLY:        if (!memcmp(ah->ar_sip, &client_addr, 4)) {            memcpy(client_ethaddr, eh->h_source, ETH_ALEN);        }        break;    default:        break;    }}void slirp_input(const uint8_t *pkt, int pkt_len){    struct mbuf *m;    int proto;    if (pkt_len < ETH_HLEN)        return;        proto = ntohs(*(uint16_t *)(pkt + 12));    switch(proto) {    case ETH_P_ARP:        arp_input(pkt, pkt_len);        break;    case ETH_P_IP:        m = m_get();        if (!m)            return;        /* Note: we add to align the IP header */        m->m_len = pkt_len + 2;        memcpy(m->m_data + 2, pkt, pkt_len);        m->m_data += 2 + ETH_HLEN;        m->m_len -= 2 + ETH_HLEN;        ip_input(m);        break;    default:        break;    }}/* output the IP packet to the ethernet device */void if_encap(const uint8_t *ip_data, int ip_data_len){    uint8_t buf[1600];    struct ethhdr *eh = (struct ethhdr *)buf;    struct arphdr *rah = (struct arphdr *)(buf + ETH_HLEN);    if (ip_data_len + ETH_HLEN > sizeof(buf))        return;    if(!memcmp(client_ethaddr,bcast_ethaddr,6))    {	/* make an ARP request to have the client address */	memcpy(eh->h_dest, bcast_ethaddr, ETH_ALEN);	memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);	eh->h_source[5] = CTL_ALIAS;	eh->h_proto = htons(ETH_P_ARP);	rah->ar_hrd = htons(1);	rah->ar_pro = htons(ETH_P_IP);	rah->ar_hln = ETH_ALEN;	rah->ar_pln = 4;	rah->ar_op = htons(ARPOP_REQUEST);	memcpy(rah->ar_sha, eh->h_source, ETH_ALEN);	memcpy(rah->ar_sip, &special_addr, 4);	rah->ar_sip[3]=CTL_ALIAS;	memcpy(rah->ar_tha, bcast_ethaddr, ETH_ALEN);	memcpy(rah->ar_tip, &client_addr, 4); 	slirp_output(buf, sizeof(struct arphdr)+ ETH_HLEN);/* XXX: We loose the first packet here, cause client_ethaddr    is bcast_ethaddr. */    }    memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);    memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);    /* XXX: not correct */    eh->h_source[5] = CTL_ALIAS;    eh->h_proto = htons(ETH_P_IP);    memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);    slirp_output(buf, ip_data_len + ETH_HLEN);}int slirp_redir(int is_udp, int host_port,                 struct in_addr guest_addr, int guest_port){    if (is_udp) {        if (!udp_listen(htons(host_port), guest_addr.s_addr,                         htons(guest_port), 0))            return -1;    } else {        if (!solisten(htons(host_port), guest_addr.s_addr,                       htons(guest_port), 0))            return -1;    }    return 0;}int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,                   int guest_port){    return add_exec(&exec_list, do_pty, (char *)args,                     addr_low_byte, htons(guest_port));}

⌨️ 快捷键说明

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