Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • slirp/libslirp
  • elmarco/libslirp
  • AkihiroSuda/libslirp
  • procurement/libslirp
  • sthibaul/libslirp
  • jnovy/libslirp
  • maos20008/libslirp
  • giuseppe/libslirp
  • rafaelgieschke/libslirp
  • rd235/libslirp
  • wanders/libslirp
  • 5eraph/libslirp
  • ashang/libslirp
  • Crosshairs/libslirp
  • jonpspri/libslirp
  • philmd/libslirp
  • rhafer/libslirp
  • dgilbert/libslirp
  • stweil/libslirp
  • bonzini/libslirp
  • osy/libslirp
  • dje/libslirp
  • abidh/libslirp
  • WaluigiWare64/libslirp
  • psandovalv/libslirp
  • thuth/libslirp
  • jma/libslirp
  • rjzak/libslirp
  • dingaopaicandu/libslirp
  • saar/libslirp
  • nicholasngai/libslirp
  • ignat.korchagin/libslirp
  • nashidau/libslirp
  • waldi/libslirp
  • ivanholmes/libslirp
  • pefoley21/libslirp
  • bgilbert/libslirp
  • jirislaby/libslirp
  • ozkanonur/libslirp
  • qianwww/libslirp
  • flwu/libslirp
  • seiya/libslirp
  • Arusekk/libslirp
  • kuznetsovam/libslirp
  • bscottmichel/libslirp-minimal
  • intelfx/libslirp
