diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ip_icmp.c | 7 | ||||
-rw-r--r-- | src/libslirp.h | 2 | ||||
-rw-r--r-- | src/slirp.c | 1 | ||||
-rw-r--r-- | src/slirp.h | 2 | ||||
-rw-r--r-- | src/socket.c | 30 | ||||
-rw-r--r-- | src/socket.h | 2 | ||||
-rw-r--r-- | src/tcp_subr.c | 4 |
7 files changed, 35 insertions, 13 deletions
diff --git a/src/ip_icmp.c b/src/ip_icmp.c index 7590cff..58e35a5 100644 --- a/src/ip_icmp.c +++ b/src/ip_icmp.c @@ -190,7 +190,12 @@ void icmp_input(struct mbuf *m, int hlen) /* Send the packet */ addr = so->fhost.ss; - sotranslate_out(so, &addr); + if (sotranslate_out(so, &addr) < 0) { + icmp_send_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, + strerror(errno)); + udp_detach(so); + return; + } if (sendto(so->s, icmp_ping_msg, strlen(icmp_ping_msg), 0, (struct sockaddr *)&addr, sockaddr_size(&addr)) == -1) { diff --git a/src/libslirp.h b/src/libslirp.h index 2ba4388..a568488 100644 --- a/src/libslirp.h +++ b/src/libslirp.h @@ -89,6 +89,8 @@ typedef struct SlirpConfig { size_t if_mtu; /* Default: IF_MRU_DEFAULT */ size_t if_mru; + /* Prohibit connecting to 127.0.0.1:* */ + bool disable_host_loopback; } SlirpConfig; Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, diff --git a/src/slirp.c b/src/slirp.c index 3be982c..f645145 100644 --- a/src/slirp.c +++ b/src/slirp.c @@ -317,6 +317,7 @@ Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaque) } slirp->if_mtu = cfg->if_mtu == 0 ? IF_MTU_DEFAULT : cfg->if_mtu; slirp->if_mru = cfg->if_mru == 0 ? IF_MRU_DEFAULT : cfg->if_mru; + slirp->disable_host_loopback = cfg->disable_host_loopback; return slirp; } diff --git a/src/slirp.h b/src/slirp.h index 5fbee5c..ea8e8c5 100644 --- a/src/slirp.h +++ b/src/slirp.h @@ -147,6 +147,8 @@ struct Slirp { int if_mtu; int if_mru; + bool disable_host_loopback; + /* mbuf states */ struct quehead m_freelist; struct quehead m_usedlist; diff --git a/src/socket.c b/src/socket.c index 34daffc..d96d8c4 100644 --- a/src/socket.c +++ b/src/socket.c @@ -657,7 +657,9 @@ int sosendto(struct socket *so, struct mbuf *m) addr = so->fhost.ss; DEBUG_CALL(" sendto()ing)"); - sotranslate_out(so, &addr); + if (sotranslate_out(so, &addr) < 0) { + return -1; + } /* Don't care what port we get */ ret = sendto(so->s, m->m_data, m->m_len, 0, (struct sockaddr *)&addr, @@ -818,8 +820,9 @@ void sofwdrain(struct socket *so) /* * Translate addr in host addr when it is a virtual address */ -void sotranslate_out(struct socket *so, struct sockaddr_storage *addr) +int sotranslate_out(struct socket *so, struct sockaddr_storage *addr) { + int rc = 0; Slirp *slirp = so->slirp; struct sockaddr_in *sin = (struct sockaddr_in *)addr; struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr; @@ -830,18 +833,19 @@ void sotranslate_out(struct socket *so, struct sockaddr_storage *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; + if (get_dns_addr(&sin->sin_addr) >= 0) { + goto ret; } + } + if (slirp->disable_host_loopback) { + rc = -1; + errno = EPERM; + goto ret; } else { sin->sin_addr = loopback_addr; } } - - DEBUG_MISC(" addr.sin_port=%d, addr.sin_addr.s_addr=%.16s", - 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)) { @@ -849,9 +853,13 @@ void sotranslate_out(struct socket *so, struct sockaddr_storage *addr) 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; + goto ret; } + } + if (slirp->disable_host_loopback) { + rc = -1; + errno = EPERM; + goto ret; } else { sin6->sin6_addr = in6addr_loopback; } @@ -861,6 +869,8 @@ void sotranslate_out(struct socket *so, struct sockaddr_storage *addr) default: break; } +ret: + return rc; } void sotranslate_in(struct socket *so, struct sockaddr_storage *addr) diff --git a/src/socket.h b/src/socket.h index d07f56d..a6a1e5e 100644 --- a/src/socket.h +++ b/src/socket.h @@ -155,7 +155,7 @@ struct iovec; /* For win32 */ size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np); int soreadbuf(struct socket *so, const char *buf, int size); -void sotranslate_out(struct socket *, struct sockaddr_storage *); +int sotranslate_out(struct socket *, struct sockaddr_storage *); void sotranslate_in(struct socket *, struct sockaddr_storage *); void sotranslate_accept(struct socket *); void sodrop(struct socket *, int num); diff --git a/src/tcp_subr.c b/src/tcp_subr.c index 83c7520..60cc0a1 100644 --- a/src/tcp_subr.c +++ b/src/tcp_subr.c @@ -424,7 +424,9 @@ int tcp_fconnect(struct socket *so, unsigned short af) addr = so->fhost.ss; DEBUG_CALL(" connect()ing"); - sotranslate_out(so, &addr); + if (sotranslate_out(so, &addr) < 0) { + return -1; + } /* We don't care what port we get */ ret = connect(s, (struct sockaddr *)&addr, sockaddr_size(&addr)); |