From 32ebd649b397ee4315e07f94e2861019136d3b3c Mon Sep 17 00:00:00 2001 From: Jef Poskanzer Date: Sat, 9 Nov 2013 14:23:36 -0800 Subject: [PATCH] Fixed some memory & fd leaks in error cases of various network setup routines. --- src/iperf_tcp.c | 33 +++++++++++++++++++++++++++++++++ src/net.c | 23 +++++++++++++++++++---- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/iperf_tcp.c b/src/iperf_tcp.c index e80b53e..cf7bf8d 100644 --- a/src/iperf_tcp.c +++ b/src/iperf_tcp.c @@ -135,6 +135,7 @@ iperf_tcp_listen(struct iperf_test *test) } if ((s = socket(res->ai_family, SOCK_STREAM, 0)) < 0) { + freeaddrinfo(res); i_errno = IESTREAMLISTEN; return -1; } @@ -142,6 +143,8 @@ iperf_tcp_listen(struct iperf_test *test) if (test->no_delay) { opt = 1; if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) { + close(s); + freeaddrinfo(res); i_errno = IESETNODELAY; return -1; } @@ -149,22 +152,30 @@ iperf_tcp_listen(struct iperf_test *test) // XXX: Setting MSS is very buggy! if ((opt = test->settings->mss)) { if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &opt, sizeof(opt)) < 0) { + close(s); + freeaddrinfo(res); i_errno = IESETMSS; return -1; } } if ((opt = test->settings->socket_bufsize)) { if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) { + close(s); + freeaddrinfo(res); i_errno = IESETBUF; return -1; } if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0) { + close(s); + freeaddrinfo(res); i_errno = IESETBUF; return -1; } } opt = 1; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { + close(s); + freeaddrinfo(res); i_errno = IEREUSEADDR; return -1; } @@ -178,6 +189,7 @@ iperf_tcp_listen(struct iperf_test *test) if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) { close(s); + freeaddrinfo(res); i_errno = IESTREAMLISTEN; return -1; } @@ -222,17 +234,25 @@ iperf_tcp_connect(struct iperf_test *test) hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", test->server_port); if (getaddrinfo(test->server_hostname, portstr, &hints, &server_res) != 0) { + if (test->bind_address) + freeaddrinfo(local_res); i_errno = IESTREAMCONNECT; return -1; } if ((s = socket(server_res->ai_family, SOCK_STREAM, 0)) < 0) { + if (test->bind_address) + freeaddrinfo(local_res); + freeaddrinfo(server_res); i_errno = IESTREAMCONNECT; return -1; } if (test->bind_address) { if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) { + close(s); + freeaddrinfo(local_res); + freeaddrinfo(server_res); i_errno = IESTREAMCONNECT; return -1; } @@ -243,28 +263,38 @@ iperf_tcp_connect(struct iperf_test *test) if (test->no_delay) { opt = 1; if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) { + close(s); + freeaddrinfo(server_res); i_errno = IESETNODELAY; return -1; } } if ((opt = test->settings->mss)) { if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &opt, sizeof(opt)) < 0) { + close(s); + freeaddrinfo(server_res); i_errno = IESETMSS; return -1; } } if ((opt = test->settings->socket_bufsize)) { if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) { + close(s); + freeaddrinfo(server_res); i_errno = IESETBUF; return -1; } if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0) { + close(s); + freeaddrinfo(server_res); i_errno = IESETBUF; return -1; } } if (test->settings->flowlabel) { if (server_res->ai_addr->sa_family != AF_INET6) { + close(s); + freeaddrinfo(server_res); i_errno = IESETFLOW; return -1; } else { @@ -274,6 +304,8 @@ iperf_tcp_connect(struct iperf_test *test) } if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) { + close(s); + freeaddrinfo(server_res); i_errno = IESTREAMCONNECT; return -1; } @@ -282,6 +314,7 @@ iperf_tcp_connect(struct iperf_test *test) /* Send cookie for verification */ if (Nwrite(s, test->cookie, COOKIE_SIZE, Ptcp) < 0) { + close(s); i_errno = IESENDCOOKIE; return -1; } diff --git a/src/net.c b/src/net.c index 460c0bd..9573f1e 100644 --- a/src/net.c +++ b/src/net.c @@ -65,18 +65,29 @@ netdial(int domain, int proto, char *local, char *server, int port) return -1; s = socket(server_res->ai_family, proto, 0); - if (s < 0) + if (s < 0) { + if (local) + freeaddrinfo(local_res); + freeaddrinfo(server_res); return -1; + } if (local) { - if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) + if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) { + close(s); + freeaddrinfo(local_res); + freeaddrinfo(server_res); return -1; + } freeaddrinfo(local_res); } ((struct sockaddr_in *) server_res->ai_addr)->sin_port = htons(port); - if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) + if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) { + close(s); + freeaddrinfo(server_res); return -1; + } freeaddrinfo(server_res); return s; @@ -100,8 +111,10 @@ netannounce(int domain, int proto, char *local, int port) return -1; s = socket(res->ai_family, proto, 0); - if (s < 0) + if (s < 0) { + freeaddrinfo(res); return -1; + } opt = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)); @@ -115,6 +128,7 @@ netannounce(int domain, int proto, char *local, int port) if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) { close(s); + freeaddrinfo(res); return -1; } @@ -122,6 +136,7 @@ netannounce(int domain, int proto, char *local, int port) if (proto == SOCK_STREAM) { if (listen(s, 5) < 0) { + close(s); return -1; } }