2009-10-11 00:04:03 +04:00
|
|
|
#include "taskimpl.h"
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/tcp.h>
|
2012-08-01 06:00:00 +04:00
|
|
|
#include <arpa/inet.h>
|
2009-10-11 00:04:03 +04:00
|
|
|
#include <sys/poll.h>
|
2012-08-01 06:00:00 +04:00
|
|
|
#include "ip.h"
|
|
|
|
|
|
|
|
static int
|
|
|
|
family(unsigned char *addr)
|
|
|
|
{
|
|
|
|
if(isv4(addr))
|
|
|
|
return AF_INET;
|
|
|
|
return AF_INET6;
|
|
|
|
}
|
2009-10-11 00:04:03 +04:00
|
|
|
|
|
|
|
int
|
|
|
|
netannounce(int istcp, char *server, int port)
|
|
|
|
{
|
|
|
|
int fd, n, proto;
|
2012-08-01 06:00:00 +04:00
|
|
|
struct sockaddr_storage ss;
|
2009-10-11 00:04:03 +04:00
|
|
|
socklen_t sn;
|
2012-08-01 06:00:00 +04:00
|
|
|
unsigned char ip[IPaddrlen];
|
2009-10-11 00:04:03 +04:00
|
|
|
|
|
|
|
taskstate("netannounce");
|
|
|
|
proto = istcp ? SOCK_STREAM : SOCK_DGRAM;
|
2012-08-01 06:00:00 +04:00
|
|
|
memset(&ss, 0, sizeof ss);
|
2009-10-11 00:04:03 +04:00
|
|
|
if(server != nil && strcmp(server, "*") != 0){
|
2012-08-01 06:00:00 +04:00
|
|
|
if(netlookup(server, ip) < 0){
|
2009-10-11 00:04:03 +04:00
|
|
|
taskstate("netlookup failed");
|
|
|
|
return -1;
|
|
|
|
}
|
2012-08-01 06:00:00 +04:00
|
|
|
ss.ss_family = family(ip);
|
|
|
|
switch(ss.ss_family){
|
|
|
|
case AF_INET:
|
|
|
|
v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, ip);
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, ip, sizeof(struct in6_addr));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}else{
|
|
|
|
ss.ss_family = AF_INET6;
|
|
|
|
((struct sockaddr_in6*)&ss)->sin6_addr = in6addr_any;
|
|
|
|
}
|
|
|
|
switch(ss.ss_family){
|
|
|
|
case AF_INET:
|
|
|
|
hnputs(&((struct sockaddr_in*)&ss)->sin_port, port);
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, port);
|
|
|
|
break;
|
2009-10-11 00:04:03 +04:00
|
|
|
}
|
2012-08-01 06:00:00 +04:00
|
|
|
if((fd = socket(ss.ss_family, proto, 0)) < 0){
|
2009-10-11 00:04:03 +04:00
|
|
|
taskstate("socket failed");
|
|
|
|
return -1;
|
|
|
|
}
|
2014-08-03 20:28:37 +04:00
|
|
|
|
2009-10-11 00:04:03 +04:00
|
|
|
/* set reuse flag for tcp */
|
2014-08-03 20:19:36 +04:00
|
|
|
sn = sizeof n;
|
2009-10-11 00:04:03 +04:00
|
|
|
if(istcp && getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >= 0){
|
|
|
|
n = 1;
|
fix warnings reported by Coverity
fd.c:230 negative_returns: fd is passed to a parameter that cannot be negative.
net.c:65 check_return: Calling setsockopt(fd, 1, 2, (char *)&n, 4U) without checking return value.
net.c:77 check_return: Calling fdnoblock(fd) without checking return value.
net.c:112 check_return: Calling fdnoblock(cfd) without checking return value.
net.c:114 check_return: Calling setsockopt(cfd, IPPROTO_TCP, 1, (char *)&one, 4U) without checking return value.
net.c:144 leaked_storage: Variable result going out of scope leaks the storage it points to.
net.c:168 check_return: Calling fdnoblock(fd) without checking return value.
net.c:173 check_return: Calling setsockopt(fd, 1, 6, &n, 4U) without checking return value.
net.c:206 check_return: Calling getsockopt(fd, 1, 4, (void *)&n, &sn) without checking return value.
task.c:59 negative_returns: fd is passed to a parameter that cannot be negative.
tcpload.c:50 Calling fdread without checking return value (as is done elsewhere 4 out of 5 times).
tcpproxy.c:51 check_return: Calling fdnoblock(fd) without checking return value.
2015-06-25 00:16:58 +03:00
|
|
|
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n) < 0){
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-10-11 00:04:03 +04:00
|
|
|
}
|
|
|
|
|
2012-08-01 06:00:00 +04:00
|
|
|
if(bind(fd, (struct sockaddr*)&ss, sizeof ss) < 0){
|
2009-10-11 00:04:03 +04:00
|
|
|
taskstate("bind failed");
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(proto == SOCK_STREAM)
|
|
|
|
listen(fd, 16);
|
|
|
|
|
fix warnings reported by Coverity
fd.c:230 negative_returns: fd is passed to a parameter that cannot be negative.
net.c:65 check_return: Calling setsockopt(fd, 1, 2, (char *)&n, 4U) without checking return value.
net.c:77 check_return: Calling fdnoblock(fd) without checking return value.
net.c:112 check_return: Calling fdnoblock(cfd) without checking return value.
net.c:114 check_return: Calling setsockopt(cfd, IPPROTO_TCP, 1, (char *)&one, 4U) without checking return value.
net.c:144 leaked_storage: Variable result going out of scope leaks the storage it points to.
net.c:168 check_return: Calling fdnoblock(fd) without checking return value.
net.c:173 check_return: Calling setsockopt(fd, 1, 6, &n, 4U) without checking return value.
net.c:206 check_return: Calling getsockopt(fd, 1, 4, (void *)&n, &sn) without checking return value.
task.c:59 negative_returns: fd is passed to a parameter that cannot be negative.
tcpload.c:50 Calling fdread without checking return value (as is done elsewhere 4 out of 5 times).
tcpproxy.c:51 check_return: Calling fdnoblock(fd) without checking return value.
2015-06-25 00:16:58 +03:00
|
|
|
if(fdnoblock(fd) < 0){
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-10-11 00:04:03 +04:00
|
|
|
taskstate("netannounce succeeded");
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
netaccept(int fd, char *server, int *port)
|
|
|
|
{
|
|
|
|
int cfd, one;
|
2012-08-01 06:00:00 +04:00
|
|
|
struct sockaddr_storage ss;
|
2009-10-11 00:04:03 +04:00
|
|
|
socklen_t len;
|
2014-08-03 20:28:37 +04:00
|
|
|
|
2009-10-11 00:04:03 +04:00
|
|
|
fdwait(fd, 'r');
|
|
|
|
|
|
|
|
taskstate("netaccept");
|
2012-08-01 06:00:00 +04:00
|
|
|
len = sizeof ss;
|
|
|
|
if((cfd = accept(fd, (void*)&ss, &len)) < 0){
|
2009-10-11 00:04:03 +04:00
|
|
|
taskstate("accept failed");
|
|
|
|
return -1;
|
|
|
|
}
|
2012-08-01 06:00:00 +04:00
|
|
|
|
|
|
|
switch(ss.ss_family){
|
|
|
|
case AF_INET:
|
|
|
|
if(server)
|
|
|
|
inet_ntop(AF_INET, &((struct sockaddr_in*)&ss)->sin_addr.s_addr, server, INET_ADDRSTRLEN);
|
|
|
|
if(port)
|
|
|
|
*port = nhgets(&((struct sockaddr_in*)&ss)->sin_port);
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
if(server)
|
|
|
|
inet_ntop(AF_INET6, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, server, INET6_ADDRSTRLEN);
|
|
|
|
if(port)
|
|
|
|
*port = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port);
|
|
|
|
break;
|
2009-10-11 00:04:03 +04:00
|
|
|
}
|
fix warnings reported by Coverity
fd.c:230 negative_returns: fd is passed to a parameter that cannot be negative.
net.c:65 check_return: Calling setsockopt(fd, 1, 2, (char *)&n, 4U) without checking return value.
net.c:77 check_return: Calling fdnoblock(fd) without checking return value.
net.c:112 check_return: Calling fdnoblock(cfd) without checking return value.
net.c:114 check_return: Calling setsockopt(cfd, IPPROTO_TCP, 1, (char *)&one, 4U) without checking return value.
net.c:144 leaked_storage: Variable result going out of scope leaks the storage it points to.
net.c:168 check_return: Calling fdnoblock(fd) without checking return value.
net.c:173 check_return: Calling setsockopt(fd, 1, 6, &n, 4U) without checking return value.
net.c:206 check_return: Calling getsockopt(fd, 1, 4, (void *)&n, &sn) without checking return value.
task.c:59 negative_returns: fd is passed to a parameter that cannot be negative.
tcpload.c:50 Calling fdread without checking return value (as is done elsewhere 4 out of 5 times).
tcpproxy.c:51 check_return: Calling fdnoblock(fd) without checking return value.
2015-06-25 00:16:58 +03:00
|
|
|
if(fdnoblock(cfd) < 0){
|
|
|
|
close(cfd);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-10-11 00:04:03 +04:00
|
|
|
one = 1;
|
fix warnings reported by Coverity
fd.c:230 negative_returns: fd is passed to a parameter that cannot be negative.
net.c:65 check_return: Calling setsockopt(fd, 1, 2, (char *)&n, 4U) without checking return value.
net.c:77 check_return: Calling fdnoblock(fd) without checking return value.
net.c:112 check_return: Calling fdnoblock(cfd) without checking return value.
net.c:114 check_return: Calling setsockopt(cfd, IPPROTO_TCP, 1, (char *)&one, 4U) without checking return value.
net.c:144 leaked_storage: Variable result going out of scope leaks the storage it points to.
net.c:168 check_return: Calling fdnoblock(fd) without checking return value.
net.c:173 check_return: Calling setsockopt(fd, 1, 6, &n, 4U) without checking return value.
net.c:206 check_return: Calling getsockopt(fd, 1, 4, (void *)&n, &sn) without checking return value.
task.c:59 negative_returns: fd is passed to a parameter that cannot be negative.
tcpload.c:50 Calling fdread without checking return value (as is done elsewhere 4 out of 5 times).
tcpproxy.c:51 check_return: Calling fdnoblock(fd) without checking return value.
2015-06-25 00:16:58 +03:00
|
|
|
if(setsockopt(cfd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof one) < 0){
|
|
|
|
close(cfd);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-10-11 00:04:03 +04:00
|
|
|
taskstate("netaccept succeeded");
|
|
|
|
return cfd;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-08-01 06:00:00 +04:00
|
|
|
netlookup(char *name, unsigned char *ip)
|
2009-10-11 00:04:03 +04:00
|
|
|
{
|
2012-08-01 06:00:00 +04:00
|
|
|
struct addrinfo *result;
|
2009-10-11 00:04:03 +04:00
|
|
|
|
2012-08-01 06:00:00 +04:00
|
|
|
if(parseip(ip, name) == 0)
|
2009-10-11 00:04:03 +04:00
|
|
|
return 0;
|
2014-08-03 20:28:37 +04:00
|
|
|
|
2009-10-11 00:04:03 +04:00
|
|
|
/* BUG - Name resolution blocks. Need a non-blocking DNS. */
|
|
|
|
taskstate("netlookup");
|
2015-06-15 23:10:38 +03:00
|
|
|
if(getaddrinfo(name, NULL, NULL, &result) == 0) {
|
2012-08-01 06:00:00 +04:00
|
|
|
switch (result->ai_family) {
|
|
|
|
case AF_INET:
|
|
|
|
v4tov6(ip, (unsigned char*)&((struct sockaddr_in*)result->ai_addr)->sin_addr.s_addr);
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
memcpy(ip, (unsigned char*)&((struct sockaddr_in6*)result->ai_addr)->sin6_addr.s6_addr, sizeof(struct in6_addr));
|
|
|
|
break;
|
|
|
|
}
|
2009-10-11 00:04:03 +04:00
|
|
|
taskstate("netlookup succeeded");
|
fix warnings reported by Coverity
fd.c:230 negative_returns: fd is passed to a parameter that cannot be negative.
net.c:65 check_return: Calling setsockopt(fd, 1, 2, (char *)&n, 4U) without checking return value.
net.c:77 check_return: Calling fdnoblock(fd) without checking return value.
net.c:112 check_return: Calling fdnoblock(cfd) without checking return value.
net.c:114 check_return: Calling setsockopt(cfd, IPPROTO_TCP, 1, (char *)&one, 4U) without checking return value.
net.c:144 leaked_storage: Variable result going out of scope leaks the storage it points to.
net.c:168 check_return: Calling fdnoblock(fd) without checking return value.
net.c:173 check_return: Calling setsockopt(fd, 1, 6, &n, 4U) without checking return value.
net.c:206 check_return: Calling getsockopt(fd, 1, 4, (void *)&n, &sn) without checking return value.
task.c:59 negative_returns: fd is passed to a parameter that cannot be negative.
tcpload.c:50 Calling fdread without checking return value (as is done elsewhere 4 out of 5 times).
tcpproxy.c:51 check_return: Calling fdnoblock(fd) without checking return value.
2015-06-25 00:16:58 +03:00
|
|
|
freeaddrinfo(result);
|
2009-10-11 00:04:03 +04:00
|
|
|
return 0;
|
|
|
|
}
|
2014-08-03 20:28:37 +04:00
|
|
|
|
2009-10-11 00:04:03 +04:00
|
|
|
taskstate("netlookup failed");
|
fix warnings reported by Coverity
fd.c:230 negative_returns: fd is passed to a parameter that cannot be negative.
net.c:65 check_return: Calling setsockopt(fd, 1, 2, (char *)&n, 4U) without checking return value.
net.c:77 check_return: Calling fdnoblock(fd) without checking return value.
net.c:112 check_return: Calling fdnoblock(cfd) without checking return value.
net.c:114 check_return: Calling setsockopt(cfd, IPPROTO_TCP, 1, (char *)&one, 4U) without checking return value.
net.c:144 leaked_storage: Variable result going out of scope leaks the storage it points to.
net.c:168 check_return: Calling fdnoblock(fd) without checking return value.
net.c:173 check_return: Calling setsockopt(fd, 1, 6, &n, 4U) without checking return value.
net.c:206 check_return: Calling getsockopt(fd, 1, 4, (void *)&n, &sn) without checking return value.
task.c:59 negative_returns: fd is passed to a parameter that cannot be negative.
tcpload.c:50 Calling fdread without checking return value (as is done elsewhere 4 out of 5 times).
tcpproxy.c:51 check_return: Calling fdnoblock(fd) without checking return value.
2015-06-25 00:16:58 +03:00
|
|
|
freeaddrinfo(result);
|
2009-10-11 00:04:03 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
netdial(int istcp, char *server, int port)
|
|
|
|
{
|
|
|
|
int proto, fd, n;
|
2012-08-01 06:00:00 +04:00
|
|
|
unsigned char ip[IPaddrlen];
|
|
|
|
struct sockaddr_storage ss;
|
2009-10-11 00:04:03 +04:00
|
|
|
socklen_t sn;
|
2014-08-03 20:28:37 +04:00
|
|
|
|
2012-08-01 06:00:00 +04:00
|
|
|
if(netlookup(server, ip) < 0)
|
2009-10-11 00:04:03 +04:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
taskstate("netdial");
|
|
|
|
proto = istcp ? SOCK_STREAM : SOCK_DGRAM;
|
2012-08-01 06:00:00 +04:00
|
|
|
if((fd = socket(family(ip), proto, 0)) < 0){
|
2009-10-11 00:04:03 +04:00
|
|
|
taskstate("socket failed");
|
|
|
|
return -1;
|
|
|
|
}
|
fix warnings reported by Coverity
fd.c:230 negative_returns: fd is passed to a parameter that cannot be negative.
net.c:65 check_return: Calling setsockopt(fd, 1, 2, (char *)&n, 4U) without checking return value.
net.c:77 check_return: Calling fdnoblock(fd) without checking return value.
net.c:112 check_return: Calling fdnoblock(cfd) without checking return value.
net.c:114 check_return: Calling setsockopt(cfd, IPPROTO_TCP, 1, (char *)&one, 4U) without checking return value.
net.c:144 leaked_storage: Variable result going out of scope leaks the storage it points to.
net.c:168 check_return: Calling fdnoblock(fd) without checking return value.
net.c:173 check_return: Calling setsockopt(fd, 1, 6, &n, 4U) without checking return value.
net.c:206 check_return: Calling getsockopt(fd, 1, 4, (void *)&n, &sn) without checking return value.
task.c:59 negative_returns: fd is passed to a parameter that cannot be negative.
tcpload.c:50 Calling fdread without checking return value (as is done elsewhere 4 out of 5 times).
tcpproxy.c:51 check_return: Calling fdnoblock(fd) without checking return value.
2015-06-25 00:16:58 +03:00
|
|
|
if(fdnoblock(fd) < 0){
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-10-11 00:04:03 +04:00
|
|
|
|
|
|
|
/* for udp */
|
|
|
|
if(!istcp){
|
|
|
|
n = 1;
|
fix warnings reported by Coverity
fd.c:230 negative_returns: fd is passed to a parameter that cannot be negative.
net.c:65 check_return: Calling setsockopt(fd, 1, 2, (char *)&n, 4U) without checking return value.
net.c:77 check_return: Calling fdnoblock(fd) without checking return value.
net.c:112 check_return: Calling fdnoblock(cfd) without checking return value.
net.c:114 check_return: Calling setsockopt(cfd, IPPROTO_TCP, 1, (char *)&one, 4U) without checking return value.
net.c:144 leaked_storage: Variable result going out of scope leaks the storage it points to.
net.c:168 check_return: Calling fdnoblock(fd) without checking return value.
net.c:173 check_return: Calling setsockopt(fd, 1, 6, &n, 4U) without checking return value.
net.c:206 check_return: Calling getsockopt(fd, 1, 4, (void *)&n, &sn) without checking return value.
task.c:59 negative_returns: fd is passed to a parameter that cannot be negative.
tcpload.c:50 Calling fdread without checking return value (as is done elsewhere 4 out of 5 times).
tcpproxy.c:51 check_return: Calling fdnoblock(fd) without checking return value.
2015-06-25 00:16:58 +03:00
|
|
|
if(setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &n, sizeof n) < 0){
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-10-11 00:04:03 +04:00
|
|
|
}
|
2014-08-03 20:28:37 +04:00
|
|
|
|
2009-10-11 00:04:03 +04:00
|
|
|
/* start connecting */
|
2012-08-01 06:00:00 +04:00
|
|
|
memset(&ss, 0, sizeof ss);
|
|
|
|
ss.ss_family = family(ip);
|
|
|
|
switch(ss.ss_family){
|
|
|
|
case AF_INET:
|
|
|
|
v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, ip);
|
|
|
|
hnputs(&((struct sockaddr_in*)&ss)->sin_port, port);
|
|
|
|
break;
|
|
|
|
case AF_INET6:
|
|
|
|
memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, ip, sizeof(struct in6_addr));
|
|
|
|
hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, port);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(connect(fd, (struct sockaddr*)&ss, sizeof ss) < 0 && errno != EINPROGRESS){
|
2009-10-11 00:04:03 +04:00
|
|
|
taskstate("connect failed");
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-08-03 20:28:37 +04:00
|
|
|
/* wait for finish */
|
2009-10-11 00:04:03 +04:00
|
|
|
fdwait(fd, 'w');
|
2012-08-01 06:00:00 +04:00
|
|
|
sn = sizeof ss;
|
|
|
|
if(getpeername(fd, (struct sockaddr*)&ss, &sn) >= 0){
|
2009-10-11 00:04:03 +04:00
|
|
|
taskstate("connect succeeded");
|
|
|
|
return fd;
|
|
|
|
}
|
2014-08-03 20:28:37 +04:00
|
|
|
|
2009-10-11 00:04:03 +04:00
|
|
|
/* report error */
|
|
|
|
sn = sizeof n;
|
fix warnings reported by Coverity
fd.c:230 negative_returns: fd is passed to a parameter that cannot be negative.
net.c:65 check_return: Calling setsockopt(fd, 1, 2, (char *)&n, 4U) without checking return value.
net.c:77 check_return: Calling fdnoblock(fd) without checking return value.
net.c:112 check_return: Calling fdnoblock(cfd) without checking return value.
net.c:114 check_return: Calling setsockopt(cfd, IPPROTO_TCP, 1, (char *)&one, 4U) without checking return value.
net.c:144 leaked_storage: Variable result going out of scope leaks the storage it points to.
net.c:168 check_return: Calling fdnoblock(fd) without checking return value.
net.c:173 check_return: Calling setsockopt(fd, 1, 6, &n, 4U) without checking return value.
net.c:206 check_return: Calling getsockopt(fd, 1, 4, (void *)&n, &sn) without checking return value.
task.c:59 negative_returns: fd is passed to a parameter that cannot be negative.
tcpload.c:50 Calling fdread without checking return value (as is done elsewhere 4 out of 5 times).
tcpproxy.c:51 check_return: Calling fdnoblock(fd) without checking return value.
2015-06-25 00:16:58 +03:00
|
|
|
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, (void*)&n, &sn) < 0){
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
|
|
|
}
|
2009-10-11 00:04:03 +04:00
|
|
|
if(n == 0)
|
|
|
|
n = ECONNREFUSED;
|
|
|
|
close(fd);
|
|
|
|
taskstate("connect failed");
|
|
|
|
errno = n;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|