This patchset is mainly consisting of code cleanups and maintainance.
- Introduced new header util.h containing utility functions to convert
addresses to char* typed string representations in a generic way and
to get the port of an address as an int. There are also functions that
work with client structures
- Replaced occurences of older conversions with the new functions
- Replaced hardcoded values with preprocessor macros where applicable
- Reduced code duplication resulting from new IPv6 support where
possible
- Other general cleanups where applicable
${CMAKE_CURRENT_SOURCE_DIR}/pds.c
${CMAKE_CURRENT_SOURCE_DIR}/server.c
${CMAKE_CURRENT_SOURCE_DIR}/timer.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/util.c
${CMAKE_CURRENT_SOURCE_DIR}/voicetarget.c
)
#include "ban.h"
#include "conf.h"
#include "ssl.h"
+#include "util.h"
static void Ban_saveBanFile(void);
static void Ban_readBanFile(void);
SSLi_hash2hex(ban->hash, hexhash);
Log_info_client(client, "User kickbanned. Reason: '%s' Hash: %s IP: %s Banned for: %d seconds",
- ban->reason, hexhash, client->addressString, ban->duration);
+ ban->reason, hexhash, Util_clientAddressToString(client), ban->duration);
}
#include "version.h"
#include "voicetarget.h"
#include "ban.h"
+#include "util.h"
extern char system_string[], version_string[];
{
client_t* newclient;
message_t *sendmsg;
- char addressPresentation[INET6_ADDRSTRLEN];
- int port;
-
- if(remote->ss_family == AF_INET) {
- inet_ntop(AF_INET, &((struct sockaddr_in*)remote)->sin_addr, addressPresentation, INET6_ADDRSTRLEN);
- port = ntohs(((struct sockaddr_in*)remote)->sin_port);
- } else {
- inet_ntop(AF_INET6, &((struct sockaddr_in6*)remote)->sin6_addr, addressPresentation, INET6_ADDRSTRLEN);
- port = ntohs(((struct sockaddr_in6*)remote)->sin6_port);
- }
if (Ban_isBannedAddr(remote)) {
- Log_info("Address %s banned. Disconnecting", addressPresentation);
+ Log_info("Address %s banned. Disconnecting", Util_addressToString(remote));
return -1;
}
if ((newclient = calloc(1, sizeof(client_t))) == NULL)
- Log_fatal("Out of memory (%s:%s)", __FILE__, __LINE__);
-
- memcpy(newclient->addressString, addressPresentation, INET6_ADDRSTRLEN);
+ Log_fatal("(%s:%s): Out of memory while allocating %d bytes.", __FILE__, __LINE__, sizeof(client_t));
newclient->tcpfd = fd;
memcpy(&newclient->remote_tcp, remote, sizeof(struct sockaddr_storage));
newclient->ssl = SSLi_newconnection(&newclient->tcpfd, &newclient->SSLready);
if (newclient->ssl == NULL) {
- Log_warn("SSL negotiation failed with %s on port %d", addressPresentation, port);
+ Log_warn("SSL negotiation failed with %s on port %d", Util_addressToString(remote), Util_addressToPort(remote));
free(newclient);
return -1;
}
return Client_send_message(client, msg);
else
Msg_free(msg);
+ return -1;
}
int Client_send_message(client_t *client, message_t *msg)
memset(key, 0, KEY_LENGTH);
+ fromport = Util_addressToPort(&from);
+
if(from.ss_family == AF_INET) {
memcpy(fromaddress, &((struct sockaddr_in*)&from)->sin_addr, sizeof(in_addr_t));
- fromport = ntohs(((struct sockaddr_in*)&from)->sin_port);
memcpy(&key[0], &fromport, 2);
memcpy(&key[2], fromaddress, sizeof(in_addr_t));
} else {
memcpy(fromaddress, &((struct sockaddr_in6*)&from)->sin6_addr, 4 * sizeof(in_addr_t));
- fromport = ntohs(((struct sockaddr_in6*)&from)->sin6_port);
memcpy(&key[0], &fromport, 2);
memcpy(&key[2], fromaddress, 4 * sizeof(in_addr_t));
}
- if (len == 0) {
- return -1;
- } else if (len < 0) {
+ if (len <= 0)
return -1;
- } else if (len < 5) {
- // 4 bytes crypt header + type + session
- return 0;
- } else if (len > UDP_PACKET_SIZE) {
+ else if (len < 5 || len > UDP_PACKET_SIZE) /* 4 bytes crypt header + type + session */
return 0;
- }
- /* Ping packet */
+ /*
+ * Reply to ping packet
+ * The second and third uint32_t are the timestamp, which will be returned unmodified
+ */
if (len == 12 && *encrypted == 0) {
uint32_t *ping = (uint32_t *)encrypted;
ping[0] = htonl((uint32_t)PROTOCOL_VERSION);
- // 1 and 2 will be the timestamp, which we return unmodified.
ping[3] = htonl((uint32_t)clientcount);
ping[4] = htonl((uint32_t)getIntConf(MAX_CLIENTS));
ping[5] = htonl((uint32_t)getIntConf(MAX_BANDWIDTH));
if (memcmp(itraddress, fromaddress, addresslength) == 0) {
if (checkDecrypt(itr, encrypted, buffer, len)) {
memcpy(itr->key, key, KEY_LENGTH);
- Log_info_client(itr, "New UDP connection from %s on port %d", itr->addressString, fromport);
+ Log_info_client(itr, "New UDP connection from %s on port %d", Util_clientAddressToString(itr), fromport);
memcpy(&itr->remote_udp, &from, sizeof(struct sockaddr_storage));
break;
}
Client_send_udp(itr, buffer, len);
break;
default:
- Log_debug("Unknown UDP message type from %s port %d", itr->addressString, fromport);
+ Log_debug("Unknown UDP message type from %s port %d", Util_clientAddressToString(itr), fromport);
break;
}
static int Client_send_udp(client_t *client, uint8_t *data, int len)
{
uint8_t *buf, *mbuf;
- uint16_t clientport;
int udpsock = (client->remote_udp.ss_family == AF_INET) ? udpsocks[0] : udpsocks[1];
- if (client->remote_udp.ss_family == AF_INET)
- clientport = ntohs(((struct sockaddr_in*)&client->remote_udp)->sin_port);
- else
- clientport = ntohs(((struct sockaddr_in6*)&client->remote_udp)->sin6_port);
- if (clientport != 0 && CryptState_isValid(&client->cryptState) &&
+ if (Util_clientAddressToPortUDP(client) != 0 && CryptState_isValid(&client->cryptState) &&
client->bUDP) {
#if defined(__LP64__)
buf = mbuf = malloc(len + 4 + 16);
bool_t shutdown_wait;
cryptState_t cryptState;
bool_t readBlockedOnWrite, writeBlockedOnRead;
-
struct sockaddr_storage remote_tcp;
struct sockaddr_storage remote_udp;
- char addressString[INET6_ADDRSTRLEN];
uint8_t rxbuf[BUFSIZE], txbuf[BUFSIZE];
uint32_t rxcount, msgsize, drainleft, txcount, txsize;
int sessionId;
#include "log.h"
#include "conf.h"
+#include "util.h"
#define STRSIZE 254
va_list argp;
char buf[STRSIZE + 1];
int offset = 0;
- uint16_t port;
if (termprint || logfile)
offset = sprintf(buf, "INFO: ");
offset += vsnprintf(&buf[offset], STRSIZE - offset, logstring, argp);
va_end(argp);
- if(client->remote_tcp.ss_family == AF_INET)
- port = ntohs(((struct sockaddr_in*)&client->remote_tcp)->sin_port);
- else
- port = ntohs(((struct sockaddr_in6*)&client->remote_tcp)->sin6_port);
-
offset += snprintf(&buf[offset], STRSIZE - offset, " - [%d] %s@%s:%d",
client->sessionId,
client->username == NULL ? "" : client->username,
- client->addressString,
- port);
+ Util_clientAddressToString(client),
+ Util_clientAddressToPortTCP(client));
if (termprint)
fprintf(stderr, "%s\n", buf);
#include "log.h"
#include "timer.h"
#include "version.h"
+#include "util.h"
#define TCP_SOCK 0
#define TCP_SOCK6 1
-
+#define TCP_SOCKS 2
#define UDP_SOCK 2
#define UDP_SOCK6 3
+#define UDP_SOCKS 2
+#define SERVER_SOCKS UDP_SOCKS + TCP_SOCKS
/* globals */
bool_t shutdown_server;
extern char *bindaddr6;
extern int bindport;
extern int bindport6;
-
int* udpsocks;
+const int on = 1;
+
/* Initialize the address structures for IPv4 and IPv6 */
struct sockaddr_storage** Server_setupAddressesAndPorts()
{
void Server_runLoop(struct pollfd* pollfds)
{
- int timeout = 1000, rc, clientcount;
+ int timeout, rc, clientcount;
etimer_t janitorTimer;
Timer_init(&janitorTimer);
pollfds[UDP_SOCK6].revents = 0;
pollfds[TCP_SOCK].revents = 0;
pollfds[TCP_SOCK6].revents = 0;
- clientcount = Client_getfds(&pollfds[4]);
+ clientcount = Client_getfds(&pollfds[SERVER_SOCKS]);
timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
if (timeout <= 0) {
Timer_restart(&janitorTimer);
timeout = (int)(1000000LL - (int64_t)Timer_elapsed(&janitorTimer)) / 1000LL;
}
- rc = poll(pollfds, clientcount + 4, timeout);
- if (rc == 0) { /* Timeout */
- /* Do maintenance */
+ rc = poll(pollfds, clientcount + SERVER_SOCKS, timeout);
+ if (rc == 0) {
+ /* Poll timed out, do maintenance */
Timer_restart(&janitorTimer);
Client_janitor();
continue;
if (errno == EINTR) /* signal */
continue;
else
- Log_fatal("poll: error %d", errno);
- }
- if (pollfds[TCP_SOCK].revents) { /* New tcp connection */
- int tcpfd, flag = 1;
- uint32_t addrlen;
- addrlen = sizeof(struct sockaddr_in);
- tcpfd = accept(pollfds[TCP_SOCK].fd, (struct sockaddr*)&remote, &addrlen);
- fcntl(tcpfd, F_SETFL, O_NONBLOCK);
- setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
- Log_debug("Connection from %s port %d\n", inet_ntoa(((struct sockaddr_in*)&remote)->sin_addr),
- ntohs(((struct sockaddr_in*)&remote)->sin_port));
- if (Client_add(tcpfd, &remote) < 0)
- close(tcpfd);
+ Log_fatal("poll: error %d (%s)", errno, strerror(errno));
}
- if (pollfds[TCP_SOCK6].revents) { /* New tcp connection */
- int tcpfd, flag = 1;
- uint32_t addrlen;
- addrlen = sizeof(struct sockaddr_in6);
- tcpfd = accept(pollfds[TCP_SOCK6].fd, (struct sockaddr*)&remote, &addrlen);
- fcntl(tcpfd, F_SETFL, O_NONBLOCK);
- setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
- if (Client_add(tcpfd, &remote) < 0)
- close(tcpfd);
+ /* Check for new connection */
+ for (i = 0; i < TCP_SOCKS; i++) {
+ if (pollfds[i].revents) {
+ static int tcpfd;
+ static uint32_t addrlen = sizeof(struct sockaddr_storage);
+ tcpfd = accept(pollfds[i].fd, (struct sockaddr *)&remote, &addrlen);
+ fcntl(tcpfd, F_SETFL, O_NONBLOCK);
+ setsockopt(tcpfd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(int));
+ Log_debug("Connection from %s port %d\n", Util_addressToString(&remote), Util_addressToPort(&remote));
+ if (Client_add(tcpfd, &remote) < 0)
+ close(tcpfd);
+ }
}
- if (pollfds[UDP_SOCK].revents) {
- Client_read_udp(udpsocks[0]);
- }
- if (pollfds[UDP_SOCK6].revents) {
- Client_read_udp(udpsocks[1]);
+ for (i = 2; i < SERVER_SOCKS; i++) {
+ if (pollfds[i].revents) {
+ Client_read_udp(udpsocks[i - UDP_SOCKS]);
+ }
}
+
for (i = 0; i < clientcount; i++) {
if (pollfds[i + 4].revents & POLLIN) {
Client_read_fd(pollfds[i + 4].fd);
if (setsockopt(sockets[0], SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) != 0)
Log_fatal("setsockopt IPv4: %s", strerror(errno));
if (bind(sockets[0], (struct sockaddr *)addresses[0], sizeof (struct sockaddr_in)) < 0)
- Log_fatal("bind IPv4: %s", strerror(errno));
+ Log_fatal("bind %s %d: %s", Util_addressToString(addresses[0]), Util_addressToPort(addresses[0]), strerror(errno));
if (listen(sockets[0], 3) < 0)
Log_fatal("listen IPv4");
fcntl(sockets[0], F_SETFL, O_NONBLOCK);
if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) != 0)
Log_fatal("setsockopt IPv6: %s", strerror(errno));
if (bind(sockets[1], (struct sockaddr *)addresses[1], sizeof (struct sockaddr_in6)) < 0)
- Log_fatal("bind IPv6: %s", strerror(errno));
+ Log_fatal("bind %s %d: %s", Util_addressToString(addresses[1]), Util_addressToPort(addresses[1]), strerror(errno));
if (listen(sockets[1], 3) < 0)
Log_fatal("listen IPv6");
fcntl(sockets[1], F_SETFL, O_NONBLOCK);
void Server_setupUDPSockets(struct sockaddr_storage* addresses[2], struct pollfd* pollfds)
{
- uint8_t yes = 1;
int val = 0;
int error = 0;
int sockets[2];
- char ipv6Representation[INET6_ADDRSTRLEN];
if((udpsocks = malloc(2 * sizeof(int))) == NULL)
Log_fatal("Out of memory (%s:%s)", __FILE__, __LINE__);
- inet_ntop(AF_INET6, &((struct sockaddr_in6*)addresses[1])->sin6_addr, ipv6Representation, sizeof(INET6_ADDRSTRLEN));
-
sockets[0] = socket(PF_INET, SOCK_DGRAM, 0);
if (bind(sockets[0], (struct sockaddr *) addresses[0], sizeof (struct sockaddr_in)) < 0)
- Log_fatal("bind %d %s: %s", ((struct sockaddr_in*)addresses[0])->sin_port,
- inet_ntoa(((struct sockaddr_in*)addresses[0])->sin_addr), strerror(errno));
+ Log_fatal("bind %s %d: %s", Util_addressToString(addresses[0]), Util_addressToPort(addresses[0]), strerror(errno));
val = 0xe0;
if (setsockopt(sockets[0], IPPROTO_IP, IP_TOS, &val, sizeof(val)) < 0)
Log_warn("Server: Failed to set TOS for UDP Socket");
pollfds[UDP_SOCK].events = POLLIN | POLLHUP | POLLERR;
sockets[1] = socket(PF_INET6, SOCK_DGRAM, 0);
- if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof(int)) != 0)
+ if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(int)) != 0)
Log_fatal("setsockopt IPv6: %s", strerror(errno));
if (bind(sockets[1], (struct sockaddr *) addresses[1], sizeof (struct sockaddr_in6)) < 0)
- Log_fatal("bind %d %s: %s", ((struct sockaddr_in*)addresses[1])->sin_port, ipv6Representation, strerror(errno));
+ Log_fatal("bind %s %d: %s", Util_addressToString(addresses[1]), Util_addressToPort(addresses[1]), strerror(errno));
val = 0xe0;
if (setsockopt(sockets[1], IPPROTO_IPV6, IPV6_TCLASS, &val, sizeof(val)) < 0)
Log_warn("Server: Failed to set TOS for UDP Socket");
fcntl(sockets[1], F_SETFL, O_NONBLOCK);
pollfds[UDP_SOCK6].fd = sockets[1];
pollfds[UDP_SOCK6].events = POLLIN | POLLHUP | POLLERR;
- udpsocks[0] = sockets[0];
- udpsocks[1] = sockets[1];
+ udpsocks[UDP_SOCK - UDP_SOCKS] = sockets[0];
+ udpsocks[UDP_SOCK6 - UDP_SOCKS] = sockets[1];
}
void Server_run()
--- /dev/null
+/* Copyright (C) 2014, Felix Morgner <felix.morgner@gmail.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#include "util.h"
+
+char* Util_addressToString(struct sockaddr_storage *address)
+{
+ char* addressString = NULL;
+
+ if (address->ss_family == AF_INET) {
+ addressString = malloc(INET_ADDRSTRLEN);
+ inet_ntop(AF_INET, &((struct sockaddr_in *)address)->sin_addr, addressString, INET_ADDRSTRLEN);
+ } else if(address->ss_family == AF_INET6) {
+ addressString = malloc(INET6_ADDRSTRLEN);
+ inet_ntop(AF_INET6, &((struct sockaddr_in6 *)address)->sin6_addr, addressString, INET6_ADDRSTRLEN);
+ }
+
+ return addressString;
+}
+
+int Util_addressToPort(struct sockaddr_storage *address)
+{
+ int port = 0;
+
+ if (address->ss_family == AF_INET) {
+ port = ntohs(((struct sockaddr_in *)address)->sin_port);
+ } else if(address->ss_family == AF_INET6) {
+ port = ntohs(((struct sockaddr_in6 *)address)->sin6_port);
+ }
+
+ return port;
+}
+
+char* Util_clientAddressToString(client_t *client)
+{
+ return Util_addressToString(&client->remote_tcp);
+}
+
+int Util_clientAddressToPortTCP(client_t *client)
+{
+ return Util_addressToPort(&client->remote_tcp);
+}
+
+int Util_clientAddressToPortUDP(client_t *client)
+{
+ return Util_addressToPort(&client->remote_udp);
+}
--- /dev/null
+/* Copyright (C) 2014, Felix Morgner <felix.morgner@gmail.com>
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ - Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ - Neither the name of the Developers nor the names of its contributors may
+ be used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+#ifndef __UTIL_H
+#define __UTIL_H
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include "client.h"
+
+char* Util_addressToString(struct sockaddr_storage *address);
+int Util_addressToPort(struct sockaddr_storage *address);
+char* Util_clientAddressToString(client_t *client);
+int Util_clientAddressToPortTCP(client_t *client);
+int Util_clientAddressToPortUDP(client_t *client);
+
+#endif // __UTIL_H