diff options
author | Jakub Sławiński | 2005-03-15 01:22:55 +0100 |
---|---|---|
committer | Joshua Judson Rosen | 2014-07-17 21:14:58 +0200 |
commit | 1adde65db245ec1fca752cfee4c198badf40fb5f (patch) | |
tree | bba33f3b1fe7d469f9df7a89af9dac77b27fa3bb /src/network.c | |
parent | udp_patch (diff) | |
download | apf-1adde65db245ec1fca752cfee4c198badf40fb5f.tar.gz |
v0.6
- Fixed: default password incompatibilities from config file
- Added: "client's id" option
- Lightly Modified: verbose mode
- Added: temporary listen ports
- Fixed: bug in printing "client's id"
- Added: 'dateformat' option to set format of the date in the logs
- Modified: command line option and config file behaviour
- Added: logging to a socket
- Fixed: parsing config file
- Fixed: major bug in packet buffering
- Added: several clients-users in one realm
- Modified: default hostname used by afserver
- Modified: server listening behaviour (for clients)
- Fixed: bug in checking options values
- Modified: verbose mode
- Modified: client initial connection to server
- Added: connection time / uptime statistics
- Added: first version of remote administration (statistics only)
- Fixed: major bug in remove_client routine
- Added: 'raclients' option
- Added: use of automake/autoconf
- Added: creating ~/.apf directory
- Modified: the way of creating/managing keys/certificates
- Added: 'dnslookups' option
- Modified: usage functions
- Fixed: no handling of missing 'listen' option after 'newrealm' in config file
- Added: 'quit' command in remote administration mode
- Modified: logging error messages during initialization
- Modified: 'newrealm' changed to 'realm' in config file
- Added: realm names
- Modified: connection time / uptime
- Added: client names / unique numbers
- Added: user unique numbers
- Fixed: segmentation fault after 'quit' command
Diffstat (limited to 'src/network.c')
-rw-r--r-- | src/network.c | 484 |
1 files changed, 484 insertions, 0 deletions
diff --git a/src/network.c b/src/network.c new file mode 100644 index 0000000..7618c76 --- /dev/null +++ b/src/network.c @@ -0,0 +1,484 @@ +/* + * active port forwarder - software for secure forwarding + * Copyright (C) 2003,2004,2005 jeremian <jeremian [at] poczta.fm> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include "inet_ntop.h" +#include "network.h" +#include "activefor.h" +#include "stats.h" +#include <string.h> +#include <errno.h> +#include <zlib.h> + +int +ip_listen(int* sockfd, const char *host, const char *serv, socklen_t *addrlenp, const char type) +{ +#if defined(HAVE_GETADDRINFO) && defined(AF_INET6) + int n; + const int on = 1; + struct addrinfo hints, *res, *ressave; + + bzero(&hints, sizeof(struct addrinfo)); + hints.ai_flags = AI_PASSIVE; + if (type & 0x02) { + hints.ai_family = AF_INET; + } + else if (type & 0x04) { + hints.ai_family = AF_INET6; + } + else { + hints.ai_family = AF_UNSPEC; + } + + if (type & 0x01) { + hints.ai_socktype = SOCK_STREAM; + } + else { + hints.ai_socktype = SOCK_DGRAM; + } + + if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) { + return n; + } + ressave = res; + + do { + (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if ((*sockfd) < 0) { + continue; /* error, try next one */ + } + + if (type & 0x01) { /* tcp_listen */ + setsockopt((*sockfd), SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + } + if (bind((*sockfd), res->ai_addr, res->ai_addrlen) == 0) { + break; /* success */ + } + + close((*sockfd)); /* bind error, close and try next one */ + } while ( (res = res->ai_next) != NULL); + + if (res == NULL) { /* errno from final socket() or bind() */ + return 1; + } + + if (type & 0x01) { /* tcp_listen */ + listen((*sockfd), 1); + } + + if (addrlenp) { + *addrlenp = res->ai_addrlen; /* return size of protocol address */ + } + + freeaddrinfo(ressave); +#else + struct sockaddr_in servaddr; + struct hostent* hostaddr; + int port; + + if (type & 0x01) { + (*sockfd) = socket(AF_INET, SOCK_STREAM, 0); + } + else { + (*sockfd) = socket(AF_INET, SOCK_DGRAM, 0); + } + + if ((*sockfd) == -1) { + return 1; + } + port = atoi(serv); + + if (host) { + hostaddr = gethostbyname(host); + if (hostaddr == NULL) { + return 2; + } + } + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + if (host) { + memcpy(&servaddr.sin_addr.s_addr, hostaddr->h_addr_list[0], hostaddr->h_length); + } + else { + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + } + servaddr.sin_port = htons(port); + + if (bind((*sockfd), (struct sockaddr*) &servaddr, sizeof(servaddr))){ + return 4; + } + + if (listen((*sockfd), 5)){ + return 5; + } +#endif + + return(0); +} + +int +ip_connect(int* sockfd, const char *host, const char *serv, const char type) +{ +#if defined(HAVE_GETADDRINFO) && defined(AF_INET6) + int n; + struct addrinfo hints, *res, *ressave; + + bzero(&hints, sizeof(struct addrinfo)); + if (type & 0x02) { + hints.ai_family = AF_INET; + } + else if (type & 0x04) { + hints.ai_family = AF_INET6; + } + else { + hints.ai_family = AF_UNSPEC; + } + if (type & 0x01) { + hints.ai_socktype = SOCK_STREAM; + } + else { + hints.ai_socktype = SOCK_DGRAM; + } + + if ( (n = getaddrinfo(host, serv, &hints, &res)) != 0) { + return n; + } + ressave = res; + + do { + (*sockfd) = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if ((*sockfd) < 0) { + continue; /* ignore this one */ + } + + if (connect((*sockfd), res->ai_addr, res->ai_addrlen) == 0) { + break; /* success */ + } + + close((*sockfd)); /* ignore this one */ + } while ( (res = res->ai_next) != NULL); + + if (res == NULL) { /* errno set from final connect() */ + return 1; + } + + freeaddrinfo(ressave); +#else + struct sockaddr_in servaddr; + struct hostent* hostaddr; + int port; + + if (type & 0x01) { + (*sockfd) = socket(AF_INET, SOCK_STREAM, 0); + } + else { + (*sockfd) = socket(AF_INET, SOCK_DGRAM, 0); + } + + if ((*sockfd) == -1) { + return 1; + } + port = atoi(serv); + + hostaddr = gethostbyname(host); + if (hostaddr == NULL) { + return 2; + } + + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(port); + memcpy(&servaddr.sin_addr.s_addr, hostaddr->h_addr_list[0], hostaddr->h_length); + + if (connect((*sockfd), (struct sockaddr*) &servaddr, sizeof(servaddr))){ + return 3; + } +#endif + + return(0); +} + +char * +sock_ntop(const struct sockaddr *sa, socklen_t salen, char* namebuf, char* portbuf, char type) +{ + char portstr[7]; + static char str[136]; /* Unix domain is largest */ + + switch (sa->sa_family) { + case AF_INET: { + struct sockaddr_in *sin = (struct sockaddr_in *) sa; + + if (type) { +#ifdef HAVE_GETNAMEINFO + if (getnameinfo(sa, salen, str, 128, NULL, 0, 0)) { + return NULL; + } +#else + struct hostent* hostname; + if ((hostname = gethostbyaddr(&sin->sin_addr, sizeof(struct in_addr), AF_INET))) { + strncpy(str, hostname->h_name, 127); + str[127] = 0; + } + else { + if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) { + return NULL; + } + } +#endif + + } + else { + if (inet_ntop(AF_INET, &sin->sin_addr, str, sizeof(str)) == NULL) { + return NULL; + } + } + if (namebuf) { + memcpy(namebuf, str, 128); + } + if (ntohs(sin->sin_port) != 0) { + snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin->sin_port)); + if (portbuf) { + snprintf(portbuf, 7, "%d", ntohs(sin->sin_port)); + } + strcat(str, portstr); + } + return(str); + } +#ifdef AF_INET6 + case AF_INET6: { + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; + + if (type) { +#ifdef HAVE_GETNAMEINFO + if (getnameinfo(sa, salen, str, 128, NULL, 0, 0)) { + return NULL; + } +#else + struct hostent* hostname; + if ((hostname = gethostbyaddr(&sin6->sin6_addr, sizeof(struct in6_addr), AF_INET6))) { + strncpy(str, hostname->h_name, 127); + str[127] = 0; + } + else { + if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) { + return NULL; + } + } +#endif + + } + else { + if (inet_ntop(AF_INET6, &sin6->sin6_addr, str, sizeof(str)) == NULL) { + return NULL; + } + } + if (namebuf) { + memcpy(namebuf, str, 128); + } + if (ntohs(sin6->sin6_port) != 0) { + snprintf(portstr, sizeof(portstr), ".%d", ntohs(sin6->sin6_port)); + if (portbuf) { + snprintf(portbuf, 7, "%d", ntohs(sin6->sin6_port)); + } + strcat(str, portstr); + } + return(str); + } +#endif + default: { + snprintf(str, sizeof(str), "sock_ntop: unknown AF_xxx: %d, len %d", sa->sa_family, salen); + return(str); + } + } + return NULL; +} + +int +SSL_writen(SSL* fd, unsigned char* buf, int amount) +{ + int sent, n; + sent = 0; + while (sent < amount) { + n = SSL_write(fd, buf+sent, amount - sent); + if (n != -1) { + sent += n; + } + if (n == -1) { + if (errno != EAGAIN) + return 0; + } + } + return amount; +} + +int +SSL_readn(SSL* fd, unsigned char* buf, int amount) +{ + int sent, n; + sent = 0; + while (sent < amount) { + n = SSL_read(fd, buf+sent, amount - sent); + if (n != -1) { + sent += n; + } + if (n == 0) + return 0; + if (n == -1) { + if (errno != EAGAIN) + return 0; + } + } + return amount; +} + +int +writen(int fd, unsigned char* buf, int amount) +{ + int sent, n; + sent = 0; + while (sent < amount) { + n = write(fd, buf+sent, amount - sent); + if (n != -1) { + sent += n; + } + if (n == -1) { + if (errno != EAGAIN) + return 0; + } + } + return amount; +} + +int +readn(int fd, unsigned char* buf, int amount) +{ + int sent, n; + sent = 0; + while (sent < amount) { + n = read(fd, buf+sent, amount - sent); + if (n != -1) { + sent += n; + } + if (n == 0) + return 0; + if (n == -1) { + if (errno != EAGAIN) + return 0; + } + } + return amount; + +} + +int +send_message(char type, clifd fd, unsigned char* buf, int amount) +{ + unsigned long clen; + int length; + static unsigned char bufor[9000]; + aflog(4, " send_message: ssl:%s zlib:%s length:%d", (TYPE_IS_SSL(type))?"yes":"no", + (TYPE_IS_ZLIB(type))?"yes":"no", amount); + clen = 8995; + length = amount - 5; + if (TYPE_IS_ZLIB(type)) { + memcpy(bufor, buf, 5); + if (amount > 5) { + compress(&bufor[5], &clen, &buf[5], length); + if (clen < length) { + length = clen; + TYPE_SET_COMP(length); + bufor[3] = length >> 8; /* high bits of message length */ + bufor[4] = length; /* low bits of message length */ + addtocg(amount-5 - clen); + } + } + if (TYPE_IS_SSL(type)) { + if (TYPE_IS_COMP(length)) { + return SSL_writen(fd.ssl, bufor, clen+5); + } + else { + return SSL_writen(fd.ssl, buf, amount); + } + } + else { + if (TYPE_IS_COMP(length)) { + return writen(fd.commfd, bufor, clen+5); + } + else { + return writen(fd.commfd, buf, amount); + } + } + } + else { + if (TYPE_IS_SSL(type)) { + return SSL_writen(fd.ssl, buf, amount); + } + else { + return writen(fd.commfd, buf, amount); + } + } +} + +int +get_message(char type, clifd fd, unsigned char* buf, int amount) +{ + int length; + unsigned long elen; + static unsigned char bufor[9000]; + aflog(4, " get_message: ssl:%s zlib:%s length:%d", (TYPE_IS_SSL(type))?"yes":"no", + (TYPE_IS_ZLIB(type))?"yes":"no", amount); + if (amount == -5) { + if (TYPE_IS_SSL(type)) { + return SSL_read(fd.ssl, buf, 5); + } + else { + return read(fd.commfd, buf, 5); + } + } + if (TYPE_IS_ZLIB(type)) { + if (TYPE_IS_SSL(type)) { + length = SSL_readn(fd.ssl, bufor, amount&0xBFFF); + } + else { + length = readn(fd.commfd, bufor, amount&0xBFFF); + } + if (length <= 0) return length; + elen = 8096; + if (TYPE_IS_COMP(amount)) { + uncompress(buf, &elen, bufor, length); + } + else { + memcpy(buf, bufor, length); + elen = length; + } + return elen; + } + else + { + if (TYPE_IS_SSL(type)) { + return SSL_readn(fd.ssl, buf, amount); + } + else { + return readn(fd.commfd, buf, amount); + } + } +} |