/* Copyright (C) 2009-2014, Martin Johansson <martin@fatbob.nu>
- Copyright (C) 2005-2014, Thorvald Natvig <thorvald@natvig.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.
-*/
+ Copyright (C) 2005-2014, Thorvald Natvig <thorvald@natvig.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 <sys/poll.h>
#include <sys/socket.h>
#include <fcntl.h>
#include "version.h"
#include "voicetarget.h"
#include "ban.h"
+#include "util.h"
extern char system_string[], version_string[];
bool_t bPreferAlpha;
extern int* udpsocks;
+extern bool_t hasv4;
void Client_init()
{
client->tokencount++;
}
-bool_t Client_token_match(client_t *client, char *str)
+bool_t Client_token_match(client_t *client, char const *str)
{
token_t *token;
struct dlist *itr;
client_itr = NULL;
while (Client_iterate(&client_itr) != NULL) {
if ((client_itr->authenticated || client_itr == connectingClient) &&
- !client_itr->bOpus) {
+ !client_itr->bOpus) {
Client_textmessage(client_itr, OPUS_WARN_SWITCHING);
}
}
{
client_t* newclient;
message_t *sendmsg;
- char addressPresentation[INET6_ADDRSTRLEN];
- int port;
-#warning FIX BANNING BEFORE RELEASE
-#if 0
- if (Ban_isBannedAddr((in_addr_t *)&remote->sin_addr)) {
- Log_info("Address %s banned. Disconnecting", inet_ntoa(remote->sin_addr));
+ if (Ban_isBannedAddr(remote)) {
+ Log_info("Address %s banned. Disconnecting", Util_addressToString(remote));
return -1;
}
-#endif
if ((newclient = calloc(1, sizeof(client_t))) == NULL)
- Log_fatal("Out of memory (%s:%s)", __FILE__, __LINE__);
-
- 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);
- }
-
- 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;
}
* 1. A valid size. The only message that is this big is UserState message with a big texture
* 2. An invalid size = protocol error, e.g. connecting with a 1.1.x client
*/
-// Log_warn("Too big message received (%d bytes). Playing safe and disconnecting client %s:%d",
-// client->msgsize, inet_ntoa(client->remote_tcp.sin_addr), ntohs(client->remote_tcp.sin_port));
+ // Log_warn("Too big message received (%d bytes). Playing safe and disconnecting client %s:%d",
+ // client->msgsize, inet_ntoa(client->remote_tcp.sin_addr), ntohs(client->remote_tcp.sin_port));
Client_free(client);
return -1;
/* client->rxcount = client->msgsize = 0; */
return 0;
}
else if (SSLi_get_error(client->ssl, rc) == SSLI_ERROR_ZERO_RETURN ||
- SSLi_get_error(client->ssl, rc) == 0) {
+ SSLi_get_error(client->ssl, rc) == 0) {
Log_info_client(client, "Connection closed by peer");
Client_close(client);
}
Log_info_client(client, "Connection closed by peer");
else
Log_info_client(client,"Error: %s - Closing connection (code %d)",
- strerror(errno));
+ strerror(errno));
}
else if (SSLi_get_error(client->ssl, rc) == SSLI_ERROR_CONNRESET) {
Log_info_client(client, "Connection reset by peer");
return Client_send_message(client, msg);
else
Msg_free(msg);
+ return -1;
}
int Client_send_message(client_t *client, message_t *msg)
}
if (client->txsize != 0 || !client->SSLready) {
/* Queue message */
- if ((client->txQueueCount > 5 && msg->messageType == UDPTunnel) ||
+ if ((client->txQueueCount > 5 && msg->messageType == UDPTunnel) ||
client->txQueueCount > 30) {
Msg_free(msg);
return -1;
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) {
+ if (len <= 0)
return -1;
- } else 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;
}
len -= 4; /* Adjust for crypt header */
msgType = (UDPMessageType_t)((buffer[0] >> 5) & 0x7);
switch (msgType) {
- case UDPVoiceSpeex:
- case UDPVoiceCELTAlpha:
- case UDPVoiceCELTBeta:
- if (bOpus)
+ case UDPVoiceSpeex:
+ case UDPVoiceCELTAlpha:
+ case UDPVoiceCELTBeta:
+ if (bOpus)
+ break;
+ case UDPVoiceOpus:
+ Client_voiceMsg(itr, buffer, len);
+ break;
+ case UDPPing:
+ Log_debug("UDP Ping reply len %d", len);
+ Client_send_udp(itr, buffer, len);
+ break;
+ default:
+ Log_debug("Unknown UDP message type from %s port %d", Util_clientAddressToString(itr), fromport);
break;
- case UDPVoiceOpus:
- Client_voiceMsg(itr, buffer, len);
- break;
- case UDPPing:
- Log_debug("UDP Ping reply len %d", len);
- Client_send_udp(itr, buffer, len);
- break;
- default:
- Log_debug("Unknown UDP message type from %s port %d", itr->addressString, fromport);
- break;
}
out:
c = list_get_entry(itr, client_t, chan_node);
Client_send_voice(client, c, buffer, pds->offset + 1, poslen);
}
- } else if ((vt = Voicetarget_get_id(client, target)) != NULL) { /* Targeted whisper */
+ } else if ((vt = Voicetarget_get_id(client, target)) != NULL) { /* Targeted whisper */
int i;
channel_t *ch;
/* Channels */
if (vt->channels[i].linked && !list_empty(&ch->channel_links)) {
struct dlist *ch_itr;
list_iterate(ch_itr, &ch->channel_links) {
+ channellist_t *chl;
channel_t *ch_link;
- ch_link = list_get_entry(ch_itr, channel_t, link_node);
+ chl = list_get_entry(ch_itr, channellist_t, node);
+ ch_link = chl->chan;
list_iterate(itr, &ch_link->clients) {
client_t *c;
c = list_get_entry(itr, client_t, chan_node);
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);
+ int udpsock = (client->remote_udp.ss_family == AF_INET) ? udpsocks[0] : udpsocks[(hasv4) ? 1 : 0];
- 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);
CryptState_encrypt(&client->cryptState, data, buf, len);
- if (client->remote_udp.ss_family == AF_INET)
- sendto(udpsock, buf, len + 4, 0, (struct sockaddr *)&client->remote_udp, sizeof(struct sockaddr_in));
- else
- sendto(udpsock, buf, len + 4, 0, (struct sockaddr *)&client->remote_udp, sizeof(struct sockaddr_in6));
+#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
+ sendto(udpsock, buf, len + 4, 0, (struct sockaddr *)&client->remote_udp, client->remote_tcp.ss_len);
+#else
+ sendto(udpsock, buf, len + 4, 0, (struct sockaddr *)&client->remote_udp, sizeof(struct sockaddr_storage));
+#endif
free(mbuf);
} else {