int slirp_init(void) { // debug_init("/tmp/slirp.log", DEBUG_DEFAULT); #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); if (get_dns_addr(&dns_addr) < 0) return -1; inet_aton(CTL_SPECIAL, &special_addr); alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS); getouraddr(); return 0; }
/* * Translate addr in host addr when it is a virtual address */ void sotranslate_out(struct socket *so, struct sockaddr_storage *addr) { Slirp *slirp = so->slirp; struct sockaddr_in *sin = (struct sockaddr_in *)addr; switch (addr->ss_family) { case AF_INET: if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == slirp->vnetwork_addr.s_addr) { /* It's an alias */ if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { if (get_dns_addr(&sin->sin_addr) < 0) { sin->sin_addr = loopback_addr; } } else { sin->sin_addr = loopback_addr; } } DEBUG_MISC((dfd, " addr.sin_port=%d, " "addr.sin_addr.s_addr=%.16s\n", ntohs(sin->sin_port), inet_ntoa(sin->sin_addr))); break; default: break; } }
/* * Translate addr in host addr when it is a virtual address */ void sotranslate_out(struct socket *so, struct sockaddr_storage *addr) { Slirp *slirp = so->slirp; struct sockaddr_in *sin = (struct sockaddr_in *)addr; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; switch (addr->ss_family) { case AF_INET: if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == slirp->vnetwork_addr.s_addr) { /* It's an alias */ if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { if (get_dns_addr(&sin->sin_addr) < 0) { sin->sin_addr = loopback_addr; } } else { sin->sin_addr = loopback_addr; } } DEBUG_MISC((dfd, " addr.sin_port=%d, " "addr.sin_addr.s_addr=%.16s\n", ntohs(sin->sin_port), inet_ntoa(sin->sin_addr))); break; case AF_INET6: if (in6_equal_net(&so->so_faddr6, &slirp->vprefix_addr6, slirp->vprefix_len)) { if (in6_equal(&so->so_faddr6, &slirp->vnameserver_addr6)) { uint32_t scope_id; if (get_dns6_addr(&sin6->sin6_addr, &scope_id) >= 0) { sin6->sin6_scope_id = scope_id; } else { sin6->sin6_addr = in6addr_loopback; } } else { sin6->sin6_addr = in6addr_loopback; } } break; default: break; } }
/* * sendto() a socket */ int sosendto(struct socket *so, struct mbuf *m) { Slirp *slirp = so->slirp; int ret; struct sockaddr_in addr; DEBUG_CALL("sosendto"); DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("m = %lx", (long)m); addr.sin_family = AF_INET; if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == slirp->vnetwork_addr.s_addr) { /* It's an alias */ if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { if (get_dns_addr(&addr.sin_addr) < 0) addr.sin_addr = loopback_addr; } else { addr.sin_addr = loopback_addr; } } else addr.sin_addr = so->so_faddr; addr.sin_port = so->so_fport; DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", ntohs(addr.sin_port), inet_ntoa(addr.sin_addr))); /* Don't care what port we get */ ret = sendto(so->s, m->m_data, m->m_len, 0, (struct sockaddr *)&addr, sizeof (struct sockaddr)); if (ret < 0) return -1; /* * Kill the socket if there's no reply in 4 minutes, * but only if it's an expirable socket */ if (so->so_expire) so->so_expire = curtime + SO_EXPIRE; so->so_state &= SS_PERSISTENT_MASK; so->so_state |= SS_ISFCONNECTED; /* So that it gets select()ed */ return 0; }
void slirp_init(int restricted, char *special_ip) { #if defined(DEBUG) debug_init("/tmp/slirp.log", DEBUG_DEFAULT); #endif #ifdef _WIN32 { WSADATA Data; WSAStartup(MAKEWORD(2,0), &Data); atexit(slirp_cleanup); } #endif link_up = 1; slirp_restrict = restricted; if_init(); ip_init(); /* Initialise mbufs *after* setting the MTU */ m_init(); /* set default addresses */ inet_aton("127.0.0.1", &loopback_addr); if (get_dns_addr(&dns_addr) < 0) { dns_addr = loopback_addr; fprintf (stderr, "Warning: No DNS servers found\n"); } if (special_ip) slirp_special_ip = special_ip; inet_aton(slirp_special_ip, &special_addr); alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS); getouraddr(); register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL); }
void slirp_init(int restricted, const char *special_ip) { #ifdef _WIN32 { WSADATA Data; WSAStartup(MAKEWORD(2,0), &Data); atexit(slirp_cleanup); } #endif link_up = 1; slirp_restrict = restricted; if_init(); ip_init(); m_init(); inet_aton("127.0.0.1", &loopback_addr); if (get_dns_addr(&dns_addr) < 0) { dns_addr = loopback_addr; fprintf (stderr, "Warning: No DNS servers found\n"); } if (special_ip) slirp_special_ip = special_ip; inet_aton(slirp_special_ip, &special_addr); alias_addr.s_addr = special_addr.s_addr | htonl(CTL_ALIAS); getouraddr(); register_savevm("slirp", 0, 1, slirp_state_save, slirp_state_load, NULL); }
/* * Process a received ICMP message. */ void icmp_input(struct mbuf *m, int hlen) { register struct icmp *icp; register struct ip *ip=mtod(m, struct ip *); int icmplen=ip->ip_len; Slirp *slirp = m->slirp; DEBUG_CALL("icmp_input"); DEBUG_ARG("m = %lx", (long )m); DEBUG_ARG("m_len = %d", m->m_len); /* * Locate icmp structure in mbuf, and check * that its not corrupted and of at least minimum length. */ if (icmplen < ICMP_MINLEN) { /* min 8 bytes payload */ freeit: m_free(m); goto end_error; } m->m_len -= hlen; m->m_data += hlen; icp = mtod(m, struct icmp *); if (cksum(m, icmplen)) { goto freeit; } m->m_len += hlen; m->m_data -= hlen; DEBUG_ARG("icmp_type = %d", icp->icmp_type); switch (icp->icmp_type) { case ICMP_ECHO: ip->ip_len += hlen; /* since ip_input subtracts this */ if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) { icmp_reflect(m); } else if (slirp->restricted) { goto freeit; } else { struct socket *so; struct sockaddr_in addr; if ((so = socreate(slirp)) == NULL) goto freeit; if (icmp_send(so, m, hlen) == 0) { return; } if(udp_attach(so) == -1) { DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n", errno,strerror(errno))); sofree(so); m_free(m); goto end_error; } so->so_m = m; so->so_faddr = ip->ip_dst; so->so_fport = htons(7); so->so_laddr = ip->ip_src; so->so_lport = htons(9); so->so_iptos = ip->ip_tos; so->so_type = IPPROTO_ICMP; so->so_state = SS_ISFCONNECTED; /* Send the packet */ addr.sin_family = AF_INET; if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) == slirp->vnetwork_addr.s_addr) { /* It's an alias */ if (so->so_faddr.s_addr == slirp->vnameserver_addr.s_addr) { if (get_dns_addr(&addr.sin_addr) < 0) addr.sin_addr = loopback_addr; } else { addr.sin_addr = loopback_addr; } } else { addr.sin_addr = so->so_faddr; } addr.sin_port = so->so_fport; if(sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0, (struct sockaddr *)&addr, sizeof(addr)) == -1) { DEBUG_MISC((dfd,"icmp_input udp sendto tx errno = %d-%s\n", errno,strerror(errno))); icmp_error(m, ICMP_UNREACH,ICMP_UNREACH_NET, 0,strerror(errno)); udp_detach(so); } } /* if ip->ip_dst.s_addr == alias_addr.s_addr */ break; case ICMP_UNREACH: /* XXX? report error? close socket? */ case ICMP_TIMXCEED: case ICMP_PARAMPROB: case ICMP_SOURCEQUENCH: case ICMP_TSTAMP: case ICMP_MASKREQ: case ICMP_REDIRECT: m_free(m); break; default: m_free(m); } /* swith */ end_error: /* m is m_free()'d xor put in a socket xor or given to ip_send */ return; }