wireguard-tools/contrib/nat-hole-punching/nat-punch-server.c
Greg Kroah-Hartman 01d00bc035 global: add SPDX tags to all files
It's good to have SPDX identifiers in all files as the Linux kernel
developers are working to add these identifiers to all files.

Update all files with the correct SPDX license identifier based on the license
text of the project or based on the license in the file itself.  The SPDX
identifier is a legally binding shorthand, which can be used instead of the
full boiler plate text.

Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Modified-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2017-12-09 22:29:28 +01:00

116 lines
2.4 KiB
C

/* SPDX-License-Identifier: GPL-2.0
*
* Copyright (C) 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
*
* Example only. Do not run in production.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
struct entry {
uint8_t pubkey[32];
uint32_t ip;
uint16_t port;
};
enum { MAX_ENTRIES = 65536, PORT = 49918 };
static struct entry entries[MAX_ENTRIES];
static unsigned int next_entry;
/* XX: this should use a hash table */
static struct entry *find_entry(uint8_t key[32])
{
int i;
for (i = 0; i < MAX_ENTRIES; ++i) {
if (!memcmp(entries[i].pubkey, key, 32))
return &entries[i];
}
return NULL;
}
/* XX: this is obviously vulnerable to DoS */
static struct entry *find_or_insert_entry(uint8_t key[32])
{
struct entry *entry = find_entry(key);
if (!entry) {
entry = &entries[next_entry++ % MAX_ENTRIES];
memcpy(entry->pubkey, key, 32);
}
return entry;
}
int main(int argc, char *argv[])
{
struct sockaddr_in addr = {
.sin_family = AF_INET,
.sin_addr = { .s_addr = htonl(INADDR_ANY) },
.sin_port = htons(PORT)
};
struct {
uint8_t my_pubkey[32];
uint8_t their_pubkey[32];
} __attribute__((packed)) packet;
struct {
uint32_t ip;
uint16_t port;
} __attribute__((packed)) reply;
struct entry *entry;
socklen_t len;
ssize_t retlen;
int optval;
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("socket");
return errno;
}
optval = 1;
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
perror("setsockopt");
return errno;
}
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("bind");
return errno;
}
for (;;) {
len = sizeof(addr);
if (recvfrom(sock, &packet, sizeof(packet), 0, (struct sockaddr *)&addr, &len) != sizeof(packet)) {
perror("recvfrom");
continue;
}
entry = find_or_insert_entry(packet.my_pubkey);
entry->ip = addr.sin_addr.s_addr;
entry->port = addr.sin_port;
entry = find_entry(packet.their_pubkey);
if (entry) {
reply.ip = entry->ip;
reply.port = entry->port;
if (sendto(sock, &reply, sizeof(reply), 0, (struct sockaddr *)&addr, len) < 0) {
perror("sendto");
continue;
}
} else {
if (sendto(sock, NULL, 0, 0, (struct sockaddr *)&addr, len) < 0) {
perror("sendto");
continue;
}
}
}
close(sock);
return 0;
}