46 results
Show changes
Commits on Source (29)
......@@ -4,6 +4,7 @@ variables:
DEPS: meson ninja-build make
gcc pkg-config glib2-devel
mingw64-gcc mingw64-pkg-config mingw64-glib2
clang-analyzer
before_script:
- dnf install -y $DEPS
......@@ -13,6 +14,7 @@ build:
- meson build || (cat build/meson-logs/meson-log.txt && exit 1)
- ninja -C build
- (cd build && meson test) || (cat build/meson-logs/testlog.txt && exit 1)
- ninja -C build scan-build
build-mingw64:
script:
......
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [4.1.0] - 2019-12-02
### Added
- The `slirp_new()` API, simpler and more extensible than `slirp_init()`.
- Allow custom MTU configuration.
- Option to disable host loopback connections.
- CI now runs scan-build too.
### Changed
- Disable `tcp_emu()` by default. `tcp_emu()` is known to have caused
several CVEs, and not useful today in most cases. The feature can
be still enabled by setting `SlirpConfig.enable_emu` to true.
- meson build system is now `subproject()` friendly.
- Replace remaining `malloc()`/`free()` with glib (which aborts on OOM)
- Various code cleanups.
### Deprecated
- The `slirp_init()` API.
### Fixed
- `getpeername()` error after `shutdown(SHUT_WR)`.
- Exec forward: correctly parse command lines that contain spaces.
- Allow 0.0.0.0 destination address.
- Make host receive broadcast packets.
- Various memory related fixes (heap overflow, leaks, NULL
dereference).
- Compilation warnings, dead code.
## [4.0.0] - 2019-05-24
### Added
- Installable as a shared library.
- meson build system
(& make build system for in-tree QEMU integration)
### Changed
- Standalone project, removing any QEMU dependency.
- License clarifications.
[unreleased]: https://gitlab.freedesktop.org/slirp/libslirp/compare/v4.1.0...master
[4.1.0]: https://gitlab.freedesktop.org/slirp/libslirp/compare/v4.0.0...v4.1.0
[4.0.0]: https://gitlab.freedesktop.org/slirp/libslirp/commits/v4.0.0
......@@ -3,7 +3,7 @@ BUILD_DIR ?= .
LIBSLIRP = $(BUILD_DIR)/libslirp.a
SLIRP_MAJOR_VERSION = 4
SLIRP_MINOR_VERSION = 0
SLIRP_MINOR_VERSION = 1
SLIRP_MICRO_VERSION = 0
all: $(LIBSLIRP)
......
project('libslirp', 'c',
version : '4.0.0',
version : '4.1.0',
license : 'BSD-3-Clause',
default_options : ['warning_level=1', 'c_std=gnu99']
)
......@@ -32,10 +32,10 @@ conf.set('SLIRP_MICRO_VERSION', micro_version)
# - If the interface is the same as the previous version, but bugs are
# fixed, change:
# REVISION += 1
lt_current = '0'
lt_revision = '0'
lt_age = '0'
lt_version = '@0@.@1@.@2@'.format(lt_current, lt_age, lt_revision)
lt_current = 1
lt_revision = 0
lt_age = 1
lt_version = '@0@.@1@.@2@'.format(lt_current - lt_age, lt_age, lt_revision)
host_system = host_machine.system()
......@@ -100,8 +100,7 @@ configure_file(
configuration : conf
)
lib = shared_library('slirp', sources,
soversion : lt_current,
lib = library('slirp', sources,
version : lt_version,
c_args : cargs,
link_args : vflag,
......@@ -110,6 +109,10 @@ lib = shared_library('slirp', sources,
install : true
)
libslirp_dep = declare_dependency(
include_directories: include_directories('.', 'src'),
link_with: lib)
install_headers(['src/libslirp.h'], subdir : 'slirp')
pkg = import('pkgconfig')
......
......@@ -71,7 +71,7 @@ bool arp_table_search(Slirp *slirp, uint32_t ip_addr,
DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){ .s_addr = ip_addr }));
/* If broadcast address */
if (ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
if (ip_addr == 0 || ip_addr == 0xffffffff || ip_addr == broadcast_addr) {
/* return Ethernet broadcast address */
memset(out_ethaddr, 0xff, ETH_ALEN);
return 1;
......
......@@ -238,13 +238,8 @@ int translate_dnssearch(Slirp *s, const char **names)
size_t i, num_domains, memreq = 0;
uint8_t *result = NULL, *outptr;
CompactDomain *domains = NULL;
const char **nameptr = names;
while (*nameptr != NULL) {
nameptr++;
}
num_domains = nameptr - names;
num_domains = g_strv_length((GStrv)names);
if (num_domains == 0) {
return -2;
}
......
......@@ -7,7 +7,6 @@ global:
slirp_connection_info;
slirp_init;
slirp_input;
slirp_new;
slirp_pollfds_fill;
slirp_pollfds_poll;
slirp_remove_hostfwd;
......@@ -20,3 +19,7 @@ global:
local:
*;
};
SLIRP_4.1 {
slirp_new;
} SLIRP_4.0;
......@@ -168,7 +168,8 @@ g_spawn_async_with_fds_slirp(const gchar *working_directory, gchar **argv,
int fork_exec(struct socket *so, const char *ex)
{
GError *err = NULL;
char **argv;
gint argc = 0;
gchar **argv = NULL;
int opt, sp[2];
DEBUG_CALL("fork_exec");
......@@ -179,7 +180,12 @@ int fork_exec(struct socket *so, const char *ex)
return 0;
}
argv = g_strsplit(ex, " ", -1);
if (!g_shell_parse_argv(ex, &argc, &argv, &err)) {
g_critical("fork_exec invalid command: %s\nerror: %s", ex, err->message);
g_error_free(err);
return 0;
}
g_spawn_async_with_fds(NULL /* cwd */, argv, NULL /* env */,
G_SPAWN_SEARCH_PATH, fork_exec_child_setup,
NULL /* data */, NULL /* child_pid */, sp[1], sp[1],
......
......@@ -9,19 +9,17 @@ static void sbappendsb(struct sbuf *sb, struct mbuf *m);
void sbfree(struct sbuf *sb)
{
free(sb->sb_data);
g_free(sb->sb_data);
}
bool sbdrop(struct sbuf *sb, int num)
bool sbdrop(struct sbuf *sb, size_t num)
{
int limit = sb->sb_datalen / 2;
/*
* We can only drop how much we have
* This should never succeed
*/
g_warn_if_fail(num <= sb->sb_cc);
if (num > sb->sb_cc)
num = sb->sb_cc;
sb->sb_cc -= num;
sb->sb_rptr += num;
if (sb->sb_rptr >= sb->sb_data + sb->sb_datalen)
......@@ -34,27 +32,11 @@ bool sbdrop(struct sbuf *sb, int num)
return false;
}
void sbreserve(struct sbuf *sb, int size)
void sbreserve(struct sbuf *sb, size_t size)
{
if (sb->sb_data) {
/* Already alloced, realloc if necessary */
if (sb->sb_datalen != size) {
sb->sb_wptr = sb->sb_rptr = sb->sb_data =
(char *)realloc(sb->sb_data, size);
sb->sb_cc = 0;
if (sb->sb_wptr)
sb->sb_datalen = size;
else
sb->sb_datalen = 0;
}
} else {
sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size);
sb->sb_cc = 0;
if (sb->sb_wptr)
sb->sb_datalen = size;
else
sb->sb_datalen = 0;
}
sb->sb_wptr = sb->sb_rptr = sb->sb_data = g_realloc(sb->sb_data, size);
sb->sb_cc = 0;
sb->sb_datalen = size;
}
/*
......@@ -161,17 +143,17 @@ static void sbappendsb(struct sbuf *sb, struct mbuf *m)
* Don't update the sbuf rptr, this will be
* done in sbdrop when the data is acked
*/
void sbcopy(struct sbuf *sb, int off, int len, char *to)
void sbcopy(struct sbuf *sb, size_t off, size_t len, char *to)
{
char *from;
g_assert(len + off <= sb->sb_cc);
from = sb->sb_rptr + off;
if (from >= sb->sb_data + sb->sb_datalen)
from -= sb->sb_datalen;
if (from < sb->sb_wptr) {
if (len > sb->sb_cc)
len = sb->sb_cc;
memcpy(to, from, len);
} else {
/* re-use off */
......
......@@ -18,10 +18,10 @@ struct sbuf {
char *sb_data; /* Actual data */
};
void sbfree(struct sbuf *);
bool sbdrop(struct sbuf *, int);
void sbreserve(struct sbuf *, int);
void sbappend(struct socket *, struct mbuf *);
void sbcopy(struct sbuf *, int, int, char *);
void sbfree(struct sbuf *sb);
bool sbdrop(struct sbuf *sb, size_t len);
void sbreserve(struct sbuf *sb, size_t size);
void sbappend(struct socket *sb, struct mbuf *mb);
void sbcopy(struct sbuf *sb, size_t off, size_t len, char *p);
#endif
......@@ -845,11 +845,6 @@ static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
{
const struct ip *iph = (const struct ip *)ifm->m_data;
if (iph->ip_dst.s_addr == 0) {
/* 0.0.0.0 can not be a destination address, something went wrong,
* avoid making it worse */
return 1;
}
if (!arp_table_search(slirp, iph->ip_dst.s_addr, ethaddr)) {
uint8_t arp_req[ETH_HLEN + sizeof(struct slirp_arphdr)];
struct ethhdr *reh = (struct ethhdr *)arp_req;
......
......@@ -266,7 +266,7 @@ struct tcpcb *tcp_close(register struct tcpcb *);
void tcp_sockclosed(struct tcpcb *);
int tcp_fconnect(struct socket *, unsigned short af);
void tcp_connect(struct socket *);
int tcp_attach(struct socket *);
void tcp_attach(struct socket *);
uint8_t tcp_tos(struct socket *);
int tcp_emu(struct socket *, struct mbuf *);
int tcp_ctl(struct socket *);
......
......@@ -95,7 +95,7 @@ void sofree(struct socket *so)
remque(so); /* crashes if so is not in a queue */
if (so->so_tcpcb) {
free(so->so_tcpcb);
g_free(so->so_tcpcb);
}
g_free(so);
}
......@@ -195,7 +195,9 @@ int soread(struct socket *so)
err = errno;
if (nn == 0) {
if (getpeername(so->s, paddr, &alen) < 0) {
int shutdown_wr = so->so_state & SS_FCANTSENDMORE;
if (!shutdown_wr && getpeername(so->s, paddr, &alen) < 0) {
err = errno;
} else {
getsockopt(so->s, SOL_SOCKET, SO_ERROR, &err, &elen);
......@@ -844,6 +846,9 @@ int sotranslate_out(struct socket *so, struct sockaddr_storage *addr)
} else {
sin->sin_addr = loopback_addr;
}
} else if (!slirp->disable_host_loopback && so->so_faddr.s_addr == 0xffffffff) {
/* Receive broadcast as well */
sin->sin_addr = loopback_addr;
}
break;
case AF_INET6:
......@@ -863,6 +868,9 @@ int sotranslate_out(struct socket *so, struct sockaddr_storage *addr)
} else {
sin6->sin6_addr = in6addr_loopback;
}
} else if (!slirp->disable_host_loopback
&& in6_equal(&so->so_faddr6, &(struct in6_addr) ALLNODES_MULTICAST)) {
sin6->sin6_addr = in6addr_loopback;
}
break;
......
......@@ -107,9 +107,6 @@ static int sbuf_tmp_post_load(void *opaque, int version)
/* Allocate the buffer space used by the field after the tmp */
sbreserve(tmp->parent, tmp->parent->sb_datalen);
if (tmp->parent->sb_datalen != requested_len) {
return -ENOMEM;
}
if (tmp->woff >= requested_len || tmp->roff >= requested_len) {
g_critical("invalid sbuf offsets r/w=%u/%u len=%u", tmp->roff,
tmp->woff, requested_len);
......@@ -159,9 +156,8 @@ static bool slirp_family_inet(void *opaque, int version_id)
static int slirp_socket_pre_load(void *opaque)
{
struct socket *so = opaque;
if (tcp_attach(so) < 0) {
return -ENOMEM;
}
tcp_attach(so);
/* Older versions don't load these fields */
so->so_ffamily = AF_INET;
so->so_lfamily = AF_INET;
......
......@@ -408,10 +408,7 @@ findso:
goto dropwithreset;
so = socreate(slirp);
if (tcp_attach(so) < 0) {
g_free(so); /* Not sofree (if it failed, it's not insqued) */
goto dropwithreset;
}
tcp_attach(so);
sbreserve(&so->so_snd, TCP_SNDSPACE);
sbreserve(&so->so_rcv, TCP_RCVSPACE);
......
......@@ -255,11 +255,7 @@ struct tcpcb *tcp_newtcpcb(struct socket *so)
{
register struct tcpcb *tp;
tp = (struct tcpcb *)malloc(sizeof(*tp));
if (tp == NULL)
return ((struct tcpcb *)0);
memset((char *)tp, 0, sizeof(struct tcpcb));
tp = g_new0(struct tcpcb, 1);
tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
/*
* 40: length of IPv4 header (20) + TCP header (20)
......@@ -336,7 +332,7 @@ struct tcpcb *tcp_close(struct tcpcb *tp)
remque(tcpiphdr2qlink(tcpiphdr_prev(t)));
m_free(m);
}
free(tp);
g_free(tp);
so->so_tcpcb = NULL;
/* clobber input socket cache if we're closing the cached connection */
if (so == slirp->tcp_last_so)
......@@ -377,8 +373,8 @@ void tcp_sockclosed(struct tcpcb *tp)
case TCPS_LISTEN:
case TCPS_SYN_SENT:
tp->t_state = TCPS_CLOSED;
tp = tcp_close(tp);
break;
tcp_close(tp);
return;
case TCPS_SYN_RECEIVED:
case TCPS_ESTABLISHED:
......@@ -474,10 +470,7 @@ void tcp_connect(struct socket *inso)
so = inso;
} else {
so = socreate(slirp);
if (tcp_attach(so) < 0) {
g_free(so); /* NOT sofree */
return;
}
tcp_attach(so);
so->lhost = inso->lhost;
so->so_ffamily = inso->so_ffamily;
}
......@@ -528,14 +521,10 @@ void tcp_connect(struct socket *inso)
/*
* Attach a TCPCB to a socket.
*/
int tcp_attach(struct socket *so)
void tcp_attach(struct socket *so)
{
if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL)
return -1;
so->so_tcpcb = tcp_newtcpcb(so);
insque(so, &so->slirp->tcb);
return 0;
}
/*
......
......@@ -321,7 +321,6 @@ static int vmstate_save_state_v(SlirpOStream *f, const VMStateDescription *vmsd,
}
for (i = 0; i < n_elems; i++) {
void *curr_elem = first_elem + size * i;
ret = 0;
if (field->flags & VMS_ARRAY_OF_POINTER) {
assert(curr_elem);
......