X-Git-Url: http://git.code-monkey.de/?a=blobdiff_plain;f=src%2Fclient.c;h=e3787a4832d3c1486f3fe2a3779b345e1dddcd1b;hb=14130a16fbe48dcba15d6e215ddaa0775074f3a7;hp=f7d2b709d35255a996d21541f20620f16ea6a7f7;hpb=b331021d492fd5febb576a61717a489c5cc875ff;p=umurmur.git diff --git a/src/client.c b/src/client.c index f7d2b70..e3787a4 100644 --- a/src/client.c +++ b/src/client.c @@ -62,7 +62,7 @@ bool_t bOpus = true; int iCodecAlpha, iCodecBeta; bool_t bPreferAlpha; -extern int udpsock; +extern int* udpsocks; void Client_init() { @@ -317,26 +317,39 @@ static int findFreeSessionId() return -1; } -int Client_add(int fd, struct sockaddr_in *remote) +int Client_add(int fd, struct sockaddr_storage *remote) { - client_t *newclient; + 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)); return -1; } - newclient = malloc(sizeof(client_t)); - if (newclient == NULL) - Log_fatal("Out of memory"); - memset(newclient, 0, sizeof(client_t)); +#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); newclient->tcpfd = fd; - memcpy(&newclient->remote_tcp, remote, sizeof(struct sockaddr_in)); + 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:%d", inet_ntoa(remote->sin_addr), - ntohs(remote->sin_port)); + Log_warn("SSL negotiation failed with %s on port %d", addressPresentation, port); free(newclient); return -1; } @@ -493,8 +506,8 @@ int Client_read(client_t *client) * 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; */ @@ -751,14 +764,16 @@ static bool_t checkDecrypt(client_t *client, const uint8_t *encrypted, uint8_t * } #define UDP_PACKET_SIZE 1024 -int Client_read_udp() +int Client_read_udp(int udpsock) { int len; - struct sockaddr_in from; - socklen_t fromlen = sizeof(struct sockaddr_in); - uint64_t key; + struct sockaddr_storage from; + socklen_t fromlen = sizeof(struct sockaddr_storage); + uint8_t key[KEY_LENGTH]; client_t *itr; UDPMessageType_t msgType; + uint8_t fromaddress[4 * sizeof(in_addr_t)]; + uint16_t fromport; #if defined(__LP64__) uint8_t encbuff[UDP_PACKET_SIZE + 8]; @@ -769,6 +784,21 @@ int Client_read_udp() uint8_t buffer[UDP_PACKET_SIZE]; len = recvfrom(udpsock, encrypted, UDP_PACKET_SIZE, MSG_TRUNC, (struct sockaddr *)&from, &fromlen); + + memset(key, 0, KEY_LENGTH); + + 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) { @@ -793,23 +823,35 @@ int Client_read_udp() return 0; } - key = (((uint64_t)from.sin_addr.s_addr) << 16) ^ from.sin_port; itr = NULL; while (Client_iterate(&itr) != NULL) { - if (itr->key == key) { + if (memcmp(itr->key, key, KEY_LENGTH) == 0) { if (!checkDecrypt(itr, encrypted, buffer, len)) goto out; break; } } if (itr == NULL) { /* Unknown peer */ + struct sockaddr_storage itraddressstorage; + uint8_t itraddress[4 * sizeof(in_addr_t)]; + int addresslength; + while (Client_iterate(&itr) != NULL) { - if (itr->remote_tcp.sin_addr.s_addr == from.sin_addr.s_addr) { + itraddressstorage = itr->remote_tcp; + if(itraddressstorage.ss_family == AF_INET) { + memcpy(itraddress, &((struct sockaddr_in*)&from)->sin_addr, sizeof(in_addr_t)); + addresslength = sizeof(in_addr_t); + } else { + memcpy(itraddress, &((struct sockaddr_in6*)&from)->sin6_addr, 4 * sizeof(in_addr_t)); + addresslength = 4 * sizeof(in_addr_t); + } + + if (memcmp(itraddress, fromaddress, addresslength) == 0) { if (checkDecrypt(itr, encrypted, buffer, len)) { - itr->key = key; - Log_info_client(itr, "New UDP connection port %d", ntohs(from.sin_port)); - memcpy(&itr->remote_udp, &from, sizeof(struct sockaddr_in)); + memcpy(itr->key, key, KEY_LENGTH); + Log_info_client(itr, "New UDP connection from %s on port %d", itr->addressString, fromport); + memcpy(&itr->remote_udp, &from, sizeof(struct sockaddr_storage)); break; } } @@ -836,7 +878,7 @@ int Client_read_udp() Client_send_udp(itr, buffer, len); break; default: - Log_debug("Unknown UDP message type from %s port %d", inet_ntoa(from.sin_addr), ntohs(from.sin_port)); + Log_debug("Unknown UDP message type from %s port %d", itr->addressString, fromport); break; } @@ -980,12 +1022,18 @@ out: return 0; } - 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 (client->remote_udp.sin_port != 0 && CryptState_isValid(&client->cryptState) && + if (clientport != 0 && CryptState_isValid(&client->cryptState) && client->bUDP) { #if defined(__LP64__) buf = mbuf = malloc(len + 4 + 16);