[ AC_DEFINE(ENABLE_JUMBOGRAMS, 1, [Support for jumbograms (packets up to 9000 bytes)]) ]
)
-dnl Check if checkpoint tracing has to be enabled
-AC_ARG_ENABLE(tracing,
- AS_HELP_STRING([--enable-tracing], [enable checkpoint tracing (debugging only)]),
- [ AC_DEFINE(ENABLE_TRACING, 1, [Checkpoint tracing]) ]
-)
-
AC_SUBST(INCLUDES)
AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile lib/Makefile po/Makefile.in m4/Makefile])
#include "../src/logger.h"
#include "utils.h"
-#ifdef ENABLE_TRACING
-volatile int (cp_line[]) = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-volatile char (*cp_file[]) = {"?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?", "?"};
-volatile int cp_index = 0;
-#endif
-
const char hexadecimals[] = "0123456789ABCDEF";
int charhex2bin(char c) {
}
}
-#ifdef ENABLE_TRACING
-void cp_trace() {
- logger(LOG_DEBUG, "Checkpoint trace: %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d <- %s:%d...",
- cp_file[(cp_index + 15) % 16], cp_line[(cp_index + 15) % 16],
- cp_file[(cp_index + 14) % 16], cp_line[(cp_index + 14) % 16],
- cp_file[(cp_index + 13) % 16], cp_line[(cp_index + 13) % 16],
- cp_file[(cp_index + 12) % 16], cp_line[(cp_index + 12) % 16],
- cp_file[(cp_index + 11) % 16], cp_line[(cp_index + 11) % 16],
- cp_file[(cp_index + 10) % 16], cp_line[(cp_index + 10) % 16],
- cp_file[(cp_index + 9) % 16], cp_line[(cp_index + 9) % 16],
- cp_file[(cp_index + 8) % 16], cp_line[(cp_index + 8) % 16],
- cp_file[(cp_index + 7) % 16], cp_line[(cp_index + 7) % 16],
- cp_file[(cp_index + 6) % 16], cp_line[(cp_index + 6) % 16],
- cp_file[(cp_index + 5) % 16], cp_line[(cp_index + 5) % 16],
- cp_file[(cp_index + 4) % 16], cp_line[(cp_index + 4) % 16],
- cp_file[(cp_index + 3) % 16], cp_line[(cp_index + 3) % 16],
- cp_file[(cp_index + 2) % 16], cp_line[(cp_index + 2) % 16],
- cp_file[(cp_index + 1) % 16], cp_line[(cp_index + 1) % 16],
- cp_file[cp_index], cp_line[cp_index]
- );
-}
-#endif
-
#if defined(HAVE_MINGW) || defined(HAVE_CYGWIN)
#ifdef HAVE_CYGWIN
#include <w32api/windows.h>
#ifndef __TINC_UTILS_H__
#define __TINC_UTILS_H__
-#ifdef ENABLE_TRACING
-extern volatile int cp_line[];
-extern volatile char *cp_file[];
-extern volatile int cp_index;
-extern void cp_trace(void);
-
-#define cp() { cp_line[cp_index] = __LINE__; cp_file[cp_index] = __FILE__; cp_index++; cp_index %= 16; }
-#define ecp() { fprintf(stderr, "Explicit checkpoint in %s line %d\n", __FILE__, __LINE__); }
-#else
-#define cp()
-#define ecp()
-#define cp_trace()
-#endif
-
extern void hex2bin(char *src, char *dst, int length);
extern void bin2hex(char *src, char *dst, int length);
bool setup_device(void) {
char *type;
- cp();
-
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = xstrdup(DEFAULT_DEVICE);
}
void close_device(void) {
- cp();
-
switch(device_type) {
#ifdef HAVE_TUNEMU
case DEVICE_TYPE_TUNEMU:
bool read_packet(vpn_packet_t *packet) {
int lenin;
- cp();
-
switch(device_type) {
case DEVICE_TYPE_TUN:
#ifdef HAVE_TUNEMU
}
bool write_packet(vpn_packet_t *packet) {
- cp();
-
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
}
void dump_device_stats(void) {
- cp();
-
logger(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
logger(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
logger(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
}
void init_configuration(avl_tree_t ** config_tree) {
- cp();
-
*config_tree = avl_alloc_tree((avl_compare_t) config_compare, (avl_action_t) free_config);
}
void exit_configuration(avl_tree_t ** config_tree) {
- cp();
-
avl_delete_tree(*config_tree);
*config_tree = NULL;
}
config_t *new_config(void) {
- cp();
-
return xmalloc_and_zero(sizeof(config_t));
}
void free_config(config_t *cfg) {
- cp();
-
if(cfg->variable)
free(cfg->variable);
}
void config_add(avl_tree_t *config_tree, config_t *cfg) {
- cp();
-
avl_insert(config_tree, cfg);
}
config_t *lookup_config(avl_tree_t *config_tree, char *variable) {
config_t cfg, *found;
- cp();
-
cfg.variable = variable;
cfg.file = "";
cfg.line = 0;
avl_node_t *node;
config_t *found;
- cp();
-
node = avl_search_node(config_tree, cfg);
if(node) {
}
bool get_config_bool(const config_t *cfg, bool *result) {
- cp();
-
if(!cfg)
return false;
}
bool get_config_int(const config_t *cfg, int *result) {
- cp();
-
if(!cfg)
return false;
}
bool get_config_string(const config_t *cfg, char **result) {
- cp();
-
if(!cfg)
return false;
bool get_config_address(const config_t *cfg, struct addrinfo **result) {
struct addrinfo *ai;
- cp();
-
if(!cfg)
return false;
bool get_config_subnet(const config_t *cfg, subnet_t ** result) {
subnet_t subnet = {0};
- cp();
-
if(!cfg)
return false;
config_t *cfg;
size_t bufsize;
- cp();
-
fp = fopen(fname, "r");
if(!fp) {
char *fname;
int x;
- cp();
-
xasprintf(&fname, "%s/tinc.conf", confbase);
x = read_config_file(config_tree, fname);
}
void init_connections(void) {
- cp();
-
connection_tree = avl_alloc_tree((avl_compare_t) connection_compare, (avl_action_t) free_connection);
broadcast = new_connection();
broadcast->name = xstrdup(_("everyone"));
}
void exit_connections(void) {
- cp();
-
avl_delete_tree(connection_tree);
free_connection(broadcast);
}
connection_t *new_connection(void) {
connection_t *c;
- cp();
-
c = xmalloc_and_zero(sizeof(connection_t));
if(!c)
}
void free_connection(connection_t *c) {
- cp();
-
if(c->name)
free(c->name);
}
void connection_add(connection_t *c) {
- cp();
-
avl_insert(connection_tree, c);
}
void connection_del(connection_t *c) {
- cp();
-
avl_delete(connection_tree, c);
}
avl_node_t *node;
connection_t *c;
- cp();
-
logger(LOG_DEBUG, _("Connections:"));
for(node = connection_tree->head; node; node = node->next) {
char *fname;
int x;
- cp();
-
xasprintf(&fname, "%s/hosts/%s", confbase, c->name);
x = read_config_file(c->config_tree, fname);
free(fname);
bool found = false;
- cp();
-
get_config_string(lookup_config(config_tree, "Device"), &device);
get_config_string(lookup_config(config_tree, "Interface"), &iface);
}
void close_device(void) {
- cp();
-
close(sp[0]);
close(sp[1]);
CloseHandle(device_handle);
bool read_packet(vpn_packet_t *packet) {
int lenin;
- cp();
-
if((lenin = read(sp[0], packet->data, MTU)) <= 0) {
logger(LOG_ERR, _("Error while reading from %s %s: %s"), device_info,
device, strerror(errno));
bool write_packet(vpn_packet_t *packet) {
long lenout;
- cp();
-
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
}
void dump_device_stats(void) {
- cp();
-
logger(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
logger(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
logger(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
}
void init_edges(void) {
- cp();
-
edge_weight_tree = avl_alloc_tree((avl_compare_t) edge_weight_compare, NULL);
}
avl_tree_t *new_edge_tree(void) {
- cp();
-
return avl_alloc_tree((avl_compare_t) edge_compare, (avl_action_t) free_edge);
}
void free_edge_tree(avl_tree_t *edge_tree) {
- cp();
-
avl_delete_tree(edge_tree);
}
void exit_edges(void) {
- cp();
-
avl_delete_tree(edge_weight_tree);
}
/* Creation and deletion of connection elements */
edge_t *new_edge(void) {
- cp();
-
return xmalloc_and_zero(sizeof(edge_t));
}
void free_edge(edge_t *e) {
- cp();
-
sockaddrfree(&e->address);
free(e);
}
void edge_add(edge_t *e) {
- cp();
-
avl_insert(edge_weight_tree, e);
avl_insert(e->from->edge_tree, e);
}
void edge_del(edge_t *e) {
- cp();
-
if(e->reverse)
e->reverse->reverse = NULL;
edge_t *lookup_edge(node_t *from, node_t *to) {
edge_t v;
- cp();
-
v.from = from;
v.to = to;
edge_t *e;
char *address;
- cp();
-
logger(LOG_DEBUG, _("Edges:"));
for(node = node_tree->head; node; node = node->next) {
}
void init_events(void) {
- cp();
-
event_tree = avl_alloc_tree((avl_compare_t) event_compare, (avl_action_t) free_event);
}
void exit_events(void) {
- cp();
-
avl_delete_tree(event_tree);
}
* the expiration time of the last event and the current time.
*/
- cp();
-
if(!event_tree->tail)
return;
}
event_t *new_event(void) {
- cp();
-
return xmalloc_and_zero(sizeof(event_t));
}
void free_event(event_t *event) {
- cp();
-
free(event);
}
void event_add(event_t *event) {
- cp();
-
event->id = ++id;
avl_insert(event_tree, event);
}
void event_del(event_t *event) {
- cp();
-
avl_delete(event_tree, event);
}
event_t *get_expired_event(void) {
event_t *event;
- cp();
-
if(event_tree->head) {
event = event_tree->head->data;
int safe_edges = 0;
bool skipped;
- cp();
-
/* Clear MST status on connections */
for(node = connection_tree->head; node; node = node->next) {
char *envp[7];
int i;
- cp();
-
todo_list = list_alloc(NULL);
/* Clear visited status on nodes */
bool setup_device(void) {
struct ifreq ifr;
- cp();
-
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = xstrdup(DEFAULT_DEVICE);
}
void close_device(void) {
- cp();
-
close(device_fd);
free(device);
bool read_packet(vpn_packet_t *packet) {
int lenin;
- cp();
-
switch(device_type) {
case DEVICE_TYPE_TUN:
lenin = read(device_fd, packet->data + 10, MTU - 10);
}
bool write_packet(vpn_packet_t *packet) {
- cp();
-
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
}
void dump_device_stats(void) {
- cp();
-
logger(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
logger(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
logger(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
int outlen;
int result;
- cp();
-
if(!c) {
logger(LOG_ERR, _("send_meta() called with NULL pointer!"));
abort();
avl_node_t *node;
connection_t *c;
- cp();
-
for(node = connection_tree->head; node; node = node->next) {
c = node->data;
bool decrypted = false;
char inbuf[MAXBUFSIZE];
- cp();
-
/* Strategy:
- Read as much as possible from the TCP socket in one go.
- Decrypt it.
.ai_flags = 0,
};
- cp();
-
get_config_string(lookup_config(config_tree, "Device"), &device);
get_config_string(lookup_config(config_tree, "Interface"), &iface);
}
void close_device(void) {
- cp();
-
CloseHandle(device_handle);
free(device);
long lenout;
OVERLAPPED overlapped = {0};
- cp();
-
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
}
void dump_device_stats(void) {
- cp();
-
logger(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
logger(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
logger(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
edge_t *e;
subnet_t *s;
- cp();
-
ifdebug(PROTOCOL) logger(LOG_DEBUG, _("Purging unreachable nodes"));
/* Remove all edges and subnets owned by unreachable nodes. */
connection_t *c;
int i, max = 0;
- cp();
-
FD_ZERO(readset);
FD_ZERO(writeset);
- Deactivate the host
*/
void terminate_connection(connection_t *c, bool report) {
- cp();
-
if(c->status.remove)
return;
avl_node_t *node, *next;
connection_t *c;
- cp();
-
for(node = connection_tree->head; node; node = next) {
next = node->next;
c = node->data;
socklen_t len = sizeof(result);
vpn_packet_t packet;
- cp();
-
/* check input from kernel */
if(device_fd >= 0 && FD_ISSET(device_fd, readset)) {
if(read_packet(&packet)) {
time_t last_ping_check, last_config_check, last_graph_dump;
event_t *event;
- cp();
-
last_ping_check = now;
last_config_check = now;
last_graph_dump = now;
if(errno != EINTR && errno != EAGAIN) {
logger(LOG_ERR, _("Error while waiting for input: %s"),
strerror(errno));
- cp_trace();
dump_connections();
return 1;
}
vpn_packet_t packet;
int len, i;
- cp();
-
n->mtuprobes++;
n->mtuevent = NULL;
/* VPN packet I/O */
static void receive_packet(node_t *n, vpn_packet_t *packet) {
- cp();
-
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Received packet of %d bytes from %s (%s)"),
packet->len, n->name, n->hostname);
unsigned char hmac[EVP_MAX_MD_SIZE];
int i;
- cp();
-
if(!n->inkey) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Got packet from %s (%s) but he hasn't got our key yet"),
n->name, n->hostname);
void receive_tcppacket(connection_t *c, char *buffer, int len) {
vpn_packet_t outpkt;
- cp();
-
outpkt.len = len;
if(c->options & OPTION_TCPONLY)
outpkt.priority = 0;
int origpriority;
int sock;
- cp();
-
if(!n->status.reachable) {
ifdebug(TRAFFIC) logger(LOG_INFO, _("Trying to send UDP packet to unreachable node %s (%s)"), n->name, n->hostname);
return;
void send_packet(const node_t *n, vpn_packet_t *packet) {
node_t *via;
- cp();
-
if(n == myself) {
if(overwrite_mac)
memcpy(packet->data, mymac.x, ETH_ALEN);
avl_node_t *node;
connection_t *c;
- cp();
-
ifdebug(TRAFFIC) logger(LOG_INFO, _("Broadcasting packet of %d bytes from %s (%s)"),
packet->len, from->name, from->hostname);
socklen_t fromlen = sizeof(from);
node_t *n;
- cp();
-
pkt.len = recvfrom(sock, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen);
if(pkt.len < 0) {
char *fname;
char *key;
- cp();
-
if(!c->rsa_key) {
c->rsa_key = RSA_new();
// RSA_blinding_on(c->rsa_key, NULL);
char *fname, *key, *pubkey;
struct stat s;
- cp();
-
if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) {
if(!get_config_string(lookup_config(myself->connection->config_tree, "PublicKey"), &pubkey)) {
logger(LOG_ERR, _("PrivateKey used but no PublicKey found!"));
bool choice;
int i, err;
- cp();
-
myself = new_node();
myself->connection = new_connection();
init_configuration(&myself->connection->config_tree);
initialize network
*/
bool setup_network(void) {
- cp();
-
now = time(NULL);
init_events();
char *envp[5];
int i;
- cp();
-
for(node = connection_tree->head; node; node = next) {
next = node->next;
c = node->data;
int option;
char *iface;
- cp();
-
nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
if(nfd < 0) {
char *addrstr;
int option;
- cp();
-
nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP);
if(nfd < 0) {
void retry_outgoing(outgoing_t *outgoing) {
event_t *event;
- cp();
-
outgoing->timeout += 5;
if(outgoing->timeout > maxtimeout)
}
void finish_connecting(connection_t *c) {
- cp();
-
ifdebug(CONNECTIONS) logger(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname);
configure_tcp(c);
char *address, *port;
int result;
- cp();
-
begin:
if(!c->outgoing->ai) {
if(!c->outgoing->cfg) {
connection_t *c;
node_t *n;
- cp();
-
n = lookup_node(outgoing->name);
if(n)
int fd;
socklen_t len = sizeof(sa);
- cp();
-
fd = accept(sock, &sa.sa, &len);
if(fd < 0) {
connection_t *c;
avl_node_t *node;
- cp();
-
if(outgoing_list) {
for(node = connection_tree->head; node; node = node->next) {
c = node->data;
struct addrinfo *ai, hint = {0};
int err;
- cp();
-
hint.ai_family = addressfamily;
hint.ai_socktype = socktype;
sockaddr_t result;
int err;
- cp();
-
hint.ai_family = AF_UNSPEC;
hint.ai_flags = AI_NUMERICHOST;
hint.ai_socktype = SOCK_STREAM;
char *scopeid;
int err;
- cp();
-
if(sa->sa.sa_family == AF_UNKNOWN) {
*addrstr = xstrdup(sa->unknown.address);
*portstr = xstrdup(sa->unknown.port);
if(err) {
logger(LOG_ERR, _("Error while translating addresses: %s"),
gai_strerror(err));
- cp_trace();
raise(SIGFPE);
exit(0);
}
char port[NI_MAXSERV] = "unknown";
int err;
- cp();
-
if(sa->sa.sa_family == AF_UNKNOWN) {
xasprintf(&str, _("%s port %s"), sa->unknown.address, sa->unknown.port);
return str;
int sockaddrcmp_noport(const sockaddr_t *a, const sockaddr_t *b) {
int result;
- cp();
-
result = a->sa.sa_family - b->sa.sa_family;
if(result)
default:
logger(LOG_ERR, _("sockaddrcmp() was called with unknown address family %d, exitting!"),
a->sa.sa_family);
- cp_trace();
raise(SIGFPE);
exit(0);
}
int sockaddrcmp(const sockaddr_t *a, const sockaddr_t *b) {
int result;
- cp();
-
result = a->sa.sa_family - b->sa.sa_family;
if(result)
default:
logger(LOG_ERR, _("sockaddrcmp() was called with unknown address family %d, exitting!"),
a->sa.sa_family);
- cp_trace();
raise(SIGFPE);
exit(0);
}
}
void sockaddrcpy(sockaddr_t *a, const sockaddr_t *b) {
- cp();
-
if(b->sa.sa_family != AF_UNKNOWN) {
*a = *b;
} else {
}
void sockaddrfree(sockaddr_t *a) {
- cp();
-
if(a->sa.sa_family == AF_UNKNOWN) {
free(a->unknown.address);
free(a->unknown.port);
}
void sockaddrunmap(sockaddr_t *sa) {
- cp();
-
if(sa->sa.sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sa->in6.sin6_addr)) {
sa->in.sin_addr.s_addr = ((uint32_t *) & sa->in6.sin6_addr)[3];
sa->in.sin_family = AF_INET;
const char *a = va;
const char *b = vb;
- cp();
-
for(m = masklen, i = 0; m >= 8; m -= 8, i++) {
result = a[i] - b[i];
if(result)
int i;
char *a = va;
- cp();
-
i = masklen / 8;
masklen %= 8;
char *a = va;
const char *b = vb;
- cp();
-
for(m = masklen, i = 0; m >= 8; m -= 8, i++)
a[i] = b[i];
int i;
const char *a = va;
- cp();
-
i = masklen / 8;
masklen %= 8;
}
void init_nodes(void) {
- cp();
-
node_tree = avl_alloc_tree((avl_compare_t) node_compare, (avl_action_t) free_node);
node_udp_tree = avl_alloc_tree((avl_compare_t) node_udp_compare, NULL);
}
void exit_nodes(void) {
- cp();
-
avl_delete_tree(node_udp_tree);
avl_delete_tree(node_tree);
}
node_t *new_node(void) {
node_t *n = xmalloc_and_zero(sizeof(*n));
- cp();
-
n->subnet_tree = new_subnet_tree();
n->edge_tree = new_edge_tree();
EVP_CIPHER_CTX_init(&n->inctx);
}
void free_node(node_t *n) {
- cp();
-
if(n->inkey)
free(n->inkey);
}
void node_add(node_t *n) {
- cp();
-
avl_insert(node_tree, n);
}
edge_t *e;
subnet_t *s;
- cp();
-
for(node = n->subnet_tree->head; node; node = next) {
next = node->next;
s = node->data;
node_t *lookup_node(char *name) {
node_t n = {0};
- cp();
-
n.name = name;
return avl_search(node_tree, &n);
node_t *lookup_node_udp(const sockaddr_t *sa) {
node_t n = {0};
- cp();
-
n.address = *sa;
n.name = NULL;
avl_node_t *node;
node_t *n;
- cp();
-
logger(LOG_DEBUG, _("Nodes:"));
for(node = node_tree->head; node; node = node->next) {
static void memory_full(int size) {
logger(LOG_ERR, _("Memory exhausted (couldn't allocate %d bytes), exitting."), size);
- cp_trace();
exit(1);
}
static bool write_pidfile(void) {
pid_t pid;
- cp();
-
pid = check_pid(pidfilename);
if(pid) {
#ifndef HAVE_MINGW
pid_t pid;
- cp();
-
pid = read_pid(pidfilename);
if(!pid) {
Detach from current terminal, write pidfile, kill parent
*/
bool detach(void) {
- cp();
-
setup_signals();
/* First check if we can open a fresh new pidfile */
char *scriptname, *p;
int i;
- cp();
-
#ifndef HAVE_MINGW
len = xasprintf(&scriptname, "\"%s/%s\"", confbase, name);
#else
static RETSIGTYPE fatal_signal_square(int a) {
logger(LOG_ERR, _("Got another fatal signal %d (%s): not restarting."), a,
strsignal(a));
- cp_trace();
exit(1);
}
static RETSIGTYPE fatal_signal_handler(int a) {
struct sigaction act;
logger(LOG_ERR, _("Got fatal signal %d (%s)"), a, strsignal(a));
- cp_trace();
if(do_detach) {
logger(LOG_NOTICE, _("Trying to re-execute in 5 seconds..."));
static RETSIGTYPE unexpected_signal_handler(int a) {
logger(LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a));
- cp_trace();
}
static RETSIGTYPE ignore_signal_handler(int a) {
char buffer[MAXBUFSIZE];
int len, request;
- cp();
-
/* Use vsnprintf instead of vxasprintf: faster, no memory
fragmentation, cleanup is automatic, and there is a limit on the
input buffer anyway */
void forward_request(connection_t *from) {
int request;
- cp();
-
ifdebug(PROTOCOL) {
sscanf(from->buffer, "%d", &request);
ifdebug(META)
bool receive_request(connection_t *c) {
int request;
- cp();
-
if(sscanf(c->buffer, "%d", &request) == 1) {
if((request < 0) || (request >= LAST) || !request_handlers[request]) {
ifdebug(META)
}
static void free_past_request(past_request_t *r) {
- cp();
-
if(r->request)
free(r->request);
}
void init_requests(void) {
- cp();
-
past_request_tree = avl_alloc_tree((avl_compare_t) past_request_compare, (avl_action_t) free_past_request);
}
void exit_requests(void) {
- cp();
-
avl_delete_tree(past_request_tree);
}
bool seen_request(char *request) {
past_request_t *new, p = {0};
- cp();
-
p.request = request;
if(avl_search(past_request_tree, &p)) {
past_request_t *p;
int left = 0, deleted = 0;
- cp();
-
for(node = past_request_tree->head; node; node = next) {
next = node->next;
p = node->data;
#include "xalloc.h"
bool send_id(connection_t *c) {
- cp();
-
return send_request(c, "%d %s %d", ID, myself->connection->name,
myself->connection->protocol_version);
}
bool id_h(connection_t *c) {
char name[MAX_STRING_SIZE];
- cp();
-
if(sscanf(c->buffer, "%*d " MAX_STRING " %d", name, &c->protocol_version) != 2) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "ID", c->name,
c->hostname);
int len;
bool x;
- cp();
-
len = RSA_size(c->rsa_key);
/* Allocate buffers for the meta key */
if(!c->outctx)
c->outctx = xmalloc_and_zero(sizeof(*c->outctx));
- cp();
+
/* Copy random data to the buffer */
RAND_pseudo_bytes((unsigned char *)c->outkey, len);
int cipher, digest, maclength, compression;
int len;
- cp();
-
if(sscanf(c->buffer, "%*d %d %d %d %d " MAX_STRING, &cipher, &digest, &maclength, &compression, buffer) != 5) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "METAKEY", c->name,
c->hostname);
char *buffer;
int len;
- cp();
-
/* CHECKME: what is most reasonable value for len? */
len = RSA_size(c->rsa_key);
char buffer[MAX_STRING_SIZE];
int len;
- cp();
-
if(sscanf(c->buffer, "%*d " MAX_STRING, buffer) != 1) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "CHALLENGE", c->name,
c->hostname);
char hash[EVP_MAX_MD_SIZE * 2 + 1];
EVP_MD_CTX ctx;
- cp();
-
/* Calculate the hash from the challenge we received */
if(!EVP_DigestInit(&ctx, c->indigest)
char myhash[EVP_MAX_MD_SIZE];
EVP_MD_CTX ctx;
- cp();
-
if(sscanf(c->buffer, "%*d " MAX_STRING, hishash) != 1) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "CHAL_REPLY", c->name,
c->hostname);
struct timeval now;
bool choice;
- cp();
-
/* Estimate weight */
gettimeofday(&now, NULL);
long int options;
node_t *n;
- cp();
-
if(sscanf(c->buffer, "%*d " MAX_STRING " %d %lx", hisport, &weight, &options) != 3) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "ACK", c->name,
c->hostname);
/* Create an edge_t for this connection */
c->edge = new_edge();
- cp();
c->edge->from = myself;
c->edge->to = n;
sockaddr2str(&c->address, &hisaddress, &dummy);
bool x;
char *address, *port;
- cp();
-
sockaddr2str(&e->address, &address, &port);
x = send_request(c, "%d %x %s %s %s %s %lx %d", ADD_EDGE, rand(),
long int options;
int weight;
- cp();
-
if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d",
from_name, to_name, to_address, to_port, &options, &weight) != 6) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_EDGE", c->name,
}
bool send_del_edge(connection_t *c, const edge_t *e) {
- cp();
-
return send_request(c, "%d %x %s %s", DEL_EDGE, rand(),
e->from->name, e->to->name);
}
char to_name[MAX_STRING_SIZE];
node_t *from, *to;
- cp();
-
if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, from_name, to_name) != 2) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_EDGE", c->name,
c->hostname);
bool mykeyused = false;
bool send_key_changed() {
- cp();
-
/* Only send this message if some other daemon requested our key previously.
This reduces unnecessary key_changed broadcasts.
*/
char name[MAX_STRING_SIZE];
node_t *n;
- cp();
-
if(sscanf(c->buffer, "%*d %*x " MAX_STRING, name) != 1) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "KEY_CHANGED",
c->name, c->hostname);
}
bool send_req_key(node_t *to) {
- cp();
-
return send_request(to->nexthop->connection, "%d %s %s", REQ_KEY, myself->name, to->name);
}
char to_name[MAX_STRING_SIZE];
node_t *from, *to;
- cp();
-
if(sscanf(c->buffer, "%*d " MAX_STRING " " MAX_STRING, from_name, to_name) != 2) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "REQ_KEY", c->name,
c->hostname);
bool send_ans_key(node_t *to) {
char *key;
- cp();
-
// Set key parameters
to->incipher = myself->incipher;
to->inkeylength = myself->inkeylength;
int cipher, digest, maclength, compression;
node_t *from, *to;
- cp();
-
if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %d %d %d %d",
from_name, to_name, key, &cipher, &digest, &maclength,
&compression) != 7) {
/* Status and error notification routines */
bool send_status(connection_t *c, int statusno, const char *statusstring) {
- cp();
-
if(!statusstring)
statusstring = "Status";
int statusno;
char statusstring[MAX_STRING_SIZE];
- cp();
-
if(sscanf(c->buffer, "%*d %d " MAX_STRING, &statusno, statusstring) != 2) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "STATUS",
c->name, c->hostname);
}
bool send_error(connection_t *c, int err, const char *errstring) {
- cp();
-
if(!errstring)
errstring = "Error";
int err;
char errorstring[MAX_STRING_SIZE];
- cp();
-
if(sscanf(c->buffer, "%*d %d " MAX_STRING, &err, errorstring) != 2) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "ERROR",
c->name, c->hostname);
}
bool send_termreq(connection_t *c) {
- cp();
-
return send_request(c, "%d", TERMREQ);
}
bool termreq_h(connection_t *c) {
- cp();
-
terminate_connection(c, c->status.active);
return true;
}
bool send_ping(connection_t *c) {
- cp();
-
c->status.pinged = true;
c->last_ping_time = now;
}
bool ping_h(connection_t *c) {
- cp();
-
return send_pong(c);
}
bool send_pong(connection_t *c) {
- cp();
-
return send_request(c, "%d", PONG);
}
bool pong_h(connection_t *c) {
- cp();
-
c->status.pinged = false;
/* Succesful connection, reset timeout if this is an outgoing connection. */
/* Sending and receiving packets via TCP */
bool send_tcppacket(connection_t *c, vpn_packet_t *packet) {
- cp();
-
/* If there already is a lot of data in the outbuf buffer, discard this packet.
We use a very simple Random Early Drop algorithm. */
bool tcppacket_h(connection_t *c) {
short int len;
- cp();
-
if(sscanf(c->buffer, "%*d %hd", &len) != 1) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "PACKET", c->name,
c->hostname);
bool send_add_subnet(connection_t *c, const subnet_t *subnet) {
char netstr[MAXNETSTR];
- cp();
-
if(!net2str(netstr, sizeof netstr, subnet))
return false;
node_t *owner;
subnet_t s = {0}, *new;
- cp();
-
if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_SUBNET", c->name,
c->hostname);
bool send_del_subnet(connection_t *c, const subnet_t *s) {
char netstr[MAXNETSTR];
- cp();
-
if(!net2str(netstr, sizeof netstr, s))
return false;
node_t *owner;
subnet_t s = {0}, *find;
- cp();
-
if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) {
logger(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_SUBNET", c->name,
c->hostname);
struct ifreq ifr;
struct sockaddr_ll sa;
- cp();
-
if(!get_config_string(lookup_config(config_tree, "Interface"), &iface))
iface = xstrdup("eth0");
}
void close_device(void) {
- cp();
-
close(device_fd);
free(device);
bool read_packet(vpn_packet_t *packet) {
int lenin;
- cp();
-
if((lenin = read(device_fd, packet->data, MTU)) <= 0) {
logger(LOG_ERR, _("Error while reading from %s %s: %s"), device_info,
device, strerror(errno));
}
bool write_packet(vpn_packet_t *packet) {
- cp();
-
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
}
void dump_device_stats(void) {
- cp();
-
logger(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
logger(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
logger(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
avl_node_t *node;
connection_t *c;
- cp();
-
subnet = lookup_subnet_mac(address);
/* If we don't know this MAC address yet, store it */
connection_t *c;
avl_node_t *node, *next, *node2;
- cp();
-
for(node = myself->subnet_tree->head; node; node = next) {
next = node->next;
s = node->data;
if(ratelimit(3))
return;
- cp();
-
/* Swap Ethernet source and destination addresses */
swap_mac_addresses(packet);
uint8_t *offset;
uint16_t ip_off, origf;
- cp();
-
memcpy(&ip, packet->data + ether_size, ip_size);
fragment.priority = packet->priority;
node_t *via;
ipv4_t dest;
- cp();
-
memcpy(&dest, &packet->data[30], sizeof dest);
subnet = lookup_subnet_ipv4(&dest);
}
static void route_ipv4(node_t *source, vpn_packet_t *packet) {
- cp();
-
if(!checklength(source, packet, ether_size + ip_size))
return;
if(ratelimit(3))
return;
- cp();
-
/* Swap Ethernet source and destination addresses */
swap_mac_addresses(packet);
node_t *via;
ipv6_t dest;
- cp();
-
memcpy(&dest, &packet->data[38], sizeof dest);
subnet = lookup_subnet_ipv6(&dest);
uint32_t next;
} pseudo;
- cp();
-
if(!checklength(source, packet, ether_size + ip6_size + ns_size))
return;
}
static void route_ipv6(node_t *source, vpn_packet_t *packet) {
- cp();
-
if(!checklength(source, packet, ether_size + ip6_size))
return;
subnet_t *subnet;
struct in_addr addr;
- cp();
-
if(!checklength(source, packet, ether_size + arp_size))
return;
subnet_t *subnet;
mac_t dest;
- cp();
-
-
/* Learn source address */
if(source == myself) {
send_packet(subnet->owner, packet);
}
-
void route(node_t *source, vpn_packet_t *packet) {
- cp();
-
if(!checklength(source, packet, ether_size))
return;
int ppa;
char *ptr;
- cp();
-
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
device = xstrdup(DEFAULT_DEVICE);
}
void close_device(void) {
- cp();
-
close(device_fd);
free(device);
bool read_packet(vpn_packet_t *packet) {
int lenin;
- cp();
-
if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) {
logger(LOG_ERR, _("Error while reading from %s %s: %s"), device_info,
device, strerror(errno));
}
bool write_packet(vpn_packet_t *packet) {
- cp();
-
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Writing packet of %d bytes to %s"),
packet->len, device_info);
}
void dump_device_stats(void) {
- cp();
-
logger(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
logger(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
logger(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);
default:
logger(LOG_ERR, _("subnet_compare() was called with unknown subnet type %d, exitting!"),
a->type);
- cp_trace();
exit(0);
}
/* Initialising trees */
void init_subnets(void) {
- cp();
-
subnet_tree = avl_alloc_tree((avl_compare_t) subnet_compare, (avl_action_t) free_subnet);
subnet_cache_flush();
}
void exit_subnets(void) {
- cp();
-
avl_delete_tree(subnet_tree);
}
avl_tree_t *new_subnet_tree(void) {
- cp();
-
return avl_alloc_tree((avl_compare_t) subnet_compare, NULL);
}
void free_subnet_tree(avl_tree_t *subnet_tree) {
- cp();
-
avl_delete_tree(subnet_tree);
}
/* Allocating and freeing space for subnets */
subnet_t *new_subnet(void) {
- cp();
-
return xmalloc_and_zero(sizeof(subnet_t));
}
void free_subnet(subnet_t *subnet) {
- cp();
-
free(subnet);
}
/* Adding and removing subnets */
void subnet_add(node_t *n, subnet_t *subnet) {
- cp();
-
subnet->owner = n;
avl_insert(subnet_tree, subnet);
}
void subnet_del(node_t *n, subnet_t *subnet) {
- cp();
-
avl_delete(n->subnet_tree, subnet);
avl_delete(subnet_tree, subnet);
uint16_t x[8];
int weight = 10;
- cp();
-
if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d#%d",
&x[0], &x[1], &x[2], &x[3], &l, &weight) >= 5) {
if(l < 0 || l > 32)
}
bool net2str(char *netstr, int len, const subnet_t *subnet) {
- cp();
-
if(!netstr || !subnet) {
logger(LOG_ERR, _("net2str() was called with netstr=%p, subnet=%p!\n"), netstr, subnet);
return false;
logger(LOG_ERR,
_("net2str() was called with unknown subnet type %d, exiting!"),
subnet->type);
- cp_trace();
exit(0);
}
/* Subnet lookup routines */
subnet_t *lookup_subnet(const node_t *owner, const subnet_t *subnet) {
- cp();
-
return avl_search(owner->subnet_tree, subnet);
}
subnet_t *lookup_subnet_mac(const mac_t *address) {
subnet_t *p, subnet = {0};
- cp();
-
subnet.type = SUBNET_MAC;
subnet.net.mac.address = *address;
subnet.owner = NULL;
avl_node_t *n;
int i;
- cp();
-
// Check if this address is cached
for(i = 0; i < 2; i++) {
avl_node_t *n;
int i;
- cp();
-
// Check if this address is cached
for(i = 0; i < 2; i++) {
subnet_t *subnet;
avl_node_t *node;
- cp();
-
logger(LOG_DEBUG, _("Subnet list:"));
for(node = subnet_tree->head; node; node = node->next) {
} name;
struct timeval tv;
- cp();
-
if(!get_config_string(lookup_config(config_tree, "Device"), &device))
xasprintf(&device, LOCALSTATEDIR "/run/%s.umlsocket", identname);
}
void close_device(void) {
- cp();
-
if(listen_fd >= 0)
close(listen_fd);
bool read_packet(vpn_packet_t *packet) {
int lenin;
- cp();
-
switch(state) {
case 0: {
struct sockaddr sa;
}
bool write_packet(vpn_packet_t *packet) {
- cp();
-
if(state != 2) {
ifdebug(TRAFFIC) logger(LOG_DEBUG, _("Dropping packet of %d bytes to %s: not connected to UML yet"),
packet->len, device_info);
}
void dump_device_stats(void) {
- cp();
-
logger(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device);
logger(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in);
logger(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out);