diff --git a/bochs/iodev/network/eth_slirp.cc b/bochs/iodev/network/eth_slirp.cc index 6e945e6f5..788c9a19e 100644 --- a/bochs/iodev/network/eth_slirp.cc +++ b/bochs/iodev/network/eth_slirp.cc @@ -325,10 +325,10 @@ bx_slirp_pktmover_c::bx_slirp_pktmover_c(const char *netif, config.vnameserver6.s6_addr[15] |= 3; } } - slirp = slirp_new(&config, &callbacks, this); slirplog = new logfunctions(); sprintf(prefix, "SLIRP%d", bx_slirp_instances); slirplog->put(prefix); + slirp = slirp_new(&config, &callbacks, this); #if !BX_HAVE_LIBSLIRP if (debug_switches != 0) { slirplog->setonoff(LOGLEV_DEBUG, ACT_REPORT); diff --git a/bochs/iodev/network/slirp/dnssearch.cc b/bochs/iodev/network/slirp/dnssearch.cc index 13cd56889..6ce0075e4 100644 --- a/bochs/iodev/network/slirp/dnssearch.cc +++ b/bochs/iodev/network/slirp/dnssearch.cc @@ -115,14 +115,13 @@ static void domain_fixup_order(CompactDomain *cd, size_t n) } } -static void domain_mklabels(Slirp *s, CompactDomain *cd, const char *input) +static void domain_mklabels(CompactDomain *cd, const char *input) { uint8_t *len_marker = cd->labels; uint8_t *output = len_marker; /* pre-incremented */ const char *in = input; char cur_chr; size_t len = 0; - char msg[80]; if (cd->len == 0) { goto fail; @@ -154,8 +153,7 @@ static void domain_mklabels(Slirp *s, CompactDomain *cd, const char *input) return; fail: - sprintf(msg, "failed to parse domain name '%s'\n", input); - slirplog_error(msg); + slirplog_error("failed to parse domain name '%s'", input); cd->len = 0; } @@ -271,7 +269,7 @@ int translate_dnssearch(Slirp *s, const char **names) outptr = result; for (i = 0; i < num_domains; i++) { domains[i].labels = outptr; - domain_mklabels(s, domains + i, names[i]); + domain_mklabels(domains + i, names[i]); if (domains[i].len == 0) { /* Bogus entry, reject it all */ free(domains); diff --git a/bochs/iodev/network/slirp/ip6_icmp.cc b/bochs/iodev/network/slirp/ip6_icmp.cc index 00779cc82..537856910 100644 --- a/bochs/iodev/network/slirp/ip6_icmp.cc +++ b/bochs/iodev/network/slirp/ip6_icmp.cc @@ -109,7 +109,7 @@ void icmp6_forward_error(struct mbuf *m, uint8_t type, uint8_t code, struct in6_ /* TODO: Handle this case */ break; default: - fprintf(stderr, "Unknown ICMP code\n"); + slirplog_error("Unknown ICMP code"); } t->m_data += ICMP6_ERROR_MINLEN; memcpy(t->m_data, m->m_data, error_data_len); @@ -419,7 +419,7 @@ void icmp6_input(struct mbuf *m) icmp6_send_echoreply(m, slirp, ip, icmp); } else { /* TODO */ - fprintf(stderr, "external icmpv6 not supported yet\n"); + slirplog_error("external icmpv6 not supported yet"); } break; diff --git a/bochs/iodev/network/slirp/ip6_input.cc b/bochs/iodev/network/slirp/ip6_input.cc index 0e81db305..4e66bcf50 100644 --- a/bochs/iodev/network/slirp/ip6_input.cc +++ b/bochs/iodev/network/slirp/ip6_input.cc @@ -39,7 +39,7 @@ void ip6_input(struct mbuf *m) DEBUG_ARG("m = %p", m); DEBUG_ARG("m_len = %d", m->m_len); - if (m->m_len < sizeof(struct ip6)) { + if (m->m_len < (int)sizeof(struct ip6)) { goto bad; } @@ -49,7 +49,7 @@ void ip6_input(struct mbuf *m) goto bad; } - if (ntohs(ip6->ip_pl) + sizeof(struct ip6) > slirp->if_mtu) { + if (ntohs(ip6->ip_pl) + sizeof(struct ip6) > (unsigned)slirp->if_mtu) { icmp6_send_error(m, ICMP6_TOOBIG, 0); goto bad; } @@ -57,7 +57,7 @@ void ip6_input(struct mbuf *m) // Check if the message size is big enough to hold what's // set in the payload length header. If not this is an invalid // packet - if (m->m_len < ntohs(ip6->ip_pl) + sizeof(struct ip6)) { + if (m->m_len < (int)(ntohs(ip6->ip_pl) + sizeof(struct ip6))) { goto bad; } diff --git a/bochs/iodev/network/slirp/libslirp.h b/bochs/iodev/network/slirp/libslirp.h index a2237473a..efb1679ce 100644 --- a/bochs/iodev/network/slirp/libslirp.h +++ b/bochs/iodev/network/slirp/libslirp.h @@ -236,11 +236,25 @@ int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, int host_port); +#define SLIRP_HOSTFWD_UDP 1 +#define SLIRP_HOSTFWD_V6ONLY 2 +int slirp_add_hostxfwd(Slirp *slirp, + const struct sockaddr *haddr, socklen_t haddrlen, + const struct sockaddr *gaddr, socklen_t gaddrlen, + int flags); +int slirp_remove_hostxfwd(Slirp *slirp, + const struct sockaddr *haddr, socklen_t haddrlen, + int flags); + /* Set up port forwarding between a port in the guest network and a * command running on the host */ int slirp_add_exec(Slirp *slirp, const char *cmdline, struct in_addr *guest_addr, int guest_port); +/* Set up port forwarding between a port in the guest network and a + * Unix port on the host */ +int slirp_add_unix(Slirp *slirp, const char *unixsock, + struct in_addr *guest_addr, int guest_port); /* Set up port forwarding between a port in the guest network and a * callback that will receive the data coming from the port */ int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque, @@ -262,6 +276,12 @@ void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port, int slirp_remove_guestfwd(Slirp *slirp, struct in_addr guest_addr, int guest_port); +/* Return a human-readable state of the slirp stack */ +char *slirp_connection_info(Slirp *slirp); + +/* Return a human-readable state of the NDP/ARP tables */ +char *slirp_neighbor_info(Slirp *slirp); + /* Return the version of the slirp implementation */ const char *slirp_version_string(void); diff --git a/bochs/iodev/network/slirp/misc.cc b/bochs/iodev/network/slirp/misc.cc index bbfffd42f..9608f529c 100644 --- a/bochs/iodev/network/slirp/misc.cc +++ b/bochs/iodev/network/slirp/misc.cc @@ -91,6 +91,18 @@ int open_unix(struct socket *so, const char *unixpath) return 0; } +char *slirp_connection_info(Slirp *slirp) +{ + /* not implemented */ + return NULL; +} + +char *slirp_neighbor_info(Slirp *slirp) +{ + /* not implemented */ + return NULL; +} + int slirp_bind_outbound(struct socket *so, unsigned short af) { int ret = 0; diff --git a/bochs/iodev/network/slirp/ncsi.cc b/bochs/iodev/network/slirp/ncsi.cc index 90c3f7cbf..d8b63df1b 100644 --- a/bochs/iodev/network/slirp/ncsi.cc +++ b/bochs/iodev/network/slirp/ncsi.cc @@ -145,7 +145,7 @@ static int ncsi_rsp_handler_oem(Slirp *slirp, const struct ncsi_pkt_hdr *nh, } /* Check for manufacturer id and Find the handler */ - for (i = 0; i < SLIRP_N_ELEMENTS(ncsi_rsp_oem_handlers); i++) { + for (i = 0; i < (int)SLIRP_N_ELEMENTS(ncsi_rsp_oem_handlers); i++) { if (ncsi_rsp_oem_handlers[i].mfr_id == mfr_id) { if (ncsi_rsp_oem_handlers[i].handler) nrh = &ncsi_rsp_oem_handlers[i]; @@ -280,7 +280,7 @@ void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) uint32_t checksum; uint32_t *pchecksum; - if (pkt_len < ETH_HLEN + sizeof(struct ncsi_pkt_hdr)) { + if (pkt_len < (int)(ETH_HLEN + sizeof(struct ncsi_pkt_hdr))) { return; /* packet too short */ } @@ -290,7 +290,7 @@ void ncsi_input(Slirp *slirp, const uint8_t *pkt, int pkt_len) memset(reh->h_source, 0xff, ETH_ALEN); reh->h_proto = htons(ETH_P_NCSI); - for (i = 0; i < SLIRP_N_ELEMENTS(ncsi_rsp_handlers); i++) { + for (i = 0; i < (int)SLIRP_N_ELEMENTS(ncsi_rsp_handlers); i++) { if (ncsi_rsp_handlers[i].type == nh->type + 0x80) { handler = &ncsi_rsp_handlers[i]; break; diff --git a/bochs/iodev/network/slirp/slirp.cc b/bochs/iodev/network/slirp/slirp.cc index 2df1766e2..3203f801e 100644 --- a/bochs/iodev/network/slirp/slirp.cc +++ b/bochs/iodev/network/slirp/slirp.cc @@ -1343,6 +1343,7 @@ int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, addr_len = sizeof(addr); if ((so->so_state & SS_HOSTFWD) && getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 && + addr_len == sizeof(addr) && addr.sin_family == AF_INET && addr.sin_addr.s_addr == host_addr.s_addr && addr.sin_port == port) { @@ -1374,6 +1375,83 @@ int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr, return 0; } +int slirp_remove_hostxfwd(Slirp *slirp, + const struct sockaddr *haddr, socklen_t haddrlen, + int flags) +{ + struct socket *so; + struct socket *head = (flags & SLIRP_HOSTFWD_UDP ? &slirp->udb : &slirp->tcb); + struct sockaddr_storage addr; + socklen_t addr_len; + + for (so = head->so_next; so != head; so = so->so_next) { + addr_len = sizeof(addr); + if ((so->so_state & SS_HOSTFWD) && + getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 && + sockaddr_equal(&addr, (const struct sockaddr_storage *) haddr)) { + so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque); + closesocket(so->s); + sofree(so); + return 0; + } + } + + return -1; +} + +int slirp_add_hostxfwd(Slirp *slirp, + const struct sockaddr *haddr, socklen_t haddrlen, + const struct sockaddr *gaddr, socklen_t gaddrlen, + int flags) +{ + struct sockaddr_in gdhcp_addr; + int fwd_flags = SS_HOSTFWD; + + if (flags & SLIRP_HOSTFWD_V6ONLY) + fwd_flags |= SS_HOSTFWD_V6ONLY; + + if (gaddr->sa_family == AF_INET) { + const struct sockaddr_in *gaddr_in = (const struct sockaddr_in *) gaddr; + + if (gaddrlen < sizeof(struct sockaddr_in)) { + errno = EINVAL; + return -1; + } + + if (!gaddr_in->sin_addr.s_addr) { + gdhcp_addr = *gaddr_in; + gdhcp_addr.sin_addr = slirp->vdhcp_startaddr; + gaddr = (struct sockaddr *) &gdhcp_addr; + gaddrlen = sizeof(gdhcp_addr); + } + } else { + if (gaddrlen < sizeof(struct sockaddr_in6)) { + errno = EINVAL; + return -1; + } + + /* + * Libslirp currently only provides a stateless DHCPv6 server, thus + * we can't translate "addr-any" to the guest here. Instead, we defer + * performing the translation to when it's needed. See + * soassign_guest_addr_if_needed(). + */ + } + + if (flags & SLIRP_HOSTFWD_UDP) { + if (!udpx_listen(slirp, haddr, haddrlen, + gaddr, gaddrlen, + fwd_flags)) + return -1; + } else { + if (!tcpx_listen(slirp, haddr, haddrlen, + gaddr, gaddrlen, + fwd_flags)) + return -1; + } + return 0; +} + /* TODO: IPv6 */ static bool check_guestfwd(Slirp *slirp, struct in_addr *guest_addr, int guest_port) @@ -1474,6 +1552,7 @@ struct socket *slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr, { struct socket *so; + /* TODO: IPv6 */ for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) { if (so->so_faddr.s_addr == guest_addr.s_addr && htons(so->so_fport) == guest_port) { @@ -1540,9 +1619,15 @@ void slirp_set_logfn(void *slirp, void *logfn, uint8_t debug_switches) } } -void slirplog_error(const char *msg) +void slirplog_error(const char *fmt, ...) { + va_list ap; + char msg[512]; + if (slirplog) { + va_start(ap, fmt); + vsprintf(msg, fmt, ap); + va_end(ap); slirplog->error("%s", msg); } } diff --git a/bochs/iodev/network/slirp/slirp.h b/bochs/iodev/network/slirp/slirp.h index 0ee08f6c0..0e90e781f 100644 --- a/bochs/iodev/network/slirp/slirp.h +++ b/bochs/iodev/network/slirp/slirp.h @@ -406,7 +406,7 @@ void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len); void *slirp_timer_new(Slirp *slirp, SlirpTimerId id, void *cb_opaque); /* Bochs addition */ -void slirplog_error(const char *msg); +void slirplog_error(const char *fmt, ...) BX_CPP_AttrPrintf(1, 2); void slirplog_debug(const char *fmt, ...) BX_CPP_AttrPrintf(1, 2); #endif diff --git a/bochs/iodev/network/slirp/socket.cc b/bochs/iodev/network/slirp/socket.cc index 53248726e..1e201b4b1 100644 --- a/bochs/iodev/network/slirp/socket.cc +++ b/bochs/iodev/network/slirp/socket.cc @@ -296,7 +296,7 @@ err: sofcantrcvmore(so); tcp_sockclosed(sototcpcb(so)); - fprintf(stderr, "soreadbuf buffer to small"); + slirplog_error("soreadbuf buffer to small"); return -1; } @@ -616,7 +616,7 @@ void sorecvfrom(struct socket *so) IF_MAXLINKHDR + sizeof(struct ip6) + sizeof(struct udphdr); break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } /* @@ -674,7 +674,7 @@ void sorecvfrom(struct socket *so) icmp6_send_error(so->so_m, ICMP6_UNREACH, code); break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } m_free(m); } @@ -714,7 +714,7 @@ void sorecvfrom(struct socket *so) ICMP6_UNREACH_ADDRESS); break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } m_free(m); return; @@ -732,7 +732,7 @@ void sorecvfrom(struct socket *so) (struct sockaddr_in6 *)&daddr); break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } } /* rx error */ } /* if ping packet */ @@ -803,7 +803,7 @@ struct socket *tcpx_listen(Slirp *slirp, break; #endif default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } switch (laddr->sa_family) { case AF_INET: @@ -814,7 +814,7 @@ struct socket *tcpx_listen(Slirp *slirp, DEBUG_ARG("lport = %s", portstr); break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } DEBUG_ARG("flags = %x", flags); @@ -1089,7 +1089,7 @@ void sotranslate_accept(struct socket *so) s = slirp_socket(PF_INET, SOCK_DGRAM, 0); break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); break; } if (s < 0) { @@ -1132,7 +1132,7 @@ unix2inet_cont: s = slirp_socket(PF_INET6, SOCK_DGRAM, 0); break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); break; } if (s < 0) { @@ -1163,7 +1163,7 @@ unix2inet6_cont: so->so_fport6 = htons(slirp_rand_int_range(49152, 65536)); } } else { - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } break; } /* case AF_UNIX */ @@ -1202,7 +1202,7 @@ int soassign_guest_addr_if_needed(struct socket *so) switch (so->so_ffamily) { case AF_INET: if (so->so_laddr.s_addr == INADDR_ANY) { - fprintf(stderr, "Unsupported address\n"); + slirplog_error("Unsupported address"); } break; diff --git a/bochs/iodev/network/slirp/socket.h b/bochs/iodev/network/slirp/socket.h index 0cd3cb031..5ac1318f2 100644 --- a/bochs/iodev/network/slirp/socket.h +++ b/bochs/iodev/network/slirp/socket.h @@ -146,7 +146,7 @@ static inline int sockaddr_equal(const struct sockaddr_storage *a, } #endif default: - fprintf(stderr, "unknown protocol\n"); + fprintf(stderr, "Unknown protocol\n"); } return 0; @@ -165,7 +165,7 @@ static inline socklen_t sockaddr_size(const struct sockaddr_storage *a) return sizeof(struct sockaddr_un); #endif default: - fprintf(stderr, "unknown protocol\n"); + fprintf(stderr, "Unknown protocol\n"); } return 0; diff --git a/bochs/iodev/network/slirp/tcp_input.cc b/bochs/iodev/network/slirp/tcp_input.cc index 11d120e2a..e4cce85ab 100644 --- a/bochs/iodev/network/slirp/tcp_input.cc +++ b/bochs/iodev/network/slirp/tcp_input.cc @@ -320,7 +320,7 @@ void tcp_input(struct mbuf *m, int iphlen, struct socket *inso, break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } len = ((sizeof(struct tcpiphdr) - sizeof(struct tcphdr)) + tlen); @@ -382,7 +382,7 @@ findso: fhost6->sin6_port = ti->ti_dport; break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } so = solookup(&slirp->tcp_last_so, &slirp->tcb, &lhost, &fhost); @@ -440,7 +440,7 @@ findso: case AF_INET6: break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } } @@ -668,7 +668,7 @@ findso: } break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } HTONL(ti->ti_seq); /* restore tcp header */ HTONL(ti->ti_ack); @@ -696,7 +696,7 @@ findso: icmp6_send_error(m, ICMP6_UNREACH, code); break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } } tcp_close(tp); @@ -1530,7 +1530,7 @@ int tcp_mss(struct tcpcb *tp, unsigned offer) sizeof(struct tcphdr) - sizeof(struct ip6); break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } if (offer) mss = MIN(mss, (int)offer); diff --git a/bochs/iodev/network/slirp/tcp_output.cc b/bochs/iodev/network/slirp/tcp_output.cc index c9d0d4263..475dda7b6 100644 --- a/bochs/iodev/network/slirp/tcp_output.cc +++ b/bochs/iodev/network/slirp/tcp_output.cc @@ -480,7 +480,7 @@ send: break; default: - fprintf(stderr, "Unknown protocol"); + slirplog_error("Unknown protocol"); } if (error) { diff --git a/bochs/iodev/network/slirp/tcp_subr.cc b/bochs/iodev/network/slirp/tcp_subr.cc index 20e14b831..1c949bf19 100644 --- a/bochs/iodev/network/slirp/tcp_subr.cc +++ b/bochs/iodev/network/slirp/tcp_subr.cc @@ -89,7 +89,7 @@ void tcp_template(struct tcpcb *tp) break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } n->ti_seq = 0; @@ -146,7 +146,7 @@ void tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, ti->ti.ti_i6.ih_x1 = 0; break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } flags = TH_ACK; } else { @@ -175,7 +175,7 @@ void tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, xchg(ti->ti_dport, ti->ti_sport, uint16_t); break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } #undef xchg } @@ -238,7 +238,7 @@ void tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } } @@ -461,7 +461,7 @@ void tcp_connect(struct socket *inso) addrlen = sizeof(struct sockaddr_in6); break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } ret = getnameinfo((const struct sockaddr *) &inso->lhost.ss, addrlen, addrstr, sizeof(addrstr), portstr, sizeof(portstr), NI_NUMERICHOST|NI_NUMERICSERV); assert(ret == 0); diff --git a/bochs/iodev/network/slirp/udp.cc b/bochs/iodev/network/slirp/udp.cc index 1318470ac..e4199b2bd 100644 --- a/bochs/iodev/network/slirp/udp.cc +++ b/bochs/iodev/network/slirp/udp.cc @@ -327,7 +327,7 @@ int udp_attach(struct socket *so, unsigned short af) setsockopt(so->s, IPPROTO_IPV6, IPV6_RECVERR, &opt, sizeof(opt)); break; default: - fprintf(stderr, "Unknown protocol\n"); + slirplog_error("Unknown protocol"); } } #endif diff --git a/bochs/misc/slirp.conf b/bochs/misc/slirp.conf index 71b6f3599..c30d56c0e 100644 --- a/bochs/misc/slirp.conf +++ b/bochs/misc/slirp.conf @@ -45,4 +45,11 @@ # Enable IPv6 support (using default Qemu setup) # ipv6_enabled = 1 +# Enable slirp debugging support if > 0 +# The value can be a combination of these debug levels +# 1 - "call" (function calls and arguments) +# 2 - "misc" (misc debug messages) +# 4 - "error" (normal errors) +# 8 - "tftp" (TFTP messages) +# 16 - "verbose_call" (more function calls) # debug_switches = 1