From f75dcef72a81a337e847adf0bae54198894f65b9 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Mon, 9 Sep 2002 21:25:28 +0000 Subject: [PATCH] Switch to K&R style indentation. --- src/conf.c | 926 +++++++++++++++++----------------- src/conf.h | 16 +- src/connection.c | 145 +++--- src/connection.h | 110 ++--- src/cygwin/device.c | 130 +++-- src/darwin/device.c | 133 +++-- src/device.h | 4 +- src/edge.c | 160 +++--- src/edge.h | 24 +- src/event.c | 89 ++-- src/event.h | 14 +- src/freebsd/device.c | 125 +++-- src/graph.c | 429 ++++++++-------- src/linux/device.c | 257 +++++----- src/meta.c | 313 ++++++------ src/meta.h | 4 +- src/net.c | 583 +++++++++++----------- src/net.h | 83 ++-- src/net_packet.c | 588 +++++++++++----------- src/net_setup.c | 1036 +++++++++++++++++++-------------------- src/net_socket.c | 665 +++++++++++++------------ src/netbsd/device.c | 137 +++--- src/netutl.c | 363 +++++++------- src/netutl.h | 4 +- src/node.c | 201 ++++---- src/node.h | 60 +-- src/openbsd/device.c | 234 +++++---- src/process.c | 617 ++++++++++++----------- src/process.h | 4 +- src/protocol.c | 344 ++++++------- src/protocol.h | 35 +- src/protocol_auth.c | 953 +++++++++++++++++------------------ src/protocol_edge.c | 430 ++++++++-------- src/protocol_key.c | 396 ++++++++------- src/protocol_misc.c | 224 +++++---- src/protocol_node.c | 380 +++++++------- src/protocol_subnet.c | 350 ++++++------- src/raw_socket/device.c | 172 +++---- src/route.c | 814 +++++++++++++++--------------- src/route.h | 13 +- src/solaris/device.c | 232 +++++---- src/subnet.c | 595 +++++++++++----------- src/subnet.h | 55 +-- src/tincd.c | 598 +++++++++++----------- 44 files changed, 6476 insertions(+), 6569 deletions(-) diff --git a/src/conf.c b/src/conf.c index f70abdf..192d04f 100644 --- a/src/conf.c +++ b/src/conf.c @@ -19,7 +19,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: conf.c,v 1.9.4.58 2002/09/09 19:39:55 guus Exp $ + $Id: conf.c,v 1.9.4.59 2002/09/09 21:24:25 guus Exp $ */ #include "config.h" @@ -38,235 +38,246 @@ #include #include -#include /* for cp */ +#include /* for cp */ #include #include "conf.h" -#include "netutl.h" /* for str2address */ +#include "netutl.h" /* for str2address */ #include "system.h" avl_tree_t *config_tree; int debug_lvl = 0; -int pingtimeout = 0; /* seconds before timeout */ -char *confbase = NULL; /* directory in which all config files are */ -char *netname = NULL; /* name of the vpn network */ +int pingtimeout = 0; /* seconds before timeout */ +char *confbase = NULL; /* directory in which all config files are */ +char *netname = NULL; /* name of the vpn network */ -int config_compare(config_t *a, config_t *b) +int config_compare(config_t * a, config_t * b) { - int result; + int result; - result = strcasecmp(a->variable, b->variable); + result = strcasecmp(a->variable, b->variable); - if(result) - return result; + if(result) + return result; - result = a->line - b->line; + result = a->line - b->line; - if(result) - return result; - else - return strcmp(a->file, b->file); + if(result) + return result; + else + return strcmp(a->file, b->file); } -void init_configuration(avl_tree_t **config_tree) +void init_configuration(avl_tree_t ** config_tree) { - cp(); - *config_tree = avl_alloc_tree((avl_compare_t)config_compare, (avl_action_t)free_config); - cp(); + cp(); + + *config_tree = avl_alloc_tree((avl_compare_t) config_compare, (avl_action_t) free_config); } -void exit_configuration(avl_tree_t **config_tree) +void exit_configuration(avl_tree_t ** config_tree) { - cp(); - avl_delete_tree(*config_tree); - *config_tree = NULL; - cp(); + cp(); + + avl_delete_tree(*config_tree); + *config_tree = NULL; } config_t *new_config(void) { - config_t *cfg; - cp(); - cfg = (config_t *)xmalloc_and_zero(sizeof(*cfg)); + cp(); - return cfg; + return (config_t *) xmalloc_and_zero(sizeof(config_t)); } -void free_config(config_t *cfg) +void free_config(config_t * cfg) { - cp(); - if(cfg->variable) - free(cfg->variable); - if(cfg->value) - free(cfg->value); - if(cfg->file) - free(cfg->file); - free(cfg); - cp(); + cp(); + + if(cfg->variable) + free(cfg->variable); + + if(cfg->value) + free(cfg->value); + + if(cfg->file) + free(cfg->file); + + free(cfg); } -void config_add(avl_tree_t *config_tree, config_t *cfg) +void config_add(avl_tree_t * config_tree, config_t * cfg) { - cp(); - avl_insert(config_tree, cfg); - cp(); + cp(); + + avl_insert(config_tree, cfg); } -config_t *lookup_config(avl_tree_t *config_tree, char *variable) +config_t *lookup_config(avl_tree_t * config_tree, char *variable) { - config_t cfg, *found; - cp(); - cfg.variable = variable; - cfg.file = ""; - cfg.line = 0; + config_t cfg, *found; + + cp(); + + cfg.variable = variable; + cfg.file = ""; + cfg.line = 0; - found = avl_search_closest_greater(config_tree, &cfg); + found = avl_search_closest_greater(config_tree, &cfg); - if(!found) - return NULL; + if(!found) + return NULL; - if(strcasecmp(found->variable, variable)) - return NULL; + if(strcasecmp(found->variable, variable)) + return NULL; - return found; + return found; } -config_t *lookup_config_next(avl_tree_t *config_tree, config_t *cfg) +config_t *lookup_config_next(avl_tree_t * config_tree, config_t * cfg) { - avl_node_t *node; - config_t *found; - cp(); - node = avl_search_node(config_tree, cfg); - - if(node) - { - if(node->next) - { - found = (config_t *)node->next->data; - if(!strcasecmp(found->variable, cfg->variable)) - return found; - } - } - - return NULL; + avl_node_t *node; + config_t *found; + + cp(); + + node = avl_search_node(config_tree, cfg); + + if(node) { + if(node->next) { + found = (config_t *) node->next->data; + + if(!strcasecmp(found->variable, cfg->variable)) + return found; + } + } + + return NULL; } -int get_config_bool(config_t *cfg, int *result) +int get_config_bool(config_t * cfg, int *result) { - cp(); - if(!cfg) - return 0; - - if(!strcasecmp(cfg->value, "yes")) - { - *result = 1; - return 1; - } - else if(!strcasecmp(cfg->value, "no")) - { - *result = 0; - return 1; - } - - syslog(LOG_ERR, _("\"yes\" or \"no\" expected for configuration variable %s in %s line %d"), - cfg->variable, cfg->file, cfg->line); - - return 0; + cp(); + + if(!cfg) + return 0; + + if(!strcasecmp(cfg->value, "yes")) { + *result = 1; + return 1; + } else if(!strcasecmp(cfg->value, "no")) { + *result = 0; + return 1; + } + + syslog(LOG_ERR, _("\"yes\" or \"no\" expected for configuration variable %s in %s line %d"), + cfg->variable, cfg->file, cfg->line); + + return 0; } -int get_config_int(config_t *cfg, int *result) +int get_config_int(config_t * cfg, int *result) { - cp(); - if(!cfg) - return 0; + cp(); + + if(!cfg) + return 0; - if(sscanf(cfg->value, "%d", result) == 1) - return 1; + if(sscanf(cfg->value, "%d", result) == 1) + return 1; - syslog(LOG_ERR, _("Integer expected for configuration variable %s in %s line %d"), - cfg->variable, cfg->file, cfg->line); - return 0; + syslog(LOG_ERR, _("Integer expected for configuration variable %s in %s line %d"), + cfg->variable, cfg->file, cfg->line); + + return 0; } -int get_config_string(config_t *cfg, char **result) +int get_config_string(config_t * cfg, char **result) { - cp(); - if(!cfg) - return 0; + cp(); + + if(!cfg) + return 0; - *result = xstrdup(cfg->value); - return 1; + *result = xstrdup(cfg->value); + + return 1; } -int get_config_address(config_t *cfg, struct addrinfo **result) +int get_config_address(config_t * cfg, struct addrinfo **result) { - struct addrinfo *ai; - cp(); - if(!cfg) - return 0; - - ai = str2addrinfo(cfg->value, NULL, 0); - - if(ai) - { - *result = ai; - return 1; - } - - syslog(LOG_ERR, _("Hostname or IP address expected for configuration variable %s in %s line %d"), - cfg->variable, cfg->file, cfg->line); - return 0; + struct addrinfo *ai; + + cp(); + + if(!cfg) + return 0; + + ai = str2addrinfo(cfg->value, NULL, 0); + + if(ai) { + *result = ai; + return 1; + } + + syslog(LOG_ERR, _("Hostname or IP address expected for configuration variable %s in %s line %d"), + cfg->variable, cfg->file, cfg->line); + + return 0; } -int get_config_port(config_t *cfg, port_t *result) +int get_config_port(config_t * cfg, port_t * result) { - cp(); - if(!cfg) - return 0; - - if(sscanf(cfg->value, "%hu", result) == 1) - { - *result = htons(*result); - return 1; - } - - syslog(LOG_ERR, _("Port number expected for configuration variable %s in %s line %d"), - cfg->variable, cfg->file, cfg->line); - return 0; + cp(); + + if(!cfg) + return 0; + + if(sscanf(cfg->value, "%hu", result) == 1) { + *result = htons(*result); + return 1; + } + + syslog(LOG_ERR, _("Port number expected for configuration variable %s in %s line %d"), + cfg->variable, cfg->file, cfg->line); + + return 0; } -int get_config_subnet(config_t *cfg, subnet_t **result) +int get_config_subnet(config_t * cfg, subnet_t ** result) { - subnet_t *subnet; - cp(); - if(!cfg) - return 0; - - subnet = str2net(cfg->value); - - if(!subnet) - { - syslog(LOG_ERR, _("Subnet expected for configuration variable %s in %s line %d"), - cfg->variable, cfg->file, cfg->line); - return 0; - } - - /* Teach newbies what subnets are... */ - - if(((subnet->type == SUBNET_IPV4) && maskcheck(&subnet->net.ipv4.address, subnet->net.ipv4.prefixlength, sizeof(ipv4_t))) - || ((subnet->type == SUBNET_IPV6) && maskcheck(&subnet->net.ipv6.address, subnet->net.ipv6.prefixlength, sizeof(ipv6_t)))) - { - syslog(LOG_ERR, _("Network address and prefix length do not match for configuration variable %s in %s line %d"), - cfg->variable, cfg->file, cfg->line); - free(subnet); - return 0; - } - - *result = subnet; - - return 1; + subnet_t *subnet; + + cp(); + + if(!cfg) + return 0; + + subnet = str2net(cfg->value); + + if(!subnet) { + syslog(LOG_ERR, _("Subnet expected for configuration variable %s in %s line %d"), + cfg->variable, cfg->file, cfg->line); + return 0; + } + + /* Teach newbies what subnets are... */ + + if(((subnet->type == SUBNET_IPV4) + && maskcheck(&subnet->net.ipv4.address, subnet->net.ipv4.prefixlength, sizeof(ipv4_t))) + || ((subnet->type == SUBNET_IPV6) + && maskcheck(&subnet->net.ipv6.address, subnet->net.ipv6.prefixlength, sizeof(ipv6_t)))) { + syslog(LOG_ERR, _ ("Network address and prefix length do not match for configuration variable %s in %s line %d"), + cfg->variable, cfg->file, cfg->line); + free(subnet); + return 0; + } + + *result = subnet; + + return 1; } /* @@ -279,358 +290,329 @@ int get_config_subnet(config_t *cfg, subnet_t **result) given, and buf needs to be expanded, the var pointed to by buflen will be increased. */ -char *readline(FILE *fp, char **buf, size_t *buflen) +char *readline(FILE * fp, char **buf, size_t * buflen) { - char *newline = NULL; - char *p; - char *line; /* The array that contains everything that has been read - so far */ - char *idx; /* Read into this pointer, which points to an offset - within line */ - size_t size, newsize; /* The size of the current array pointed to by - line */ - size_t maxlen; /* Maximum number of characters that may be read with - fgets. This is newsize - oldsize. */ - - if(feof(fp)) - return NULL; - - if(buf && buflen) - { - size = *buflen; - line = *buf; - } - else - { - size = 100; - line = xmalloc(size); - } - - maxlen = size; - idx = line; - *idx = 0; - for(;;) - { - errno = 0; - p = fgets(idx, maxlen, fp); - if(!p) /* EOF or error */ - { - if(feof(fp)) - break; - - /* otherwise: error; let the calling function print an error - message if applicable */ - free(line); - return NULL; + char *newline = NULL; + char *p; + char *line; /* The array that contains everything that has been read so far */ + char *idx; /* Read into this pointer, which points to an offset within line */ + size_t size, newsize; /* The size of the current array pointed to by line */ + size_t maxlen; /* Maximum number of characters that may be read with fgets. This is newsize - oldsize. */ + + if(feof(fp)) + return NULL; + + if(buf && buflen) { + size = *buflen; + line = *buf; + } else { + size = 100; + line = xmalloc(size); } - newline = strchr(p, '\n'); - if(!newline) - /* We haven't yet read everything to the end of the line */ - { - newsize = size << 1; - line = xrealloc(line, newsize); - idx = &line[size - 1]; - maxlen = newsize - size + 1; - size = newsize; + maxlen = size; + idx = line; + *idx = 0; + + for(;;) { + errno = 0; + p = fgets(idx, maxlen, fp); + + if(!p) { /* EOF or error */ + if(feof(fp)) + break; + + /* otherwise: error; let the calling function print an error message if applicable */ + free(line); + return NULL; + } + + newline = strchr(p, '\n'); + + if(!newline) { /* We haven't yet read everything to the end of the line */ + newsize = size << 1; + line = xrealloc(line, newsize); + idx = &line[size - 1]; + maxlen = newsize - size + 1; + size = newsize; + } else { + *newline = '\0'; /* kill newline */ + break; /* yay */ + } } - else - { - *newline = '\0'; /* kill newline */ - break; /* yay */ + + if(buf && buflen) { + *buflen = size; + *buf = line; } - } - - if(buf && buflen) - { - *buflen = size; - *buf = line; - } - return line; + + return line; } /* Parse a configuration file and put the results in the configuration tree starting at *base. */ -int read_config_file(avl_tree_t *config_tree, const char *fname) +int read_config_file(avl_tree_t * config_tree, const char *fname) { - int err = -2; /* Parse error */ - FILE *fp; - char *buffer, *line; - char *variable, *value; - int lineno = 0, ignore = 0; - config_t *cfg; - size_t bufsize; - - cp(); - fp = fopen (fname, "r"); - - if(!fp) - { - syslog(LOG_ERR, _("Cannot open config file %s: %s"), fname, strerror(errno)); - return -3; - } - - bufsize = 100; - buffer = xmalloc(bufsize); - - for(;;) - { - line = readline(fp, &buffer, &bufsize); - - if(!line) - { - err = -1; - break; + int err = -2; /* Parse error */ + FILE *fp; + char *buffer, *line; + char *variable, *value; + int lineno = 0, ignore = 0; + config_t *cfg; + size_t bufsize; + + cp(); + + fp = fopen(fname, "r"); + + if(!fp) { + syslog(LOG_ERR, _("Cannot open config file %s: %s"), fname, + strerror(errno)); + return -3; } - if(feof(fp)) - { - err = 0; - break; - } + bufsize = 100; + buffer = xmalloc(bufsize); + + for(;;) { + line = readline(fp, &buffer, &bufsize); + + if(!line) { + err = -1; + break; + } + + if(feof(fp)) { + err = 0; + break; + } - lineno++; + lineno++; - variable = strtok(line, "\t ="); - - if(!variable) - continue; /* no tokens on this line */ + variable = strtok(line, "\t ="); - if(variable[0] == '#') - continue; /* comment: ignore */ + if(!variable) + continue; /* no tokens on this line */ - if(!strcmp(variable, "-----BEGIN")) - ignore = 1; + if(variable[0] == '#') + continue; /* comment: ignore */ - if(!ignore) - { - value = strtok(NULL, "\t\n\r ="); + if(!strcmp(variable, "-----BEGIN")) + ignore = 1; - if(!value || value[0] == '#') - { - syslog(LOG_ERR, _("No value for variable `%s' on line %d while reading config file %s"), - variable, lineno, fname); - break; - } + if(!ignore) { + value = strtok(NULL, "\t\n\r ="); - cfg = new_config(); - cfg->variable = xstrdup(variable); - cfg->value = xstrdup(value); - cfg->file = xstrdup(fname); - cfg->line = lineno; + if(!value || value[0] == '#') { + syslog(LOG_ERR, _("No value for variable `%s' on line %d while reading config file %s"), + variable, lineno, fname); + break; + } - config_add(config_tree, cfg); - } + cfg = new_config(); + cfg->variable = xstrdup(variable); + cfg->value = xstrdup(value); + cfg->file = xstrdup(fname); + cfg->line = lineno; - if(!strcmp(variable, "-----END")) - ignore = 0; - } + config_add(config_tree, cfg); + } - free(buffer); - fclose (fp); - cp(); - return err; + if(!strcmp(variable, "-----END")) + ignore = 0; + } + + free(buffer); + fclose(fp); + + return err; } int read_server_config() { - char *fname; - int x; - cp(); - asprintf(&fname, "%s/tinc.conf", confbase); - x = read_config_file(config_tree, fname); - if(x == -1) /* System error: complain */ - { - syslog(LOG_ERR, _("Failed to read `%s': %s"), fname, strerror(errno)); - } - free(fname); - cp(); - return x; + char *fname; + int x; + + cp(); + + asprintf(&fname, "%s/tinc.conf", confbase); + x = read_config_file(config_tree, fname); + + if(x == -1) { /* System error: complain */ + syslog(LOG_ERR, _("Failed to read `%s': %s"), fname, strerror(errno)); + } + + free(fname); + + return x; } -int isadir(const char* f) +int isadir(const char *f) { - struct stat s; + struct stat s; - if(stat(f, &s) < 0) - return 0; - else - return S_ISDIR(s.st_mode); + if(stat(f, &s) < 0) + return 0; + else + return S_ISDIR(s.st_mode); } int is_safe_path(const char *file) { - char *p; - const char *f; - char x; - struct stat s; - char l[MAXBUFSIZE]; + char *p; + const char *f; + char x; + struct stat s; + char l[MAXBUFSIZE]; + + if(*file != '/') { + syslog(LOG_ERR, _("`%s' is not an absolute path"), file); + return 0; + } - if(*file != '/') - { - syslog(LOG_ERR, _("`%s' is not an absolute path"), file); - return 0; - } + p = strrchr(file, '/'); - p = strrchr(file, '/'); + if(p == file) /* It's in the root */ + p++; - if(p == file) /* It's in the root */ - p++; + x = *p; + *p = '\0'; - x = *p; - *p = '\0'; + f = file; - f = file; check1: - if(lstat(f, &s) < 0) - { - syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno)); - return 0; - } - - if(s.st_uid != geteuid()) - { - syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"), - f, s.st_uid, geteuid()); - return 0; - } - - if(S_ISLNK(s.st_mode)) - { - syslog(LOG_WARNING, _("Warning: `%s' is a symlink"), - f); - - if(readlink(f, l, MAXBUFSIZE) < 0) - { - syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, strerror(errno)); - return 0; - } - - f = l; - goto check1; - } - - *p = x; - f = file; + if(lstat(f, &s) < 0) { + syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno)); + return 0; + } + + if(s.st_uid != geteuid()) { + syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"), + f, s.st_uid, geteuid()); + return 0; + } + + if(S_ISLNK(s.st_mode)) { + syslog(LOG_WARNING, _("Warning: `%s' is a symlink"), f); + + if(readlink(f, l, MAXBUFSIZE) < 0) { + syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, + strerror(errno)); + return 0; + } + + f = l; + goto check1; + } + + *p = x; + f = file; check2: - if(lstat(f, &s) < 0 && errno != ENOENT) - { - syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno)); - return 0; - } - - if(errno == ENOENT) - return 1; - - if(s.st_uid != geteuid()) - { - syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"), - f, s.st_uid, geteuid()); - return 0; - } - - if(S_ISLNK(s.st_mode)) - { - syslog(LOG_WARNING, _("Warning: `%s' is a symlink"), - f); - - if(readlink(f, l, MAXBUFSIZE) < 0) - { - syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, strerror(errno)); - return 0; - } - - f = l; - goto check2; - } - - if(s.st_mode & 0007) - { - /* Accessible by others */ - syslog(LOG_ERR, _("`%s' has unsecure permissions"), - f); - return 0; - } - - return 1; + if(lstat(f, &s) < 0 && errno != ENOENT) { + syslog(LOG_ERR, _("Couldn't stat `%s': %s"), f, strerror(errno)); + return 0; + } + + if(errno == ENOENT) + return 1; + + if(s.st_uid != geteuid()) { + syslog(LOG_ERR, _("`%s' is owned by UID %d instead of %d"), + f, s.st_uid, geteuid()); + return 0; + } + + if(S_ISLNK(s.st_mode)) { + syslog(LOG_WARNING, _("Warning: `%s' is a symlink"), f); + + if(readlink(f, l, MAXBUFSIZE) < 0) { + syslog(LOG_ERR, _("Unable to read symbolic link `%s': %s"), f, + strerror(errno)); + return 0; + } + + f = l; + goto check2; + } + + if(s.st_mode & 0007) { + /* Accessible by others */ + syslog(LOG_ERR, _("`%s' has unsecure permissions"), f); + return 0; + } + + return 1; } -FILE *ask_and_safe_open(const char* filename, const char* what, const char* mode) +FILE *ask_and_safe_open(const char *filename, const char *what, + const char *mode) { - FILE *r; - char *directory; - char *fn; - - /* Check stdin and stdout */ - if(!isatty(0) || !isatty(1)) - { - /* Argh, they are running us from a script or something. Write - the files to the current directory and let them burn in hell - for ever. */ - fn = xstrdup(filename); - } - else - { - /* Ask for a file and/or directory name. */ - fprintf(stdout, _("Please enter a file to save %s to [%s]: "), - what, filename); - fflush(stdout); - - fn = readline(stdin, NULL, NULL); - - if(!fn) - { - fprintf(stderr, _("Error while reading stdin: %s\n"), strerror(errno)); - return NULL; + FILE *r; + char *directory; + char *fn; + + /* Check stdin and stdout */ + if(!isatty(0) || !isatty(1)) { + /* Argh, they are running us from a script or something. Write + the files to the current directory and let them burn in hell + for ever. */ + fn = xstrdup(filename); + } else { + /* Ask for a file and/or directory name. */ + fprintf(stdout, _("Please enter a file to save %s to [%s]: "), + what, filename); + fflush(stdout); + + fn = readline(stdin, NULL, NULL); + + if(!fn) { + fprintf(stderr, _("Error while reading stdin: %s\n"), + strerror(errno)); + return NULL; + } + + if(!strlen(fn)) + /* User just pressed enter. */ + fn = xstrdup(filename); } - if(!strlen(fn)) - /* User just pressed enter. */ - fn = xstrdup(filename); - } - - if(!strchr(fn, '/') || fn[0] != '/') - { - /* The directory is a relative path or a filename. */ - char *p; - - directory = get_current_dir_name(); - asprintf(&p, "%s/%s", directory, fn); - free(fn); - free(directory); - fn = p; - } - - umask(0077); /* Disallow everything for group and other */ - - /* Open it first to keep the inode busy */ - - r = fopen(fn, mode); - - if(!r) - { - fprintf(stderr, _("Error opening file `%s': %s\n"), - fn, strerror(errno)); - free(fn); - return NULL; - } - - /* Then check the file for nasty attacks */ - if(!is_safe_path(fn)) /* Do not permit any directories that are - readable or writeable by other users. */ - { - fprintf(stderr, _("The file `%s' (or any of the leading directories) has unsafe permissions.\n" - "I will not create or overwrite this file.\n"), - fn); - fclose(r); - free(fn); - return NULL; - } - - free(fn); - - return r; + if(!strchr(fn, '/') || fn[0] != '/') { + /* The directory is a relative path or a filename. */ + char *p; + + directory = get_current_dir_name(); + asprintf(&p, "%s/%s", directory, fn); + free(fn); + free(directory); + fn = p; + } + + umask(0077); /* Disallow everything for group and other */ + + /* Open it first to keep the inode busy */ + + r = fopen(fn, mode); + + if(!r) { + fprintf(stderr, _("Error opening file `%s': %s\n"), + fn, strerror(errno)); + free(fn); + return NULL; + } + + /* Then check the file for nasty attacks */ + if(!is_safe_path(fn)) { /* Do not permit any directories that are readable or writeable by other users. */ + fprintf(stderr, _("The file `%s' (or any of the leading directories) has unsafe permissions.\n" + "I will not create or overwrite this file.\n"), fn); + fclose(r); + free(fn); + return NULL; + } + + free(fn); + + return r; } diff --git a/src/conf.h b/src/conf.h index 847e52c..e9fb2ae 100644 --- a/src/conf.h +++ b/src/conf.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: conf.h,v 1.6.4.33 2002/06/21 10:11:12 guus Exp $ + $Id: conf.h,v 1.6.4.34 2002/09/09 21:24:31 guus Exp $ */ #ifndef __TINC_CONF_H__ @@ -32,10 +32,10 @@ #include "subnet.h" typedef struct config_t { - char *variable; - char *value; - char *file; - int line; + char *variable; + char *value; + char *file; + int line; } config_t; extern avl_tree_t *config_tree; @@ -59,12 +59,12 @@ extern int get_config_int(config_t *, int *); extern int get_config_port(config_t *, port_t *); extern int get_config_string(config_t *, char **); extern int get_config_address(config_t *, struct addrinfo **); -struct subnet_t; /* Needed for next line. */ +struct subnet_t; /* Needed for next line. */ extern int get_config_subnet(config_t *, struct subnet_t **); extern int read_config_file(avl_tree_t *, const char *); extern int read_server_config(void); -extern FILE *ask_and_safe_open(const char*, const char*, const char *); +extern FILE *ask_and_safe_open(const char *, const char *, const char *); extern int is_safe_path(const char *); -#endif /* __TINC_CONF_H__ */ +#endif /* __TINC_CONF_H__ */ diff --git a/src/connection.c b/src/connection.c index 9fd23a7..089ff0d 100644 --- a/src/connection.c +++ b/src/connection.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: connection.c,v 1.1.2.32 2002/09/09 19:39:58 guus Exp $ + $Id: connection.c,v 1.1.2.33 2002/09/09 21:24:31 guus Exp $ */ #include "config.h" @@ -30,7 +30,7 @@ #include #include -#include "net.h" /* Don't ask. */ +#include "net.h" /* Don't ask. */ #include "netutl.h" #include "config.h" #include "conf.h" @@ -43,102 +43,109 @@ avl_tree_t *connection_tree; /* Meta connections */ connection_t *broadcast; -int connection_compare(connection_t *a, connection_t *b) +int connection_compare(connection_t * a, connection_t * b) { - return a - b; + return a - b; } void init_connections(void) { - cp(); - connection_tree = avl_alloc_tree((avl_compare_t)connection_compare, NULL); - cp(); - broadcast = new_connection(); - broadcast->name = xstrdup(_("everyone")); - broadcast->hostname = xstrdup(_("BROADCAST")); - cp(); + cp(); + + connection_tree = avl_alloc_tree((avl_compare_t) connection_compare, NULL); + broadcast = new_connection(); + broadcast->name = xstrdup(_("everyone")); + broadcast->hostname = xstrdup(_("BROADCAST")); } void exit_connections(void) { - cp(); - avl_delete_tree(connection_tree); - cp(); - free_connection(broadcast); - cp(); + cp(); + + avl_delete_tree(connection_tree); + free_connection(broadcast); } connection_t *new_connection(void) { - connection_t *c; - cp(); - c = (connection_t *)xmalloc_and_zero(sizeof(connection_t)); + connection_t *c; + + cp(); + + c = (connection_t *) xmalloc_and_zero(sizeof(connection_t)); + + if(!c) + return NULL; - if(!c) - return NULL; + gettimeofday(&c->start, NULL); - gettimeofday(&c->start, NULL); - cp(); - return c; + return c; } -void free_connection(connection_t *c) +void free_connection(connection_t * c) { - cp(); - if(c->hostname) - free(c->hostname); - if(c->inkey) - free(c->inkey); - if(c->outkey) - free(c->outkey); - if(c->mychallenge) - free(c->mychallenge); - if(c->hischallenge) - free(c->hischallenge); - free(c); - cp(); + cp(); + + if(c->hostname) + free(c->hostname); + + if(c->inkey) + free(c->inkey); + + if(c->outkey) + free(c->outkey); + + if(c->mychallenge) + free(c->mychallenge); + + if(c->hischallenge) + free(c->hischallenge); + + free(c); } -void connection_add(connection_t *c) +void connection_add(connection_t * c) { - cp(); - avl_insert(connection_tree, c); - cp(); + cp(); + + avl_insert(connection_tree, c); } -void connection_del(connection_t *c) +void connection_del(connection_t * c) { - cp(); - avl_delete(connection_tree, c); - cp(); + cp(); + + avl_delete(connection_tree, c); } void dump_connections(void) { - avl_node_t *node; - connection_t *c; - cp(); - syslog(LOG_DEBUG, _("Connections:")); - - for(node = connection_tree->head; node; node = node->next) - { - c = (connection_t *)node->data; - syslog(LOG_DEBUG, _(" %s at %s options %lx socket %d status %04x"), - c->name, c->hostname, c->options, c->socket, c->status); - } - - syslog(LOG_DEBUG, _("End of connections.")); - cp(); + avl_node_t *node; + connection_t *c; + + cp(); + + syslog(LOG_DEBUG, _("Connections:")); + + for(node = connection_tree->head; node; node = node->next) { + c = (connection_t *) node->data; + syslog(LOG_DEBUG, _(" %s at %s options %lx socket %d status %04x"), + c->name, c->hostname, c->options, c->socket, c->status); + } + + syslog(LOG_DEBUG, _("End of connections.")); } -int read_connection_config(connection_t *c) +int read_connection_config(connection_t * c) { - char *fname; - int x; - cp(); - asprintf(&fname, "%s/hosts/%s", confbase, c->name); - x = read_config_file(c->config_tree, fname); - free(fname); - cp(); - return x; + char *fname; + int x; + + cp(); + + asprintf(&fname, "%s/hosts/%s", confbase, c->name); + x = read_config_file(c->config_tree, fname); + free(fname); + + return x; } diff --git a/src/connection.h b/src/connection.h index 4d2ea2d..9755227 100644 --- a/src/connection.h +++ b/src/connection.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: connection.h,v 1.1.2.30 2002/09/04 16:26:44 guus Exp $ + $Id: connection.h,v 1.1.2.31 2002/09/09 21:24:31 guus Exp $ */ #ifndef __TINC_CONNECTION_H__ @@ -50,62 +50,62 @@ #define OPTION_TCPONLY 0x0002 typedef struct connection_status_t { - int pinged:1; /* sent ping */ - int active:1; /* 1 if active.. */ - int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */ - int termreq:1; /* the termination of this connection was requested */ - int remove:1; /* Set to 1 if you want this connection removed */ - int timeout:1; /* 1 if gotten timeout */ - int encryptout:1; /* 1 if we can encrypt outgoing traffic */ - int decryptin:1; /* 1 if we have to decrypt incoming traffic */ - int mst:1; /* 1 if this connection is part of a minimum spanning tree */ - int unused:18; + int pinged:1; /* sent ping */ + int active:1; /* 1 if active.. */ + int connecting:1; /* 1 if we are waiting for a non-blocking connect() to finish */ + int termreq:1; /* the termination of this connection was requested */ + int remove:1; /* Set to 1 if you want this connection removed */ + int timeout:1; /* 1 if gotten timeout */ + int encryptout:1; /* 1 if we can encrypt outgoing traffic */ + int decryptin:1; /* 1 if we have to decrypt incoming traffic */ + int mst:1; /* 1 if this connection is part of a minimum spanning tree */ + int unused:18; } connection_status_t; typedef struct connection_t { - char *name; /* name he claims to have */ - - sockaddr_t address; /* his real (internet) ip */ - char *hostname; /* the hostname of its real ip */ - int protocol_version; /* used protocol */ - - int socket; /* socket used for this connection */ - long int options; /* options for this connection */ - struct connection_status_t status; /* status info */ - int estimated_weight; /* estimation for the weight of the edge for this connection */ - struct timeval start; /* time this connection was started, used for above estimation */ - struct outgoing_t *outgoing; /* used to keep track of outgoing connections */ - - struct node_t *node; /* node associated with the other end */ - struct edge_t *edge; /* edge associated with this connection */ - - RSA *rsa_key; /* his public/private key */ - const EVP_CIPHER *incipher; /* Cipher he will use to send data to us */ - const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */ - EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */ - EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */ - char *inkey; /* His symmetric meta key + iv */ - char *outkey; /* Our symmetric meta key + iv */ - int inkeylength; /* Length of his key + iv */ - int outkeylength; /* Length of our key + iv */ - const EVP_MD *indigest; - const EVP_MD *outdigest; - int inmaclength; - int outmaclength; - int incompression; - int outcompression; - char *mychallenge; /* challenge we received from him */ - char *hischallenge; /* challenge we sent to him */ - - char buffer[MAXBUFSIZE]; /* metadata input buffer */ - int buflen; /* bytes read into buffer */ - int reqlen; /* length of incoming request */ - int tcplen; /* length of incoming TCPpacket */ - int allow_request; /* defined if there's only one request possible */ - - time_t last_ping_time; /* last time we saw some activity from the other end */ - - avl_tree_t *config_tree; /* Pointer to configuration tree belonging to him */ + char *name; /* name he claims to have */ + + sockaddr_t address; /* his real (internet) ip */ + char *hostname; /* the hostname of its real ip */ + int protocol_version; /* used protocol */ + + int socket; /* socket used for this connection */ + long int options; /* options for this connection */ + struct connection_status_t status; /* status info */ + int estimated_weight; /* estimation for the weight of the edge for this connection */ + struct timeval start; /* time this connection was started, used for above estimation */ + struct outgoing_t *outgoing; /* used to keep track of outgoing connections */ + + struct node_t *node; /* node associated with the other end */ + struct edge_t *edge; /* edge associated with this connection */ + + RSA *rsa_key; /* his public/private key */ + const EVP_CIPHER *incipher; /* Cipher he will use to send data to us */ + const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */ + EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */ + EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */ + char *inkey; /* His symmetric meta key + iv */ + char *outkey; /* Our symmetric meta key + iv */ + int inkeylength; /* Length of his key + iv */ + int outkeylength; /* Length of our key + iv */ + const EVP_MD *indigest; + const EVP_MD *outdigest; + int inmaclength; + int outmaclength; + int incompression; + int outcompression; + char *mychallenge; /* challenge we received from him */ + char *hischallenge; /* challenge we sent to him */ + + char buffer[MAXBUFSIZE]; /* metadata input buffer */ + int buflen; /* bytes read into buffer */ + int reqlen; /* length of incoming request */ + int tcplen; /* length of incoming TCPpacket */ + int allow_request; /* defined if there's only one request possible */ + + time_t last_ping_time; /* last time we saw some activity from the other end */ + + avl_tree_t *config_tree; /* Pointer to configuration tree belonging to him */ } connection_t; extern avl_tree_t *connection_tree; @@ -120,4 +120,4 @@ extern void connection_del(connection_t *); extern void dump_connections(void); extern int read_connection_config(connection_t *); -#endif /* __TINC_CONNECTION_H__ */ +#endif /* __TINC_CONNECTION_H__ */ diff --git a/src/cygwin/device.c b/src/cygwin/device.c index f5380ab..b14aec1 100644 --- a/src/cygwin/device.c +++ b/src/cygwin/device.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: device.c,v 1.1.2.1 2002/07/11 12:57:06 guus Exp $ + $Id: device.c,v 1.1.2.2 2002/09/09 21:25:18 guus Exp $ */ #include "config.h" @@ -51,90 +51,78 @@ extern subnet_t mymac; int setup_device(void) { - struct ifreq ifr; - -cp - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = DEFAULT_DEVICE; - - if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) - interface = rindex(device, '/')?rindex(device, '/')+1:device; -cp - if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) - { - syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return -1; - } -cp - /* Set default MAC address for ethertap devices */ - - mymac.type = SUBNET_MAC; - mymac.net.mac.address.x[0] = 0xfe; - mymac.net.mac.address.x[1] = 0xfd; - mymac.net.mac.address.x[2] = 0x00; - mymac.net.mac.address.x[3] = 0x00; - mymac.net.mac.address.x[4] = 0x00; - mymac.net.mac.address.x[5] = 0x00; - - device_info = _("Stub device for Cygwin environment"); - - syslog(LOG_INFO, _("%s is a %s"), device, device_info); -cp - return 0; + struct ifreq ifr; + + cp if(!get_config_string(lookup_config(config_tree, "Device"), &device)) + device = DEFAULT_DEVICE; + + if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) + interface = rindex(device, '/') ? rindex(device, '/') + 1 : device; + cp if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) { + syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); + return -1; + } + cp + /* Set default MAC address for ethertap devices */ + mymac.type = SUBNET_MAC; + mymac.net.mac.address.x[0] = 0xfe; + mymac.net.mac.address.x[1] = 0xfd; + mymac.net.mac.address.x[2] = 0x00; + mymac.net.mac.address.x[3] = 0x00; + mymac.net.mac.address.x[4] = 0x00; + mymac.net.mac.address.x[5] = 0x00; + + device_info = _("Stub device for Cygwin environment"); + + syslog(LOG_INFO, _("%s is a %s"), device, device_info); + cp return 0; } void close_device(void) { -cp - close(device_fd); + cp close(device_fd); } -int read_packet(vpn_packet_t *packet) +int read_packet(vpn_packet_t * packet) { - int lenin; -cp - if((lenin = read(device_fd, packet->data, MTU)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } + int lenin; + cp if((lenin = read(device_fd, packet->data, MTU)) <= 0) { + syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, + device, strerror(errno)); + return -1; + } - packet->len = lenin; + packet->len = lenin; - device_total_in += packet->len; + device_total_in += packet->len; - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info); - } + if(debug_lvl >= DEBUG_TRAFFIC) { + syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, + device_info); + } - return 0; -cp -} + return 0; +cp} -int write_packet(vpn_packet_t *packet) +int write_packet(vpn_packet_t * packet) { -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), - packet->len, device_info); - - if(write(device_fd, packet->data, packet->len) < 0) - { - syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - device_total_out += packet->len; -cp - return 0; + cp if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), + packet->len, device_info); + + if(write(device_fd, packet->data, packet->len) < 0) { + syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, + strerror(errno)); + return -1; + } + + device_total_out += packet->len; + cp return 0; } void dump_device_stats(void) { -cp - syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); - syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); - syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); -cp -} + cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); + syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); + syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); +cp} diff --git a/src/darwin/device.c b/src/darwin/device.c index 2f673ab..d30f0b6 100644 --- a/src/darwin/device.c +++ b/src/darwin/device.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: device.c,v 1.1.2.2 2002/06/21 10:11:34 guus Exp $ + $Id: device.c,v 1.1.2.3 2002/09/09 21:25:19 guus Exp $ */ #include "config.h" @@ -58,96 +58,83 @@ extern subnet_t mymac; */ int setup_device(void) { -cp - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = DEFAULT_DEVICE; - - if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) - interface = rindex(device, '/')?rindex(device, '/')+1:device; -cp - if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) - { - syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return -1; - } -cp - - /* Set default MAC address for ethertap devices */ - - mymac.type = SUBNET_MAC; - mymac.net.mac.address.x[0] = 0xfe; - mymac.net.mac.address.x[1] = 0xfd; - mymac.net.mac.address.x[2] = 0x00; - mymac.net.mac.address.x[3] = 0x00; - mymac.net.mac.address.x[4] = 0x00; - mymac.net.mac.address.x[5] = 0x00; - - device_info = _("MacOS/X tun device"); - - syslog(LOG_INFO, _("%s is a %s"), device, device_info); -cp - return 0; + cp if(!get_config_string(lookup_config(config_tree, "Device"), &device)) + device = DEFAULT_DEVICE; + + if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) + interface = rindex(device, '/') ? rindex(device, '/') + 1 : device; + cp if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) { + syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); + return -1; + } + cp + /* Set default MAC address for ethertap devices */ + mymac.type = SUBNET_MAC; + mymac.net.mac.address.x[0] = 0xfe; + mymac.net.mac.address.x[1] = 0xfd; + mymac.net.mac.address.x[2] = 0x00; + mymac.net.mac.address.x[3] = 0x00; + mymac.net.mac.address.x[4] = 0x00; + mymac.net.mac.address.x[5] = 0x00; + + device_info = _("MacOS/X tun device"); + + syslog(LOG_INFO, _("%s is a %s"), device, device_info); + cp return 0; } void close_device(void) { -cp - close(device_fd); + cp close(device_fd); } /* read, encrypt and send data that is available through the ethertap device */ -int read_packet(vpn_packet_t *packet) +int read_packet(vpn_packet_t * packet) { - int lenin; -cp - if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } + int lenin; + cp if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) { + syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, + device, strerror(errno)); + return -1; + } - memcpy(packet->data, mymac.net.mac.address.x, 6); - memcpy(packet->data + 6, mymac.net.mac.address.x, 6); - packet->data[12] = 0x08; - packet->data[13] = 0x00; + memcpy(packet->data, mymac.net.mac.address.x, 6); + memcpy(packet->data + 6, mymac.net.mac.address.x, 6); + packet->data[12] = 0x08; + packet->data[13] = 0x00; - packet->len = lenin + 14; + packet->len = lenin + 14; - device_total_in += packet->len; + device_total_in += packet->len; - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), - packet->len, device_info); + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), + packet->len, device_info); - return 0; -cp -} + return 0; +cp} -int write_packet(vpn_packet_t *packet) +int write_packet(vpn_packet_t * packet) { -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), - packet->len, device_info); - - if(write(device_fd, packet->data + 14, packet->len - 14) < 0) - { - syslog(LOG_ERR, _("Error while writing to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - device_total_out += packet->len; -cp -} + cp if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), + packet->len, device_info); + + if(write(device_fd, packet->data + 14, packet->len - 14) < 0) { + syslog(LOG_ERR, _("Error while writing to %s %s: %s"), device_info, + device, strerror(errno)); + return -1; + } + + device_total_out += packet->len; +cp} void dump_device_stats(void) { -cp - syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); - syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); - syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); -cp -} + cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); + syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); + syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); +cp} diff --git a/src/device.h b/src/device.h index 20f9dad..04225dd 100644 --- a/src/device.h +++ b/src/device.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: device.h,v 1.1.2.6 2002/06/21 10:11:12 guus Exp $ + $Id: device.h,v 1.1.2.7 2002/09/09 21:24:31 guus Exp $ */ #ifndef __TINC_DEVICE_H__ @@ -33,4 +33,4 @@ extern int read_packet(vpn_packet_t *); extern int write_packet(vpn_packet_t *); extern void dump_device_stats(void); -#endif /* __TINC_DEVICE_H__ */ +#endif /* __TINC_DEVICE_H__ */ diff --git a/src/edge.c b/src/edge.c index e35d806..8c10009 100644 --- a/src/edge.c +++ b/src/edge.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: edge.c,v 1.1.2.15 2002/09/09 19:39:58 guus Exp $ + $Id: edge.c,v 1.1.2.16 2002/09/09 21:24:31 guus Exp $ */ #include "config.h" @@ -29,7 +29,7 @@ #include #include -#include "net.h" /* Don't ask. */ +#include "net.h" /* Don't ask. */ #include "netutl.h" #include "config.h" #include "conf.h" @@ -41,132 +41,132 @@ #include "xalloc.h" #include "system.h" -avl_tree_t *edge_weight_tree; /* Tree with all edges, sorted on weight */ +avl_tree_t *edge_weight_tree; /* Tree with all edges, sorted on weight */ -int edge_compare(edge_t *a, edge_t *b) +int edge_compare(edge_t * a, edge_t * b) { - return strcmp(a->to->name, b->to->name); + return strcmp(a->to->name, b->to->name); } -int edge_weight_compare(edge_t *a, edge_t *b) +int edge_weight_compare(edge_t * a, edge_t * b) { - int result; + int result; - result = a->weight - b->weight; + result = a->weight - b->weight; - if(result) - return result; + if(result) + return result; - result = strcmp(a->from->name, b->from->name); + result = strcmp(a->from->name, b->from->name); - if(result) - return result; + if(result) + return result; - return strcmp(a->to->name, b->to->name); + return strcmp(a->to->name, b->to->name); } void init_edges(void) { - cp(); - edge_weight_tree = avl_alloc_tree((avl_compare_t)edge_weight_compare, NULL); - cp(); + 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, NULL); - cp(); + cp(); + + return avl_alloc_tree((avl_compare_t) edge_compare, NULL); } -void free_edge_tree(avl_tree_t *edge_tree) +void free_edge_tree(avl_tree_t * edge_tree) { - cp(); - avl_delete_tree(edge_tree); - cp(); + cp(); + + avl_delete_tree(edge_tree); } void exit_edges(void) { - cp(); - avl_delete_tree(edge_weight_tree); - cp(); + cp(); + + avl_delete_tree(edge_weight_tree); } /* Creation and deletion of connection elements */ edge_t *new_edge(void) { - edge_t *e; - cp(); - e = (edge_t *)xmalloc_and_zero(sizeof(*e)); - cp(); - return e; + cp(); + + return (edge_t *) xmalloc_and_zero(sizeof(edge_t)); } -void free_edge(edge_t *e) +void free_edge(edge_t * e) { - cp(); - free(e); - cp(); + cp(); + + free(e); } -void edge_add(edge_t *e) +void edge_add(edge_t * e) { - cp(); - avl_insert(edge_weight_tree, e); - avl_insert(e->from->edge_tree, e); - cp(); - e->reverse = lookup_edge(e->to, e->from); - if(e->reverse) - e->reverse->reverse = e; - cp(); + cp(); + + avl_insert(edge_weight_tree, e); + avl_insert(e->from->edge_tree, e); + + e->reverse = lookup_edge(e->to, e->from); + + if(e->reverse) + e->reverse->reverse = e; } -void edge_del(edge_t *e) +void edge_del(edge_t * e) { - cp(); - if(e->reverse) - e->reverse->reverse = NULL; - cp(); - avl_delete(edge_weight_tree, e); - avl_delete(e->from->edge_tree, e); - cp(); + cp(); + + if(e->reverse) + e->reverse->reverse = NULL; + + avl_delete(e->from->edge_tree, e); + avl_delete(edge_weight_tree, e); } -edge_t *lookup_edge(node_t *from, node_t *to) +edge_t *lookup_edge(node_t * from, node_t * to) { - edge_t v; - cp(); - v.from = from; - v.to = to; + edge_t v; + + cp(); + + v.from = from; + v.to = to; - return avl_search(from->edge_tree, &v); + return avl_search(from->edge_tree, &v); } void dump_edges(void) { - avl_node_t *node, *node2; - node_t *n; - edge_t *e; - char *address; - cp(); - syslog(LOG_DEBUG, _("Edges:")); - - for(node = node_tree->head; node; node = node->next) - { - n = (node_t *)node->data; - for(node2 = n->edge_tree->head; node2; node2 = node2->next) - { - e = (edge_t *)node2->data; - address = sockaddr2hostname(&e->address); - syslog(LOG_DEBUG, _(" %s to %s at %s options %lx weight %d"), - e->from->name, e->to->name, address, - e->options, e->weight); - free(address); + avl_node_t *node, *node2; + node_t *n; + edge_t *e; + char *address; + + cp(); + + syslog(LOG_DEBUG, _("Edges:")); + + for(node = node_tree->head; node; node = node->next) { + n = (node_t *) node->data; + for(node2 = n->edge_tree->head; node2; node2 = node2->next) { + e = (edge_t *) node2->data; + address = sockaddr2hostname(&e->address); + syslog(LOG_DEBUG, _(" %s to %s at %s options %lx weight %d"), + e->from->name, e->to->name, address, e->options, e->weight); + free(address); + } } - } - syslog(LOG_DEBUG, _("End of edges.")); - cp(); + syslog(LOG_DEBUG, _("End of edges.")); } diff --git a/src/edge.h b/src/edge.h index 9ddb756..875b1aa 100644 --- a/src/edge.h +++ b/src/edge.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: edge.h,v 1.1.2.10 2002/09/06 10:23:52 guus Exp $ + $Id: edge.h,v 1.1.2.11 2002/09/09 21:24:31 guus Exp $ */ #ifndef __TINC_EDGE_H__ @@ -30,18 +30,18 @@ #include "connection.h" typedef struct edge_t { - struct node_t *from; - struct node_t *to; - sockaddr_t address; - - long int options; /* options turned on for this edge */ - int weight; /* weight of this edge */ - - struct connection_t *connection; /* connection associated with this edge, if available */ - struct edge_t *reverse; /* edge in the opposite direction, if available */ + struct node_t *from; + struct node_t *to; + sockaddr_t address; + + long int options; /* options turned on for this edge */ + int weight; /* weight of this edge */ + + struct connection_t *connection; /* connection associated with this edge, if available */ + struct edge_t *reverse; /* edge in the opposite direction, if available */ } edge_t; -extern avl_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weight */ +extern avl_tree_t *edge_weight_tree; /* Tree with all known edges sorted on weight */ extern void init_edges(void); extern void exit_edges(void); @@ -54,4 +54,4 @@ extern void edge_del(edge_t *); extern edge_t *lookup_edge(struct node_t *, struct node_t *); extern void dump_edges(void); -#endif /* __TINC_EDGE_H__ */ +#endif /* __TINC_EDGE_H__ */ diff --git a/src/event.c b/src/event.c index bc56dc1..acf2ffb 100644 --- a/src/event.c +++ b/src/event.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: event.c,v 1.1.4.4 2002/09/09 19:39:58 guus Exp $ + $Id: event.c,v 1.1.4.5 2002/09/09 21:24:31 guus Exp $ */ #include "config.h" @@ -38,73 +38,74 @@ extern time_t now; int id; -int event_compare(event_t *a, event_t *b) +int event_compare(event_t * a, event_t * b) { - if(a->time > b->time) - return 1; - if(a->time < b->time) - return -1; - return a->id - b->id; + if(a->time > b->time) + return 1; + + if(a->time < b->time) + return -1; + + return a->id - b->id; } void init_events(void) { - cp(); - event_tree = avl_alloc_tree((avl_compare_t)event_compare, NULL); - cp(); + cp(); + + event_tree = avl_alloc_tree((avl_compare_t) event_compare, NULL); } void exit_events(void) { - cp(); - avl_delete_tree(event_tree); - cp(); + cp(); + + avl_delete_tree(event_tree); } event_t *new_event(void) { - event_t *event; - cp(); - event = (event_t *)xmalloc_and_zero(sizeof(*event)); - cp(); - return event; + cp(); + + return (event_t *) xmalloc_and_zero(sizeof(event_t)); } -void free_event(event_t *event) +void free_event(event_t * event) { - cp(); - free(event); - cp(); + cp(); + + free(event); } -void event_add(event_t *event) +void event_add(event_t * event) { - cp(); - event->id = ++id; - avl_insert(event_tree, event); - cp(); + cp(); + + event->id = ++id; + avl_insert(event_tree, event); } -void event_del(event_t *event) +void event_del(event_t * event) { - cp(); - avl_delete(event_tree, event); - cp(); + cp(); + + avl_delete(event_tree, event); } event_t *get_expired_event(void) { - event_t *event; - cp(); - if(event_tree->head) - { - event = (event_t *)event_tree->head->data; - if(event->time < now) - { - avl_delete(event_tree, event); - return event; - } - } - cp(); - return NULL; + event_t *event; + + cp(); + + if(event_tree->head) { + event = (event_t *) event_tree->head->data; + + if(event->time < now) { + avl_delete(event_tree, event); + return event; + } + } + + return NULL; } diff --git a/src/event.h b/src/event.h index e5f5516..5833ad1 100644 --- a/src/event.h +++ b/src/event.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: event.h,v 1.1.4.2 2002/06/21 10:11:12 guus Exp $ + $Id: event.h,v 1.1.4.3 2002/09/09 21:24:34 guus Exp $ */ #ifndef __TINC_EVENT_H__ @@ -28,13 +28,13 @@ avl_tree_t *event_tree; -typedef void (*event_handler_t)(void *); +typedef void (*event_handler_t) (void *); typedef struct { - time_t time; - int id; - event_handler_t handler; - void *data; + time_t time; + int id; + event_handler_t handler; + void *data; } event_t; extern void init_events(void); @@ -45,4 +45,4 @@ extern void event_add(event_t *); extern void event_del(event_t *); extern event_t *get_expired_event(void); -#endif /* __TINC_EVENT_H__ */ +#endif /* __TINC_EVENT_H__ */ diff --git a/src/freebsd/device.c b/src/freebsd/device.c index 1139c65..0e3a9fc 100644 --- a/src/freebsd/device.c +++ b/src/freebsd/device.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: device.c,v 1.1.2.5 2002/06/21 10:11:35 guus Exp $ + $Id: device.c,v 1.1.2.6 2002/09/09 21:25:19 guus Exp $ */ #include "config.h" @@ -58,91 +58,78 @@ extern subnet_t mymac; */ int setup_device(void) { -cp - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = DEFAULT_DEVICE; - - if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) - interface = rindex(device, '/')?rindex(device, '/')+1:device; -cp - if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) - { - syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return -1; - } -cp - - /* Set default MAC address for ethertap devices */ - - mymac.type = SUBNET_MAC; - mymac.net.mac.address.x[0] = 0xfe; - mymac.net.mac.address.x[1] = 0xfd; - mymac.net.mac.address.x[2] = 0x00; - mymac.net.mac.address.x[3] = 0x00; - mymac.net.mac.address.x[4] = 0x00; - mymac.net.mac.address.x[5] = 0x00; - - device_info = _("FreeBSD tap device"); - - syslog(LOG_INFO, _("%s is a %s"), device, device_info); -cp - return 0; + cp if(!get_config_string(lookup_config(config_tree, "Device"), &device)) + device = DEFAULT_DEVICE; + + if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) + interface = rindex(device, '/') ? rindex(device, '/') + 1 : device; + cp if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) { + syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); + return -1; + } + cp + /* Set default MAC address for ethertap devices */ + mymac.type = SUBNET_MAC; + mymac.net.mac.address.x[0] = 0xfe; + mymac.net.mac.address.x[1] = 0xfd; + mymac.net.mac.address.x[2] = 0x00; + mymac.net.mac.address.x[3] = 0x00; + mymac.net.mac.address.x[4] = 0x00; + mymac.net.mac.address.x[5] = 0x00; + + device_info = _("FreeBSD tap device"); + + syslog(LOG_INFO, _("%s is a %s"), device, device_info); + cp return 0; } void close_device(void) { -cp - close(device_fd); + cp close(device_fd); } /* read, encrypt and send data that is available through the ethertap device */ -int read_packet(vpn_packet_t *packet) +int read_packet(vpn_packet_t * packet) { - int lenin; -cp - if((lenin = read(device_fd, packet->data, MTU)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } + int lenin; + cp if((lenin = read(device_fd, packet->data, MTU)) <= 0) { + syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, + device, strerror(errno)); + return -1; + } - packet->len = lenin; + packet->len = lenin; - device_total_in += packet->len; + device_total_in += packet->len; - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), - packet->len, device_info); + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), + packet->len, device_info); - return 0; -cp -} + return 0; +cp} -int write_packet(vpn_packet_t *packet) +int write_packet(vpn_packet_t * packet) { -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), - packet->len, device_info); - - if(write(device_fd, packet->data, packet->len) < 0) - { - syslog(LOG_ERR, _("Error while writing to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - device_total_out += packet->len; -cp -} + cp if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), + packet->len, device_info); + + if(write(device_fd, packet->data, packet->len) < 0) { + syslog(LOG_ERR, _("Error while writing to %s %s: %s"), device_info, + device, strerror(errno)); + return -1; + } + + device_total_out += packet->len; +cp} void dump_device_stats(void) { -cp - syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); - syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); - syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); -cp -} + cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); + syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); + syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); +cp} diff --git a/src/graph.c b/src/graph.c index fb1eb65..d1bd2ac 100644 --- a/src/graph.c +++ b/src/graph.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: graph.c,v 1.1.2.18 2002/09/09 19:39:58 guus Exp $ + $Id: graph.c,v 1.1.2.19 2002/09/09 21:24:34 guus Exp $ */ /* We need to generate two trees from the graph: @@ -51,7 +51,7 @@ #include "config.h" #include #ifdef HAVE_SYS_PARAM_H - #include +#include #endif #include @@ -74,78 +74,79 @@ void mst_kruskal(void) { - avl_node_t *node, *next; - edge_t *e; - node_t *n; - connection_t *c; - int nodes = 0; - int safe_edges = 0; - int skipped; - - /* Clear MST status on connections */ - - for(node = connection_tree->head; node; node = node->next) - { - c = (connection_t *)node->data; - c->status.mst = 0; - } - - /* Do we have something to do at all? */ - - if(!edge_weight_tree->head) - return; - - if(debug_lvl >= DEBUG_SCARY_THINGS) - syslog(LOG_DEBUG, "Running Kruskal's algorithm:"); - - /* Clear visited status on nodes */ - - for(node = node_tree->head; node; node = node->next) - { - n = (node_t *)node->data; - n->status.visited = 0; - nodes++; - } - - /* Starting point */ - - ((edge_t *)edge_weight_tree->head->data)->from->status.visited = 1; - - /* Add safe edges */ - - for(skipped = 0, node = edge_weight_tree->head; node; node = next) - { - next = node->next; - e = (edge_t *)node->data; - - if(!e->reverse || e->from->status.visited == e->to->status.visited) - { - skipped = 1; - continue; - } - - e->from->status.visited = 1; - e->to->status.visited = 1; - if(e->connection) - e->connection->status.mst = 1; - if(e->reverse->connection) - e->reverse->connection->status.mst = 1; - - safe_edges++; - - if(debug_lvl >= DEBUG_SCARY_THINGS) - syslog(LOG_DEBUG, " Adding edge %s - %s weight %d", e->from->name, e->to->name, e->weight); - - if(skipped) - { - skipped = 0; - next = edge_weight_tree->head; - continue; - } - } - - if(debug_lvl >= DEBUG_SCARY_THINGS) - syslog(LOG_DEBUG, "Done, counted %d nodes and %d safe edges.", nodes, safe_edges); + avl_node_t *node, *next; + edge_t *e; + node_t *n; + connection_t *c; + int nodes = 0; + int safe_edges = 0; + int skipped; + + cp(); + + /* Clear MST status on connections */ + + for(node = connection_tree->head; node; node = node->next) { + c = (connection_t *) node->data; + c->status.mst = 0; + } + + /* Do we have something to do at all? */ + + if(!edge_weight_tree->head) + return; + + if(debug_lvl >= DEBUG_SCARY_THINGS) + syslog(LOG_DEBUG, "Running Kruskal's algorithm:"); + + /* Clear visited status on nodes */ + + for(node = node_tree->head; node; node = node->next) { + n = (node_t *) node->data; + n->status.visited = 0; + nodes++; + } + + /* Starting point */ + + ((edge_t *) edge_weight_tree->head->data)->from->status.visited = 1; + + /* Add safe edges */ + + for(skipped = 0, node = edge_weight_tree->head; node; node = next) { + next = node->next; + e = (edge_t *) node->data; + + if(!e->reverse || e->from->status.visited == e->to->status.visited) { + skipped = 1; + continue; + } + + e->from->status.visited = 1; + e->to->status.visited = 1; + + if(e->connection) + e->connection->status.mst = 1; + + if(e->reverse->connection) + e->reverse->connection->status.mst = 1; + + safe_edges++; + + if(debug_lvl >= DEBUG_SCARY_THINGS) + syslog(LOG_DEBUG, " Adding edge %s - %s weight %d", e->from->name, + e->to->name, e->weight); + + if(skipped) { + skipped = 0; + next = edge_weight_tree->head; + continue; + } + } + + if(debug_lvl >= DEBUG_SCARY_THINGS) + syslog(LOG_DEBUG, "Done, counted %d nodes and %d safe edges.", nodes, + safe_edges); } /* Implementation of a simple breadth-first search algorithm. @@ -154,144 +155,152 @@ void mst_kruskal(void) void sssp_bfs(void) { - avl_node_t *node, *from, *next, *to; - edge_t *e; - node_t *n; - avl_tree_t *todo_tree; - int indirect; - char *name; - char *address, *port; - char *envp[7]; - int i; - - todo_tree = avl_alloc_tree(NULL, NULL); - - /* Clear visited status on nodes */ - - for(node = node_tree->head; node; node = node->next) - { - n = (node_t *)node->data; - n->status.visited = 0; - n->status.indirect = 1; - } - - /* Begin with myself */ - - myself->status.visited = 1; - myself->status.indirect = 0; - myself->nexthop = myself; - myself->via = myself; - node = avl_alloc_node(); - node->data = myself; - avl_insert_top(todo_tree, node); - - /* Loop while todo_tree is filled */ - - while(todo_tree->head) - { - for(from = todo_tree->head; from; from = next) /* "from" is the node from which we start */ - { - next = from->next; - n = (node_t *)from->data; - - for(to = n->edge_tree->head; to; to = to->next) /* "to" is the edge connected to "from" */ - { - e = (edge_t *)to->data; - - if(!e->reverse) - continue; - - /* Situation: - - / - / - ------(n)-----(e->to) - \ - \ - - n->address is set to the e->address of the edge left of n to n. - We are currently examining the edge e right of n from n: - - - If e->reverse->address != n->address, then e->to is probably - not reachable for the nodes left of n. We do as if the indirectdata - flag is set on edge e. - - If edge e provides for better reachability of e->to, update - e->to and (re)add it to the todo_tree to (re)examine the reachability - of nodes behind it. - */ - - indirect = n->status.indirect || e->options & OPTION_INDIRECT || ((n != myself) && sockaddrcmp(&n->address, &e->reverse->address)); - - if(e->to->status.visited && (!e->to->status.indirect || indirect)) - continue; - - e->to->status.visited = 1; - e->to->status.indirect = indirect; - e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop; - e->to->via = indirect ? n->via : e->to; - e->to->options = e->options; - if(sockaddrcmp(&e->to->address, &e->address)) - { - node = avl_unlink(node_udp_tree, e->to); - e->to->address = e->address; - if(e->to->hostname) - free(e->to->hostname); - e->to->hostname = sockaddr2hostname(&e->to->address); - avl_insert_node(node_udp_tree, node); - } - node = avl_alloc_node(); - node->data = e->to; - avl_insert_before(todo_tree, from, node); - } - - avl_delete_node(todo_tree, from); - } - } - - avl_free_tree(todo_tree); - - /* Check reachability status. */ - - for(node = node_tree->head; node; node = next) - { - next = node->next; - n = (node_t *)node->data; - - if(n->status.visited != n->status.reachable) - { - n->status.reachable = !n->status.reachable; - if(debug_lvl >= DEBUG_TRAFFIC) - if(n->status.reachable) - syslog(LOG_DEBUG, _("Node %s (%s) became reachable"), n->name, n->hostname); - else - syslog(LOG_DEBUG, _("Node %s (%s) became unreachable"), n->name, n->hostname); - - n->status.validkey = 0; - n->status.waitingforkey = 0; - - asprintf(&envp[0], "NETNAME=%s", netname?:""); - asprintf(&envp[1], "DEVICE=%s", device?:""); - asprintf(&envp[2], "INTERFACE=%s", interface?:""); - asprintf(&envp[3], "NODE=%s", n->name); - sockaddr2str(&n->address, &address, &port); - asprintf(&envp[4], "REMOTEADDRESS=%s", address); - asprintf(&envp[5], "REMOTEPORT=%s", port); - envp[6] = NULL; - - asprintf(&name, n->status.reachable?"hosts/%s-up":"hosts/%s-down", n->name); - execute_script(name, envp); - free(name); - free(address); - free(port); - - for(i = 0; i < 7; i++) - free(envp[i]); - } - } + avl_node_t *node, *from, *next, *to; + edge_t *e; + node_t *n; + avl_tree_t *todo_tree; + int indirect; + char *name; + char *address, *port; + char *envp[7]; + int i; + + cp(); + + todo_tree = avl_alloc_tree(NULL, NULL); + + /* Clear visited status on nodes */ + + for(node = node_tree->head; node; node = node->next) { + n = (node_t *) node->data; + n->status.visited = 0; + n->status.indirect = 1; + } + + /* Begin with myself */ + + myself->status.visited = 1; + myself->status.indirect = 0; + myself->nexthop = myself; + myself->via = myself; + node = avl_alloc_node(); + node->data = myself; + avl_insert_top(todo_tree, node); + + /* Loop while todo_tree is filled */ + + while(todo_tree->head) { + for(from = todo_tree->head; from; from = next) { /* "from" is the node from which we start */ + next = from->next; + n = (node_t *) from->data; + + for(to = n->edge_tree->head; to; to = to->next) { /* "to" is the edge connected to "from" */ + e = (edge_t *) to->data; + + if(!e->reverse) + continue; + + /* Situation: + + / + / + ------(n)-----(e->to) + \ + \ + + n->address is set to the e->address of the edge left of n to n. + We are currently examining the edge e right of n from n: + + - If e->reverse->address != n->address, then e->to is probably + not reachable for the nodes left of n. We do as if the indirectdata + flag is set on edge e. + - If edge e provides for better reachability of e->to, update + e->to and (re)add it to the todo_tree to (re)examine the reachability + of nodes behind it. + */ + + indirect = n->status.indirect || e->options & OPTION_INDIRECT + || ((n != myself) + && sockaddrcmp(&n->address, &e->reverse->address)); + + if(e->to->status.visited + && (!e->to->status.indirect || indirect)) + continue; + + e->to->status.visited = 1; + e->to->status.indirect = indirect; + e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop; + e->to->via = indirect ? n->via : e->to; + e->to->options = e->options; + + if(sockaddrcmp(&e->to->address, &e->address)) { + node = avl_unlink(node_udp_tree, e->to); + e->to->address = e->address; + + if(e->to->hostname) + free(e->to->hostname); + + e->to->hostname = sockaddr2hostname(&e->to->address); + avl_insert_node(node_udp_tree, node); + } + + node = avl_alloc_node(); + node->data = e->to; + avl_insert_before(todo_tree, from, node); + } + + avl_delete_node(todo_tree, from); + } + } + + avl_free_tree(todo_tree); + + /* Check reachability status. */ + + for(node = node_tree->head; node; node = next) { + next = node->next; + n = (node_t *) node->data; + + if(n->status.visited != n->status.reachable) { + n->status.reachable = !n->status.reachable; + + if(debug_lvl >= DEBUG_TRAFFIC) + if(n->status.reachable) + syslog(LOG_DEBUG, _("Node %s (%s) became reachable"), + n->name, n->hostname); + else + syslog(LOG_DEBUG, _("Node %s (%s) became unreachable"), + n->name, n->hostname); + + n->status.validkey = 0; + n->status.waitingforkey = 0; + + asprintf(&envp[0], "NETNAME=%s", netname ? : ""); + asprintf(&envp[1], "DEVICE=%s", device ? : ""); + asprintf(&envp[2], "INTERFACE=%s", interface ? : ""); + asprintf(&envp[3], "NODE=%s", n->name); + sockaddr2str(&n->address, &address, &port); + asprintf(&envp[4], "REMOTEADDRESS=%s", address); + asprintf(&envp[5], "REMOTEPORT=%s", port); + envp[6] = NULL; + + asprintf(&name, + n->status.reachable ? "hosts/%s-up" : "hosts/%s-down", + n->name); + execute_script(name, envp); + + free(name); + free(address); + free(port); + + for(i = 0; i < 7; i++) + free(envp[i]); + } + } } void graph(void) { - mst_kruskal(); - sssp_bfs(); + mst_kruskal(); + sssp_bfs(); } diff --git a/src/linux/device.c b/src/linux/device.c index 0088acc..0391f6a 100644 --- a/src/linux/device.c +++ b/src/linux/device.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: device.c,v 1.1.2.10 2002/09/09 19:40:12 guus Exp $ + $Id: device.c,v 1.1.2.11 2002/09/09 21:25:23 guus Exp $ */ #include "config.h" @@ -34,14 +34,14 @@ #include #ifdef HAVE_TUNTAP - #ifdef LINUX_IF_TUN_H - #include LINUX_IF_TUN_H - #else - #include - #endif - #define DEFAULT_DEVICE "/dev/misc/net/tun" +#ifdef LINUX_IF_TUN_H +#include LINUX_IF_TUN_H #else - #define DEFAULT_DEVICE "/dev/tap0" +#include +#endif +#define DEFAULT_DEVICE "/dev/misc/net/tun" +#else +#define DEFAULT_DEVICE "/dev/tap0" #endif #include @@ -71,160 +71,137 @@ extern subnet_t mymac; */ int setup_device(void) { - struct ifreq ifr; + struct ifreq ifr; -cp - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = DEFAULT_DEVICE; + cp if(!get_config_string(lookup_config(config_tree, "Device"), &device)) + device = DEFAULT_DEVICE; - if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) + if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) #ifdef HAVE_TUNTAP - interface = netname; + interface = netname; #else - interface = rindex(device, '/')?rindex(device, '/')+1:device; + interface = rindex(device, '/') ? rindex(device, '/') + 1 : device; #endif -cp - device_fd = open(device, O_RDWR | O_NONBLOCK); - - if(device_fd < 0) - { - syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return -1; - } -cp - /* Set default MAC address for ethertap devices */ - - mymac.type = SUBNET_MAC; - mymac.net.mac.address.x[0] = 0xfe; - mymac.net.mac.address.x[1] = 0xfd; - mymac.net.mac.address.x[2] = 0x00; - mymac.net.mac.address.x[3] = 0x00; - mymac.net.mac.address.x[4] = 0x00; - mymac.net.mac.address.x[5] = 0x00; + cp device_fd = open(device, O_RDWR | O_NONBLOCK); + + if(device_fd < 0) { + syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); + return -1; + } + cp + /* Set default MAC address for ethertap devices */ + mymac.type = SUBNET_MAC; + mymac.net.mac.address.x[0] = 0xfe; + mymac.net.mac.address.x[1] = 0xfd; + mymac.net.mac.address.x[2] = 0x00; + mymac.net.mac.address.x[3] = 0x00; + mymac.net.mac.address.x[4] = 0x00; + mymac.net.mac.address.x[5] = 0x00; #ifdef HAVE_TUNTAP - /* Ok now check if this is an old ethertap or a new tun/tap thingie */ - - memset(&ifr, 0, sizeof(ifr)); -cp - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - if (interface) - strncpy(ifr.ifr_name, interface, IFNAMSIZ); -cp - if (!ioctl(device_fd, TUNSETIFF, (void *) &ifr)) - { - device_info = _("Linux tun/tap device"); - device_type = DEVICE_TYPE_TUNTAP; - strncpy(ifrname, ifr.ifr_name, IFNAMSIZ); - interface = ifrname; - } - else - if (!ioctl(device_fd, (('T'<< 8) | 202), (void *) &ifr)) - { - syslog(LOG_WARNING, _("Old ioctl() request was needed for %s"), device); - device_type = DEVICE_TYPE_TUNTAP; - device_info = _("Linux tun/tap device"); - strncpy(ifrname, ifr.ifr_name, IFNAMSIZ); - interface = ifrname; - } - else + /* Ok now check if this is an old ethertap or a new tun/tap thingie */ + + memset(&ifr, 0, sizeof(ifr)); + cp ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + if(interface) + strncpy(ifr.ifr_name, interface, IFNAMSIZ); + cp if(!ioctl(device_fd, TUNSETIFF, (void *) &ifr)) { + device_info = _("Linux tun/tap device"); + device_type = DEVICE_TYPE_TUNTAP; + strncpy(ifrname, ifr.ifr_name, IFNAMSIZ); + interface = ifrname; + } else if(!ioctl(device_fd, (('T' << 8) | 202), (void *) &ifr)) { + syslog(LOG_WARNING, _("Old ioctl() request was needed for %s"), device); + device_type = DEVICE_TYPE_TUNTAP; + device_info = _("Linux tun/tap device"); + strncpy(ifrname, ifr.ifr_name, IFNAMSIZ); + interface = ifrname; + } else #endif - { - device_info = _("Linux ethertap device"); - device_type = DEVICE_TYPE_ETHERTAP; - interface = rindex(device, '/')?rindex(device, '/')+1:device; - } - - syslog(LOG_INFO, _("%s is a %s"), device, device_info); -cp - return 0; + { + device_info = _("Linux ethertap device"); + device_type = DEVICE_TYPE_ETHERTAP; + interface = rindex(device, '/') ? rindex(device, '/') + 1 : device; + } + + syslog(LOG_INFO, _("%s is a %s"), device, device_info); + cp return 0; } void close_device(void) { -cp - close(device_fd); + cp close(device_fd); } /* read, encrypt and send data that is available through the ethertap device */ -int read_packet(vpn_packet_t *packet) +int read_packet(vpn_packet_t * packet) { - int lenin; -cp - if(device_type == DEVICE_TYPE_TUNTAP) - { - lenin = read(device_fd, packet->data, MTU); - - if(lenin <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - packet->len = lenin; - } - else /* ethertap */ - { - lenin = read(device_fd, packet->data - 2, MTU + 2); - - if(lenin <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - packet->len = lenin - 2; - } - - device_total_in += packet->len; - - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info); - } - - return 0; -cp -} + int lenin; + cp if(device_type == DEVICE_TYPE_TUNTAP) { + lenin = read(device_fd, packet->data, MTU); + + if(lenin <= 0) { + syslog(LOG_ERR, _("Error while reading from %s %s: %s"), + device_info, device, strerror(errno)); + return -1; + } + + packet->len = lenin; + } else { /* ethertap */ + + lenin = read(device_fd, packet->data - 2, MTU + 2); -int write_packet(vpn_packet_t *packet) + if(lenin <= 0) { + syslog(LOG_ERR, _("Error while reading from %s %s: %s"), + device_info, device, strerror(errno)); + return -1; + } + + packet->len = lenin - 2; + } + + device_total_in += packet->len; + + if(debug_lvl >= DEBUG_TRAFFIC) { + syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, + device_info); + } + + return 0; +cp} + +int write_packet(vpn_packet_t * packet) { -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), - packet->len, device_info); - - if(device_type == DEVICE_TYPE_TUNTAP) - { - if(write(device_fd, packet->data, packet->len) < 0) - { - syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - } - else/* ethertap */ - { - *(short int *)(packet->data - 2) = packet->len; - if(write(device_fd, packet->data - 2, packet->len + 2) < 0) - { - syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - } - - device_total_out += packet->len; -cp - return 0; + cp if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), + packet->len, device_info); + + if(device_type == DEVICE_TYPE_TUNTAP) { + if(write(device_fd, packet->data, packet->len) < 0) { + syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, + strerror(errno)); + return -1; + } + } else { /* ethertap */ + + *(short int *) (packet->data - 2) = packet->len; + if(write(device_fd, packet->data - 2, packet->len + 2) < 0) { + syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, + strerror(errno)); + return -1; + } + } + + device_total_out += packet->len; + cp return 0; } void dump_device_stats(void) { -cp - syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); - syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); - syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); -cp -} + cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); + syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); + syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); +cp} diff --git a/src/meta.c b/src/meta.c index 7a68d9d..fa475df 100644 --- a/src/meta.c +++ b/src/meta.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: meta.c,v 1.1.2.28 2002/09/09 19:39:58 guus Exp $ + $Id: meta.c,v 1.1.2.29 2002/09/09 21:24:34 guus Exp $ */ #include "config.h" @@ -39,173 +39,160 @@ #include "system.h" #include "protocol.h" -int send_meta(connection_t *c, char *buffer, int length) +int send_meta(connection_t * c, char *buffer, int length) { - char *bufp; - int outlen; - char outbuf[MAXBUFSIZE]; - cp(); - if(debug_lvl >= DEBUG_META) - syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s)"), length, - c->name, c->hostname); - - if(c->status.encryptout) - { - EVP_EncryptUpdate(c->outctx, outbuf, &outlen, buffer, length); - bufp = outbuf; - length = outlen; - } - else - bufp = buffer; - - if(write(c->socket, bufp, length) < 0) - { - syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %s"), c->name, c->hostname, strerror(errno)); - return -1; - } - cp(); - return 0; + char *bufp; + int outlen; + char outbuf[MAXBUFSIZE]; + + cp(); + + if(debug_lvl >= DEBUG_META) + syslog(LOG_DEBUG, _("Sending %d bytes of metadata to %s (%s)"), length, + c->name, c->hostname); + + if(c->status.encryptout) { + EVP_EncryptUpdate(c->outctx, outbuf, &outlen, buffer, length); + bufp = outbuf; + length = outlen; + } else + bufp = buffer; + + if(write(c->socket, bufp, length) < 0) { + syslog(LOG_ERR, _("Sending meta data to %s (%s) failed: %s"), c->name, + c->hostname, strerror(errno)); + return -1; + } + + return 0; } -void broadcast_meta(connection_t *from, char *buffer, int length) +void broadcast_meta(connection_t * from, char *buffer, int length) { - avl_node_t *node; - connection_t *c; - cp(); - for(node = connection_tree->head; node; node = node->next) - { - c = (connection_t *)node->data; - if(c != from && c->status.active) - send_meta(c, buffer, length); - } - cp(); + avl_node_t *node; + connection_t *c; + + cp(); + + for(node = connection_tree->head; node; node = node->next) { + c = (connection_t *) node->data; + + if(c != from && c->status.active) + send_meta(c, buffer, length); + } } -int receive_meta(connection_t *c) +int receive_meta(connection_t * c) { - int x, l = sizeof(x); - int oldlen, i; - int lenin, reqlen; - int decrypted = 0; - char inbuf[MAXBUFSIZE]; - cp(); - if(getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0) - { - syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s %s (%s)"), __FILE__, __LINE__, c->socket, strerror(errno), - c->name, c->hostname); - return -1; - } - if(x) - { - syslog(LOG_ERR, _("Metadata socket error for %s (%s): %s"), - c->name, c->hostname, strerror(x)); - return -1; - } - - /* Strategy: - - Read as much as possible from the TCP socket in one go. - - Decrypt it. - - Check if a full request is in the input buffer. - - If yes, process request and remove it from the buffer, - then check again. - - If not, keep stuff in buffer and exit. - */ - - lenin = read(c->socket, c->buffer + c->buflen, MAXBUFSIZE - c->buflen); - - if(lenin<=0) - { - if(lenin==0) - { - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_NOTICE, _("Connection closed by %s (%s)"), - c->name, c->hostname); - } - else - if(errno==EINTR) - return 0; - else - syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %s"), - c->name, c->hostname, strerror(errno)); - - return -1; - } - - oldlen = c->buflen; - c->buflen += lenin; - - while(lenin) - { - /* Decrypt */ - - if(c->status.decryptin && !decrypted) - { - EVP_DecryptUpdate(c->inctx, inbuf, &lenin, c->buffer + oldlen, lenin); - memcpy(c->buffer + oldlen, inbuf, lenin); - decrypted = 1; - } - - /* Are we receiving a TCPpacket? */ - - if(c->tcplen) - { - if(c->tcplen <= c->buflen) - { - receive_tcppacket(c, c->buffer, c->tcplen); - - c->buflen -= c->tcplen; - lenin -= c->tcplen; - memmove(c->buffer, c->buffer + c->tcplen, c->buflen); - oldlen = 0; - c->tcplen = 0; - continue; - } - else - { - break; - } - } - - /* Otherwise we are waiting for a request */ - - reqlen = 0; - - for(i = oldlen; i < c->buflen; i++) - { - if(c->buffer[i] == '\n') - { - c->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */ - reqlen = i + 1; - break; - } - } - - if(reqlen) - { - c->reqlen = reqlen; - if(receive_request(c)) - return -1; - - c->buflen -= reqlen; - lenin -= reqlen; - memmove(c->buffer, c->buffer + reqlen, c->buflen); - oldlen = 0; - continue; - } - else - { - break; - } - } - - if(c->buflen >= MAXBUFSIZE) - { - syslog(LOG_ERR, _("Metadata read buffer overflow for %s (%s)"), - c->name, c->hostname); - return -1; - } - - c->last_ping_time = now; - cp(); - return 0; + int x, l = sizeof(x); + int oldlen, i; + int lenin, reqlen; + int decrypted = 0; + char inbuf[MAXBUFSIZE]; + + cp(); + + if(getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &x, &l) < 0) { + syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s %s (%s)"), __FILE__, + __LINE__, c->socket, strerror(errno), c->name, c->hostname); + return -1; + } + + if(x) { + syslog(LOG_ERR, _("Metadata socket error for %s (%s): %s"), + c->name, c->hostname, strerror(x)); + return -1; + } + + /* Strategy: + - Read as much as possible from the TCP socket in one go. + - Decrypt it. + - Check if a full request is in the input buffer. + - If yes, process request and remove it from the buffer, + then check again. + - If not, keep stuff in buffer and exit. + */ + + lenin = read(c->socket, c->buffer + c->buflen, MAXBUFSIZE - c->buflen); + + if(lenin <= 0) { + if(lenin == 0) { + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_NOTICE, _("Connection closed by %s (%s)"), + c->name, c->hostname); + } else if(errno == EINTR) + return 0; + else + syslog(LOG_ERR, _("Metadata socket read error for %s (%s): %s"), + c->name, c->hostname, strerror(errno)); + + return -1; + } + + oldlen = c->buflen; + c->buflen += lenin; + + while(lenin) { + /* Decrypt */ + + if(c->status.decryptin && !decrypted) { + EVP_DecryptUpdate(c->inctx, inbuf, &lenin, c->buffer + oldlen, + lenin); + memcpy(c->buffer + oldlen, inbuf, lenin); + decrypted = 1; + } + + /* Are we receiving a TCPpacket? */ + + if(c->tcplen) { + if(c->tcplen <= c->buflen) { + receive_tcppacket(c, c->buffer, c->tcplen); + + c->buflen -= c->tcplen; + lenin -= c->tcplen; + memmove(c->buffer, c->buffer + c->tcplen, c->buflen); + oldlen = 0; + c->tcplen = 0; + continue; + } else { + break; + } + } + + /* Otherwise we are waiting for a request */ + + reqlen = 0; + + for(i = oldlen; i < c->buflen; i++) { + if(c->buffer[i] == '\n') { + c->buffer[i] = '\0'; /* replace end-of-line by end-of-string so we can use sscanf */ + reqlen = i + 1; + break; + } + } + + if(reqlen) { + c->reqlen = reqlen; + if(receive_request(c)) + return -1; + + c->buflen -= reqlen; + lenin -= reqlen; + memmove(c->buffer, c->buffer + reqlen, c->buflen); + oldlen = 0; + continue; + } else { + break; + } + } + + if(c->buflen >= MAXBUFSIZE) { + syslog(LOG_ERR, _("Metadata read buffer overflow for %s (%s)"), + c->name, c->hostname); + return -1; + } + + c->last_ping_time = now; + + return 0; } diff --git a/src/meta.h b/src/meta.h index 55b1e0c..dedabb1 100644 --- a/src/meta.h +++ b/src/meta.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: meta.h,v 1.1.2.7 2002/06/21 10:11:12 guus Exp $ + $Id: meta.h,v 1.1.2.8 2002/09/09 21:24:34 guus Exp $ */ #ifndef __TINC_META_H__ @@ -29,4 +29,4 @@ extern int send_meta(connection_t *, const char *, int); extern int broadcast_meta(connection_t *, const char *, int); extern int receive_meta(connection_t *); -#endif /* __TINC_META_H__ */ +#endif /* __TINC_META_H__ */ diff --git a/src/net.c b/src/net.c index b0bfaca..5cd3fa5 100644 --- a/src/net.c +++ b/src/net.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net.c,v 1.35.4.179 2002/09/09 19:39:58 guus Exp $ + $Id: net.c,v 1.35.4.180 2002/09/09 21:24:34 guus Exp $ */ #include "config.h" @@ -27,13 +27,13 @@ #include #include #ifdef HAVE_NETINET_IN_SYSTM_H - #include +#include #endif #ifdef HAVE_NETINET_IP_H - #include +#include #endif #ifdef HAVE_NETINET_TCP_H - #include +#include #endif #include #include @@ -87,81 +87,76 @@ time_t now = 0; void purge(void) { - avl_node_t *nnode, *nnext, *enode, *enext, *snode, *snext; - node_t *n; - edge_t *e; - subnet_t *s; - cp(); - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_DEBUG, _("Purging unreachable nodes")); - - for(nnode = node_tree->head; nnode; nnode = nnext) - { - nnext = nnode->next; - n = (node_t *)nnode->data; - - if(!n->status.reachable) - { - if(debug_lvl >= DEBUG_SCARY_THINGS) - syslog(LOG_DEBUG, _("Purging node %s (%s)"), n->name, n->hostname); - - for(snode = n->subnet_tree->head; snode; snode = snext) - { - snext = snode->next; - s = (subnet_t *)snode->data; - send_del_subnet(broadcast, s); - subnet_del(n, s); - } - - for(enode = n->edge_tree->head; enode; enode = enext) - { - enext = enode->next; - e = (edge_t *)enode->data; - send_del_edge(broadcast, e); - edge_del(e); - } - - node_del(n); - } - } - cp(); + avl_node_t *nnode, *nnext, *enode, *enext, *snode, *snext; + node_t *n; + edge_t *e; + subnet_t *s; + + cp(); + + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_DEBUG, _("Purging unreachable nodes")); + + for(nnode = node_tree->head; nnode; nnode = nnext) { + nnext = nnode->next; + n = (node_t *) nnode->data; + + if(!n->status.reachable) { + if(debug_lvl >= DEBUG_SCARY_THINGS) + syslog(LOG_DEBUG, _("Purging node %s (%s)"), n->name, + n->hostname); + + for(snode = n->subnet_tree->head; snode; snode = snext) { + snext = snode->next; + s = (subnet_t *) snode->data; + send_del_subnet(broadcast, s); + subnet_del(n, s); + } + + for(enode = n->edge_tree->head; enode; enode = enext) { + enext = enode->next; + e = (edge_t *) enode->data; + send_del_edge(broadcast, e); + edge_del(e); + } + + node_del(n); + } + } } /* put all file descriptors in an fd_set array While we're at it, purge stuff that needs to be removed. */ -void build_fdset(fd_set *fs) +void build_fdset(fd_set * fs) { - avl_node_t *node, *next; - connection_t *c; - int i; - cp(); - FD_ZERO(fs); - - for(node = connection_tree->head; node; node = next) - { - next = node->next; - c = (connection_t *)node->data; - - if(c->status.remove) - { - connection_del(c); - if(!connection_tree->head) - purge(); - } - else - FD_SET(c->socket, fs); - } - - for(i = 0; i < listen_sockets; i++) - { - FD_SET(listen_socket[i].tcp, fs); - FD_SET(listen_socket[i].udp, fs); - } - - FD_SET(device_fd, fs); - cp(); + avl_node_t *node, *next; + connection_t *c; + int i; + + cp(); + + FD_ZERO(fs); + + for(node = connection_tree->head; node; node = next) { + next = node->next; + c = (connection_t *) node->data; + + if(c->status.remove) { + connection_del(c); + if(!connection_tree->head) + purge(); + } else + FD_SET(c->socket, fs); + } + + for(i = 0; i < listen_sockets; i++) { + FD_SET(listen_socket[i].tcp, fs); + FD_SET(listen_socket[i].udp, fs); + } + + FD_SET(device_fd, fs); } /* @@ -171,45 +166,43 @@ void build_fdset(fd_set *fs) - Check if we need to retry making an outgoing connection - Deactivate the host */ -void terminate_connection(connection_t *c, int report) +void terminate_connection(connection_t * c, int report) { - cp(); - if(c->status.remove) - return; + cp(); + + if(c->status.remove) + return; - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_NOTICE, _("Closing connection with %s (%s)"), - c->name, c->hostname); + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_NOTICE, _("Closing connection with %s (%s)"), + c->name, c->hostname); - c->status.remove = 1; - c->status.active = 0; + c->status.remove = 1; + c->status.active = 0; - if(c->node) - c->node->connection = NULL; + if(c->node) + c->node->connection = NULL; - if(c->socket) - close(c->socket); + if(c->socket) + close(c->socket); - if(c->edge) - { - if(report) - send_del_edge(broadcast, c->edge); + if(c->edge) { + if(report) + send_del_edge(broadcast, c->edge); - edge_del(c->edge); + edge_del(c->edge); - /* Run MST and SSSP algorithms */ + /* Run MST and SSSP algorithms */ - graph(); - } + graph(); + } - /* Check if this was our outgoing connection */ + /* Check if this was our outgoing connection */ - if(c->outgoing) - { - retry_outgoing(c->outgoing); - c->outgoing = NULL; - } - cp(); + if(c->outgoing) { + retry_outgoing(c->outgoing); + c->outgoing = NULL; + } } /* @@ -222,106 +215,99 @@ void terminate_connection(connection_t *c, int report) */ void check_dead_connections(void) { - avl_node_t *node, *next; - connection_t *c; - cp(); - for(node = connection_tree->head; node; node = next) - { - next = node->next; - c = (connection_t *)node->data; - if(c->last_ping_time + pingtimeout < now) - { - if(c->status.active) - { - if(c->status.pinged) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_INFO, _("%s (%s) didn't respond to PING"), - c->name, c->hostname); - c->status.timeout = 1; - terminate_connection(c, 1); - } - else - { - send_ping(c); - } - } - else - { - if(c->status.remove) - { - syslog(LOG_WARNING, _("Old connection_t for %s (%s) status %04x still lingering, deleting..."), c->name, c->hostname, c->status); - connection_del(c); - continue; - } - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_WARNING, _("Timeout from %s (%s) during authentication"), - c->name, c->hostname); - terminate_connection(c, 0); - } - } - } - cp(); + avl_node_t *node, *next; + connection_t *c; + + cp(); + + for(node = connection_tree->head; node; node = next) { + next = node->next; + c = (connection_t *) node->data; + + if(c->last_ping_time + pingtimeout < now) { + if(c->status.active) { + if(c->status.pinged) { + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_INFO, _("%s (%s) didn't respond to PING"), + c->name, c->hostname); + c->status.timeout = 1; + terminate_connection(c, 1); + } else { + send_ping(c); + } + } else { + if(c->status.remove) { + syslog(LOG_WARNING, _("Old connection_t for %s (%s) status %04x still lingering, deleting..."), + c->name, c->hostname, c->status); + connection_del(c); + continue; + } + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_WARNING, _("Timeout from %s (%s) during authentication"), + c->name, c->hostname); + terminate_connection(c, 0); + } + } + } } /* check all connections to see if anything happened on their sockets */ -void check_network_activity(fd_set *f) +void check_network_activity(fd_set * f) { - connection_t *c; - avl_node_t *node; - int result, i; - int len = sizeof(result); - vpn_packet_t packet; - cp(); - if(FD_ISSET(device_fd, f)) - { - if(!read_packet(&packet)) - route_outgoing(&packet); - } - - for(node = connection_tree->head; node; node = node->next) - { - c = (connection_t *)node->data; - - if(c->status.remove) - continue; - - if(FD_ISSET(c->socket, f)) - { - if(c->status.connecting) - { - c->status.connecting = 0; - getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len); - if(!result) - finish_connecting(c); - else - { - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_DEBUG, _("Error while connecting to %s (%s): %s"), c->name, c->hostname, strerror(result)); - close(c->socket); - do_outgoing_connection(c); - continue; - } - } - if(receive_meta(c) < 0) - { - terminate_connection(c, c->status.active); - continue; - } - } - } - - for(i = 0; i < listen_sockets; i++) - { - if(FD_ISSET(listen_socket[i].udp, f)) - handle_incoming_vpn_data(listen_socket[i].udp); - if(FD_ISSET(listen_socket[i].tcp, f)) - handle_new_meta_connection(listen_socket[i].tcp); - } - cp(); + connection_t *c; + avl_node_t *node; + int result, i; + int len = sizeof(result); + vpn_packet_t packet; + + cp(); + + if(FD_ISSET(device_fd, f)) { + if(!read_packet(&packet)) + route_outgoing(&packet); + } + + for(node = connection_tree->head; node; node = node->next) { + c = (connection_t *) node->data; + + if(c->status.remove) + continue; + + if(FD_ISSET(c->socket, f)) { + if(c->status.connecting) { + c->status.connecting = 0; + getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len); + + if(!result) + finish_connecting(c); + else { + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_DEBUG, + _("Error while connecting to %s (%s): %s"), + c->name, c->hostname, strerror(result)); + close(c->socket); + do_outgoing_connection(c); + continue; + } + } + + if(receive_meta(c) < 0) { + terminate_connection(c, c->status.active); + continue; + } + } + } + + for(i = 0; i < listen_sockets; i++) { + if(FD_ISSET(listen_socket[i].udp, f)) + handle_incoming_vpn_data(listen_socket[i].udp); + + if(FD_ISSET(listen_socket[i].tcp, f)) + handle_new_meta_connection(listen_socket[i].tcp); + } } /* @@ -329,115 +315,106 @@ void check_network_activity(fd_set *f) */ void main_loop(void) { - fd_set fset; - struct timeval tv; - int r; - time_t last_ping_check; - event_t *event; - cp(); - last_ping_check = now; - - srand(now); - - for(;;) - { - now = time(NULL); - - tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */ - tv.tv_usec = 0; - - build_fdset(&fset); - - r = select(FD_SETSIZE, &fset, NULL, NULL, &tv); - - if(r < 0) - { - if(errno != EINTR && errno != EAGAIN) - { - syslog(LOG_ERR, _("Error while waiting for input: %s"), strerror(errno)); - cp_trace(); - dump_connections(); - return; - } - - continue; - } - - check_network_activity(&fset); - - if(do_purge) - { - purge(); - do_purge = 0; - } - - /* Let's check if everybody is still alive */ - - if(last_ping_check + pingtimeout < now) - { - check_dead_connections(); - last_ping_check = now; - - if(routing_mode== RMODE_SWITCH) - age_mac(); - - age_past_requests(); - - /* Should we regenerate our key? */ - - if(keyexpires < now) - { - if(debug_lvl >= DEBUG_STATUS) - syslog(LOG_INFO, _("Regenerating symmetric key")); - - RAND_pseudo_bytes(myself->key, myself->keylength); - send_key_changed(broadcast, myself); - keyexpires = now + keylifetime; - } - } - - - while((event = get_expired_event())) - { - event->handler(event->data); - free(event); - } - - if(sigalrm) - { - syslog(LOG_INFO, _("Flushing event queue")); - - while(event_tree->head) - { - event = (event_t *)event_tree->head->data; - event->handler(event->data); - event_del(event); - } - sigalrm = 0; - } - - if(sighup) - { - sighup = 0; - close_network_connections(); - exit_configuration(&config_tree); - - syslog(LOG_INFO, _("Rereading configuration file and restarting in 5 seconds...")); - sleep(5); - - init_configuration(&config_tree); - - if(read_server_config()) - { - syslog(LOG_ERR, _("Unable to reread configuration file, exitting.")); - exit(1); - } - - if(setup_network_connections()) - return; + fd_set fset; + struct timeval tv; + int r; + time_t last_ping_check; + event_t *event; + + cp(); + + last_ping_check = now; + srand(now); + + for(;;) { + now = time(NULL); + + tv.tv_sec = 1 + (rand() & 7); /* Approx. 5 seconds, randomized to prevent global synchronisation effects */ + tv.tv_usec = 0; + + build_fdset(&fset); + + r = select(FD_SETSIZE, &fset, NULL, NULL, &tv); + + if(r < 0) { + if(errno != EINTR && errno != EAGAIN) { + syslog(LOG_ERR, _("Error while waiting for input: %s"), + strerror(errno)); + cp_trace(); + dump_connections(); + return; + } + + continue; + } + + check_network_activity(&fset); + + if(do_purge) { + purge(); + do_purge = 0; + } + + /* Let's check if everybody is still alive */ + + if(last_ping_check + pingtimeout < now) { + check_dead_connections(); + last_ping_check = now; + + if(routing_mode == RMODE_SWITCH) + age_mac(); + + age_past_requests(); + + /* Should we regenerate our key? */ + + if(keyexpires < now) { + if(debug_lvl >= DEBUG_STATUS) + syslog(LOG_INFO, _("Regenerating symmetric key")); + + RAND_pseudo_bytes(myself->key, myself->keylength); + send_key_changed(broadcast, myself); + keyexpires = now + keylifetime; + } + } + + + while((event = get_expired_event())) { + event->handler(event->data); + free(event); + } + + if(sigalrm) { + syslog(LOG_INFO, _("Flushing event queue")); + + while(event_tree->head) { + event = (event_t *) event_tree->head->data; + event->handler(event->data); + event_del(event); + } + sigalrm = 0; + } + + if(sighup) { + sighup = 0; + close_network_connections(); + exit_configuration(&config_tree); + + syslog(LOG_INFO, _("Rereading configuration file and restarting in 5 seconds...")); + sleep(5); + + init_configuration(&config_tree); + + if(read_server_config()) { + syslog(LOG_ERR, + _("Unable to reread configuration file, exitting.")); + exit(1); + } + + if(setup_network_connections()) + return; - continue; - } - } - cp(); + continue; + } + } } diff --git a/src/net.h b/src/net.h index a16db15..08b0aea 100644 --- a/src/net.h +++ b/src/net.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net.h,v 1.9.4.52 2002/06/21 10:11:12 guus Exp $ + $Id: net.h,v 1.9.4.53 2002/09/09 21:24:36 guus Exp $ */ #ifndef __TINC_NET_H__ @@ -29,43 +29,40 @@ #include #ifdef HAVE_INTTYPES_H - #include +#include #endif #include "config.h" #ifdef ENABLE_JUMBOGRAMS - #define MTU 9014 /* 9000 bytes payload + 14 bytes ethernet header */ - #define MAXSIZE 9100 /* MTU + header (seqno) and trailer (CBC padding and HMAC) */ - #define MAXBUFSIZE 9100 /* Must support TCP packets of length 9000. */ +#define MTU 9014 /* 9000 bytes payload + 14 bytes ethernet header */ +#define MAXSIZE 9100 /* MTU + header (seqno) and trailer (CBC padding and HMAC) */ +#define MAXBUFSIZE 9100 /* Must support TCP packets of length 9000. */ #else - #define MTU 1514 /* 1500 bytes payload + 14 bytes ethernet header */ - #define MAXSIZE 1600 /* MTU + header (seqno) and trailer (CBC padding and HMAC) */ - #define MAXBUFSIZE 2100 /* Quite large but needed for support of keys up to 8192 bits. */ +#define MTU 1514 /* 1500 bytes payload + 14 bytes ethernet header */ +#define MAXSIZE 1600 /* MTU + header (seqno) and trailer (CBC padding and HMAC) */ +#define MAXBUFSIZE 2100 /* Quite large but needed for support of keys up to 8192 bits. */ #endif -#define MAXSOCKETS 128 /* Overkill... */ +#define MAXSOCKETS 128 /* Overkill... */ -#define MAXQUEUELENGTH 8 /* Maximum number of packats in a single queue */ +#define MAXQUEUELENGTH 8 /* Maximum number of packats in a single queue */ -typedef struct mac_t -{ - uint8_t x[6]; +typedef struct mac_t { + uint8_t x[6]; } mac_t; -typedef struct ipv4_t -{ - uint8_t x[4]; +typedef struct ipv4_t { + uint8_t x[4]; } ipv4_t; typedef struct ip_mask_t { - ipv4_t address; - ipv4_t mask; + ipv4_t address; + ipv4_t mask; } ip_mask_t; -typedef struct ipv6_t -{ - uint16_t x[8]; +typedef struct ipv6_t { + uint16_t x[8]; } ipv6_t; typedef unsigned short port_t; @@ -73,9 +70,9 @@ typedef unsigned short port_t; typedef short length_t; typedef union { - struct sockaddr sa; - struct sockaddr_in in; - struct sockaddr_in6 in6; + struct sockaddr sa; + struct sockaddr_in in; + struct sockaddr_in6 in6; } sockaddr_t; #ifdef SA_LEN @@ -85,35 +82,35 @@ typedef union { #endif typedef struct vpn_packet_t { - length_t len; /* the actual number of bytes in the `data' field */ - int priority; /* priority or TOS */ - uint32_t seqno; /* 32 bits sequence number (network byte order of course) */ - uint8_t data[MAXSIZE]; + length_t len; /* the actual number of bytes in the `data' field */ + int priority; /* priority or TOS */ + uint32_t seqno; /* 32 bits sequence number (network byte order of course) */ + uint8_t data[MAXSIZE]; } vpn_packet_t; typedef struct queue_element_t { - void *packet; - struct queue_element_t *prev; - struct queue_element_t *next; + void *packet; + struct queue_element_t *prev; + struct queue_element_t *next; } queue_element_t; typedef struct packet_queue_t { - queue_element_t *head; - queue_element_t *tail; + queue_element_t *head; + queue_element_t *tail; } packet_queue_t; typedef struct outgoing_t { - char *name; - int timeout; - struct config_t *cfg; - struct addrinfo *ai; - struct addrinfo *aip; + char *name; + int timeout; + struct config_t *cfg; + struct addrinfo *ai; + struct addrinfo *aip; } outgoing_t; typedef struct listen_socket_t { - int tcp; - int udp; - sockaddr_t sa; + int tcp; + int udp; + sockaddr_t sa; } listen_socket_t; extern int maxtimeout; @@ -123,7 +120,7 @@ extern int addressfamily; extern char *request_name[]; extern char *status_text[]; -#include "connection.h" /* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */ +#include "connection.h" /* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */ extern listen_socket_t listen_socket[MAXSOCKETS]; extern int listen_sockets; @@ -154,4 +151,4 @@ extern void terminate_connection(connection_t *, int); extern void flush_queue(struct node_t *); extern int read_rsa_public_key(struct connection_t *); -#endif /* __TINC_NET_H__ */ +#endif /* __TINC_NET_H__ */ diff --git a/src/net_packet.c b/src/net_packet.c index db31b77..00733b6 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net_packet.c,v 1.1.2.21 2002/09/09 19:39:58 guus Exp $ + $Id: net_packet.c,v 1.1.2.22 2002/09/09 21:24:41 guus Exp $ */ #include "config.h" @@ -27,13 +27,13 @@ #include #include #ifdef HAVE_NETINET_IN_SYSTM_H - #include +#include #endif #ifdef HAVE_NETINET_IP_H - #include +#include #endif #ifdef HAVE_NETINET_TCP_H - #include +#include #endif #include #include @@ -85,349 +85,353 @@ int keyexpires = 0; /* VPN packet I/O */ -void receive_udppacket(node_t *n, vpn_packet_t *inpkt) +void receive_udppacket(node_t * n, vpn_packet_t * inpkt) { - vpn_packet_t pkt1, pkt2; - vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2}; - int nextpkt = 0; - vpn_packet_t *outpkt = pkt[0]; - int outlen, outpad; - long int complen = MTU + 12; - EVP_CIPHER_CTX ctx; - char hmac[EVP_MAX_MD_SIZE]; - cp(); - /* Check the message authentication code */ - - if(myself->digest && myself->maclength) - { - inpkt->len -= myself->maclength; - HMAC(myself->digest, myself->key, myself->keylength, (char *)&inpkt->seqno, inpkt->len, hmac, NULL); - if(memcmp(hmac, (char *)&inpkt->seqno + inpkt->len, myself->maclength)) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"), n->name, n->hostname); - return; - } - } - - /* Decrypt the packet */ - - if(myself->cipher) - { - outpkt = pkt[nextpkt++]; - - EVP_DecryptInit(&ctx, myself->cipher, myself->key, myself->key + myself->cipher->key_len); - EVP_DecryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len); - EVP_DecryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad); - - outpkt->len = outlen + outpad; - inpkt = outpkt; - } - - /* Check the sequence number */ - - inpkt->len -= sizeof(inpkt->seqno); - inpkt->seqno = ntohl(inpkt->seqno); - - if(inpkt->seqno <= n->received_seqno) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Got late or replayed packet from %s (%s), seqno %d"), n->name, n->hostname, inpkt->seqno); - return; - } - - n->received_seqno = inpkt->seqno; - - if(n->received_seqno > MAX_SEQNO) - keyexpires = 0; - - /* Decompress the packet */ - - if(myself->compression) - { - outpkt = pkt[nextpkt++]; - - if(uncompress(outpkt->data, &complen, inpkt->data, inpkt->len) != Z_OK) - { - syslog(LOG_ERR, _("Error while uncompressing packet from %s (%s)"), n->name, n->hostname); - return; - } - - outpkt->len = complen; - inpkt = outpkt; - } - - receive_packet(n, inpkt); - cp(); + vpn_packet_t pkt1, pkt2; + vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 }; + int nextpkt = 0; + vpn_packet_t *outpkt = pkt[0]; + int outlen, outpad; + long int complen = MTU + 12; + EVP_CIPHER_CTX ctx; + char hmac[EVP_MAX_MD_SIZE]; + + cp(); + + /* Check the message authentication code */ + + if(myself->digest && myself->maclength) { + inpkt->len -= myself->maclength; + HMAC(myself->digest, myself->key, myself->keylength, + (char *) &inpkt->seqno, inpkt->len, hmac, NULL); + + if(memcmp(hmac, (char *) &inpkt->seqno + inpkt->len, myself->maclength)) { + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, _("Got unauthenticated packet from %s (%s)"), + n->name, n->hostname); + return; + } + } + + /* Decrypt the packet */ + + if(myself->cipher) { + outpkt = pkt[nextpkt++]; + + EVP_DecryptInit(&ctx, myself->cipher, myself->key, + myself->key + myself->cipher->key_len); + EVP_DecryptUpdate(&ctx, (char *) &outpkt->seqno, &outlen, + (char *) &inpkt->seqno, inpkt->len); + EVP_DecryptFinal(&ctx, (char *) &outpkt->seqno + outlen, &outpad); + + outpkt->len = outlen + outpad; + inpkt = outpkt; + } + + /* Check the sequence number */ + + inpkt->len -= sizeof(inpkt->seqno); + inpkt->seqno = ntohl(inpkt->seqno); + + if(inpkt->seqno <= n->received_seqno) { + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, + _("Got late or replayed packet from %s (%s), seqno %d"), + n->name, n->hostname, inpkt->seqno); + return; + } + + n->received_seqno = inpkt->seqno; + + if(n->received_seqno > MAX_SEQNO) + keyexpires = 0; + + /* Decompress the packet */ + + if(myself->compression) { + outpkt = pkt[nextpkt++]; + + if(uncompress(outpkt->data, &complen, inpkt->data, inpkt->len) != Z_OK) { + syslog(LOG_ERR, _("Error while uncompressing packet from %s (%s)"), + n->name, n->hostname); + return; + } + + outpkt->len = complen; + inpkt = outpkt; + } + + receive_packet(n, inpkt); } -void receive_tcppacket(connection_t *c, char *buffer, int len) +void receive_tcppacket(connection_t * c, char *buffer, int len) { - vpn_packet_t outpkt; - cp(); - outpkt.len = len; - memcpy(outpkt.data, buffer, len); + vpn_packet_t outpkt; + + cp(); - receive_packet(c->node, &outpkt); - cp(); + outpkt.len = len; + memcpy(outpkt.data, buffer, len); + + receive_packet(c->node, &outpkt); } -void receive_packet(node_t *n, vpn_packet_t *packet) +void receive_packet(node_t * n, vpn_packet_t * packet) { - cp(); - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Received packet of %d bytes from %s (%s)"), packet->len, n->name, n->hostname); + cp(); + + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, _("Received packet of %d bytes from %s (%s)"), + packet->len, n->name, n->hostname); - route_incoming(n, packet); - cp(); + route_incoming(n, packet); } -void send_udppacket(node_t *n, vpn_packet_t *inpkt) +void send_udppacket(node_t * n, vpn_packet_t * inpkt) { - vpn_packet_t pkt1, pkt2; - vpn_packet_t *pkt[] = {&pkt1, &pkt2, &pkt1, &pkt2}; - int nextpkt = 0; - vpn_packet_t *outpkt; - int origlen; - int outlen, outpad; - long int complen = MTU + 12; - EVP_CIPHER_CTX ctx; - vpn_packet_t *copy; - static int priority = 0; - int origpriority; - int sock; - cp(); - /* Make sure we have a valid key */ + vpn_packet_t pkt1, pkt2; + vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 }; + int nextpkt = 0; + vpn_packet_t *outpkt; + int origlen; + int outlen, outpad; + long int complen = MTU + 12; + EVP_CIPHER_CTX ctx; + vpn_packet_t *copy; + static int priority = 0; + int origpriority; + int sock; - if(!n->status.validkey) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_INFO, _("No valid key known yet for %s (%s), queueing packet"), - n->name, n->hostname); + cp(); - /* Since packet is on the stack of handle_tap_input(), - we have to make a copy of it first. */ + /* Make sure we have a valid key */ - copy = xmalloc(sizeof(vpn_packet_t)); - memcpy(copy, inpkt, sizeof(vpn_packet_t)); + if(!n->status.validkey) { + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_INFO, + _("No valid key known yet for %s (%s), queueing packet"), + n->name, n->hostname); - list_insert_tail(n->queue, copy); + /* Since packet is on the stack of handle_tap_input(), we have to make a copy of it first. */ - if(n->queue->count > MAXQUEUELENGTH) - list_delete_head(n->queue); + copy = xmalloc(sizeof(vpn_packet_t)); + memcpy(copy, inpkt, sizeof(vpn_packet_t)); - if(!n->status.waitingforkey) - send_req_key(n->nexthop->connection, myself, n); + list_insert_tail(n->queue, copy); - n->status.waitingforkey = 1; + if(n->queue->count > MAXQUEUELENGTH) + list_delete_head(n->queue); - return; - } + if(!n->status.waitingforkey) + send_req_key(n->nexthop->connection, myself, n); - origlen = inpkt->len; - origpriority = inpkt->priority; + n->status.waitingforkey = 1; - /* Compress the packet */ + return; + } - if(n->compression) - { - outpkt = pkt[nextpkt++]; + origlen = inpkt->len; + origpriority = inpkt->priority; - if(compress2(outpkt->data, &complen, inpkt->data, inpkt->len, n->compression) != Z_OK) - { - syslog(LOG_ERR, _("Error while compressing packet to %s (%s)"), n->name, n->hostname); - return; - } - - outpkt->len = complen; - inpkt = outpkt; - } + /* Compress the packet */ - /* Add sequence number */ + if(n->compression) { + outpkt = pkt[nextpkt++]; - inpkt->seqno = htonl(++(n->sent_seqno)); - inpkt->len += sizeof(inpkt->seqno); + if(compress2 + (outpkt->data, &complen, inpkt->data, inpkt->len, + n->compression) != Z_OK) { + syslog(LOG_ERR, _("Error while compressing packet to %s (%s)"), + n->name, n->hostname); + return; + } - /* Encrypt the packet */ + outpkt->len = complen; + inpkt = outpkt; + } - if(n->cipher) - { - outpkt = pkt[nextpkt++]; + /* Add sequence number */ - EVP_EncryptInit(&ctx, n->cipher, n->key, n->key + n->cipher->key_len); - EVP_EncryptUpdate(&ctx, (char *)&outpkt->seqno, &outlen, (char *)&inpkt->seqno, inpkt->len); - EVP_EncryptFinal(&ctx, (char *)&outpkt->seqno + outlen, &outpad); + inpkt->seqno = htonl(++(n->sent_seqno)); + inpkt->len += sizeof(inpkt->seqno); - outpkt->len = outlen + outpad; - inpkt = outpkt; - } + /* Encrypt the packet */ - /* Add the message authentication code */ + if(n->cipher) { + outpkt = pkt[nextpkt++]; - if(n->digest && n->maclength) - { - HMAC(n->digest, n->key, n->keylength, (char *)&inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len, &outlen); - inpkt->len += n->maclength; - } + EVP_EncryptInit(&ctx, n->cipher, n->key, n->key + n->cipher->key_len); + EVP_EncryptUpdate(&ctx, (char *) &outpkt->seqno, &outlen, + (char *) &inpkt->seqno, inpkt->len); + EVP_EncryptFinal(&ctx, (char *) &outpkt->seqno + outlen, &outpad); - /* Determine which socket we have to use */ + outpkt->len = outlen + outpad; + inpkt = outpkt; + } - for(sock = 0; sock < listen_sockets; sock++) - if(n->address.sa.sa_family == listen_socket[sock].sa.sa.sa_family) - break; + /* Add the message authentication code */ - if(sock >= listen_sockets) - sock = 0; /* If none is available, just use the first and hope for the best. */ - - /* Send the packet */ + if(n->digest && n->maclength) { + HMAC(n->digest, n->key, n->keylength, (char *) &inpkt->seqno, + inpkt->len, (char *) &inpkt->seqno + inpkt->len, &outlen); + inpkt->len += n->maclength; + } + + /* Determine which socket we have to use */ + + for(sock = 0; sock < listen_sockets; sock++) + if(n->address.sa.sa_family == listen_socket[sock].sa.sa.sa_family) + break; + + if(sock >= listen_sockets) + sock = 0; /* If none is available, just use the first and hope for the best. */ + + /* Send the packet */ #if defined(SOL_IP) && defined(IP_TOS) - if(priorityinheritance && origpriority != priority && listen_socket[sock].sa.sa.sa_family == AF_INET) - { - priority = origpriority; - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Setting outgoing packet priority to %d"), priority); - if(setsockopt(sock, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */ - syslog(LOG_ERR, _("System call `%s' failed: %s"), "setsockopt", strerror(errno)); - } + if(priorityinheritance && origpriority != priority + && listen_socket[sock].sa.sa.sa_family == AF_INET) { + priority = origpriority; + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, _("Setting outgoing packet priority to %d"), + priority); + if(setsockopt(sock, SOL_IP, IP_TOS, &priority, sizeof(priority))) /* SO_PRIORITY doesn't seem to work */ + syslog(LOG_ERR, _("System call `%s' failed: %s"), "setsockopt", + strerror(errno)); + } #endif - if((sendto(listen_socket[sock].udp, (char *)&inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa))) < 0) - { - syslog(LOG_ERR, _("Error sending packet to %s (%s): %s"), - n->name, n->hostname, strerror(errno)); - return; - } - - inpkt->len = origlen; - cp(); + if((sendto(listen_socket[sock].udp, (char *) &inpkt->seqno, inpkt->len, 0, &(n->address.sa), SALEN(n->address.sa))) < 0) { + syslog(LOG_ERR, _("Error sending packet to %s (%s): %s"), n->name, + n->hostname, strerror(errno)); + return; + } + + inpkt->len = origlen; } /* send a packet to the given vpn ip. */ -void send_packet(node_t *n, vpn_packet_t *packet) +void send_packet(node_t * n, vpn_packet_t * packet) { - node_t *via; - cp(); - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_ERR, _("Sending packet of %d bytes to %s (%s)"), - packet->len, n->name, n->hostname); - - if(n == myself) - { - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_NOTICE, _("Packet is looping back to us!")); - } - - return; - } - - if(!n->status.reachable) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_INFO, _("Node %s (%s) is not reachable"), - n->name, n->hostname); - return; - } - - via = (n->via == myself)?n->nexthop:n->via; - - if(via != n && debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_ERR, _("Sending packet to %s via %s (%s)"), - n->name, via->name, n->via->hostname); - - if((myself->options | via->options) & OPTION_TCPONLY) - { - if(send_tcppacket(via->connection, packet)) - terminate_connection(via->connection, 1); - } - else - send_udppacket(via, packet); + node_t *via; + + cp(); + + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_ERR, _("Sending packet of %d bytes to %s (%s)"), + packet->len, n->name, n->hostname); + + if(n == myself) { + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_NOTICE, _("Packet is looping back to us!")); + + return; + } + + if(!n->status.reachable) { + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_INFO, _("Node %s (%s) is not reachable"), + n->name, n->hostname); + + return; + } + + via = (n->via == myself) ? n->nexthop : n->via; + + if(via != n && debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_ERR, _("Sending packet to %s via %s (%s)"), + n->name, via->name, n->via->hostname); + + if((myself->options | via->options) & OPTION_TCPONLY) { + if(send_tcppacket(via->connection, packet)) + terminate_connection(via->connection, 1); + } else + send_udppacket(via, packet); } /* Broadcast a packet using the minimum spanning tree */ -void broadcast_packet(node_t *from, vpn_packet_t *packet) +void broadcast_packet(node_t * from, vpn_packet_t * packet) { - avl_node_t *node; - connection_t *c; - cp(); - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_INFO, _("Broadcasting packet of %d bytes from %s (%s)"), - packet->len, from->name, from->hostname); - - for(node = connection_tree->head; node; node = node->next) - { - c = (connection_t *)node->data; - if(c->status.active && c->status.mst && c != from->nexthop->connection) - send_packet(c->node, packet); - } - cp(); + avl_node_t *node; + connection_t *c; + + cp(); + + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_INFO, _("Broadcasting packet of %d bytes from %s (%s)"), + packet->len, from->name, from->hostname); + + for(node = connection_tree->head; node; node = node->next) { + c = (connection_t *) node->data; + + if(c->status.active && c->status.mst && c != from->nexthop->connection) + send_packet(c->node, packet); + } } -void flush_queue(node_t *n) +void flush_queue(node_t * n) { - list_node_t *node, *next; - cp(); - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_INFO, _("Flushing queue for %s (%s)"), n->name, n->hostname); - - for(node = n->queue->head; node; node = next) - { - next = node->next; - send_udppacket(n, (vpn_packet_t *)node->data); - list_delete_node(n->queue, node); - } - cp(); + list_node_t *node, *next; + + cp(); + + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_INFO, _("Flushing queue for %s (%s)"), n->name, n->hostname); + + for(node = n->queue->head; node; node = next) { + next = node->next; + send_udppacket(n, (vpn_packet_t *) node->data); + list_delete_node(n->queue, node); + } } void handle_incoming_vpn_data(int sock) { - vpn_packet_t pkt; - int x, l = sizeof(x); - char *hostname; - sockaddr_t from; - socklen_t fromlen = sizeof(from); - node_t *n; - cp(); - if(getsockopt(sock, SOL_SOCKET, SO_ERROR, &x, &l) < 0) - { - syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s"), - __FILE__, __LINE__, sock, strerror(errno)); - cp_trace(); - exit(1); - } - if(x) - { - syslog(LOG_ERR, _("Incoming data socket error: %s"), strerror(x)); - return; - } - - pkt.len = recvfrom(sock, (char *)&pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); - - if(pkt.len <= 0) - { - syslog(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno)); - return; - } - - sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */ - - n = lookup_node_udp(&from); - - if(!n) - { - hostname = sockaddr2hostname(&from); - syslog(LOG_WARNING, _("Received UDP packet from unknown source %s"), hostname); - free(hostname); - return; - } - - if(n->connection) - n->connection->last_ping_time = now; - - receive_udppacket(n, &pkt); - cp(); + vpn_packet_t pkt; + int x, l = sizeof(x); + char *hostname; + sockaddr_t from; + socklen_t fromlen = sizeof(from); + node_t *n; + + cp(); + + if(getsockopt(sock, SOL_SOCKET, SO_ERROR, &x, &l) < 0) { + syslog(LOG_ERR, _("This is a bug: %s:%d: %d:%s"), + __FILE__, __LINE__, sock, strerror(errno)); + cp_trace(); + exit(1); + } + + if(x) { + syslog(LOG_ERR, _("Incoming data socket error: %s"), strerror(x)); + return; + } + + pkt.len = recvfrom(sock, (char *) &pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen); + + if(pkt.len <= 0) { + syslog(LOG_ERR, _("Receiving packet failed: %s"), strerror(errno)); + return; + } + + sockaddrunmap(&from); /* Some braindead IPv6 implementations do stupid things. */ + + n = lookup_node_udp(&from); + + if(!n) { + hostname = sockaddr2hostname(&from); + syslog(LOG_WARNING, _("Received UDP packet from unknown source %s"), + hostname); + free(hostname); + return; + } + + if(n->connection) + n->connection->last_ping_time = now; + + receive_udppacket(n, &pkt); } diff --git a/src/net_setup.c b/src/net_setup.c index 0fe5068..eee0560 100644 --- a/src/net_setup.c +++ b/src/net_setup.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net_setup.c,v 1.1.2.24 2002/09/09 19:39:58 guus Exp $ + $Id: net_setup.c,v 1.1.2.25 2002/09/09 21:24:41 guus Exp $ */ #include "config.h" @@ -27,13 +27,13 @@ #include #include #ifdef HAVE_NETINET_IN_SYSTM_H - #include +#include #endif #ifdef HAVE_NETINET_IP_H - #include +#include #endif #ifdef HAVE_NETINET_TCP_H - #include +#include #endif #include #include @@ -77,148 +77,152 @@ char *myport; -int read_rsa_public_key(connection_t *c) +int read_rsa_public_key(connection_t * c) { - FILE *fp; - char *fname; - char *key; - cp(); - if(!c->rsa_key) - c->rsa_key = RSA_new(); - - /* First, check for simple PublicKey statement */ - - if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) - { - BN_hex2bn(&c->rsa_key->n, key); - BN_hex2bn(&c->rsa_key->e, "FFFF"); - free(key); - return 0; - } - - /* Else, check for PublicKeyFile statement and read it */ - - if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname)) - { - if(is_safe_path(fname)) - { - fp = fopen(fname, "r"); - if(!fp) - { - syslog(LOG_ERR, _("Error reading RSA public key file `%s': %s"), - fname, strerror(errno)); - free(fname); - return -1; - } - free(fname); - c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL); - fclose(fp); - if(c->rsa_key) - return 0; /* Woohoo. */ - - /* If it fails, try PEM_read_RSA_PUBKEY. */ - fp = fopen(fname, "r"); - if(!fp) - { - syslog(LOG_ERR, _("Error reading RSA public key file `%s': %s"), - fname, strerror(errno)); - free(fname); - return -1; - } - free(fname); - c->rsa_key = PEM_read_RSA_PUBKEY(fp, &c->rsa_key, NULL, NULL); - fclose(fp); - if(c->rsa_key) - return 0; - - syslog(LOG_ERR, _("Reading RSA public key file `%s' failed: %s"), - fname, strerror(errno)); - return -1; - } - else - { - free(fname); - return -1; - } - } - - /* Else, check if a harnessed public key is in the config file */ - - asprintf(&fname, "%s/hosts/%s", confbase, c->name); - fp = fopen(fname, "r"); - - if(fp) - { - c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL); - fclose(fp); - } - - free(fname); - - if(c->rsa_key) - return 0; - - /* Try again with PEM_read_RSA_PUBKEY. */ - - asprintf(&fname, "%s/hosts/%s", confbase, c->name); - fp = fopen(fname, "r"); - - if(fp) - { - c->rsa_key = PEM_read_RSA_PUBKEY(fp, &c->rsa_key, NULL, NULL); - fclose(fp); - } - - free(fname); - - if(c->rsa_key) - return 0; - - syslog(LOG_ERR, _("No public key for %s specified!"), c->name); - return -1; + FILE *fp; + char *fname; + char *key; + + cp(); + + if(!c->rsa_key) + c->rsa_key = RSA_new(); + + /* First, check for simple PublicKey statement */ + + if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) { + BN_hex2bn(&c->rsa_key->n, key); + BN_hex2bn(&c->rsa_key->e, "FFFF"); + free(key); + return 0; + } + + /* Else, check for PublicKeyFile statement and read it */ + + if(get_config_string + (lookup_config(c->config_tree, "PublicKeyFile"), &fname)) { + if(is_safe_path(fname)) { + fp = fopen(fname, "r"); + + if(!fp) { + syslog(LOG_ERR, _("Error reading RSA public key file `%s': %s"), + fname, strerror(errno)); + free(fname); + return -1; + } + + free(fname); + c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL); + fclose(fp); + + if(c->rsa_key) + return 0; /* Woohoo. */ + + /* If it fails, try PEM_read_RSA_PUBKEY. */ + fp = fopen(fname, "r"); + + if(!fp) { + syslog(LOG_ERR, _("Error reading RSA public key file `%s': %s"), + fname, strerror(errno)); + free(fname); + return -1; + } + + free(fname); + c->rsa_key = PEM_read_RSA_PUBKEY(fp, &c->rsa_key, NULL, NULL); + fclose(fp); + + if(c->rsa_key) + return 0; + + syslog(LOG_ERR, _("Reading RSA public key file `%s' failed: %s"), + fname, strerror(errno)); + return -1; + } else { + free(fname); + return -1; + } + } + + /* Else, check if a harnessed public key is in the config file */ + + asprintf(&fname, "%s/hosts/%s", confbase, c->name); + fp = fopen(fname, "r"); + + if(fp) { + c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL); + fclose(fp); + } + + free(fname); + + if(c->rsa_key) + return 0; + + /* Try again with PEM_read_RSA_PUBKEY. */ + + asprintf(&fname, "%s/hosts/%s", confbase, c->name); + fp = fopen(fname, "r"); + + if(fp) { + c->rsa_key = PEM_read_RSA_PUBKEY(fp, &c->rsa_key, NULL, NULL); + fclose(fp); + } + + free(fname); + + if(c->rsa_key) + return 0; + + syslog(LOG_ERR, _("No public key for %s specified!"), c->name); + + return -1; } int read_rsa_private_key(void) { - FILE *fp; - char *fname, *key; - cp(); - if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) - { - myself->connection->rsa_key = RSA_new(); - BN_hex2bn(&myself->connection->rsa_key->d, key); - BN_hex2bn(&myself->connection->rsa_key->e, "FFFF"); - free(key); - return 0; - } - - if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) - asprintf(&fname, "%s/rsa_key.priv", confbase); - - if(is_safe_path(fname)) - { - fp = fopen(fname, "r"); - if(!fp) - { - syslog(LOG_ERR, _("Error reading RSA private key file `%s': %s"), - fname, strerror(errno)); - free(fname); - return -1; - } - free(fname); - myself->connection->rsa_key = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); - fclose(fp); - if(!myself->connection->rsa_key) - { - syslog(LOG_ERR, _("Reading RSA private key file `%s' failed: %s"), - fname, strerror(errno)); - return -1; - } - return 0; - } - - free(fname); - return -1; + FILE *fp; + char *fname, *key; + + cp(); + + if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) { + myself->connection->rsa_key = RSA_new(); + BN_hex2bn(&myself->connection->rsa_key->d, key); + BN_hex2bn(&myself->connection->rsa_key->e, "FFFF"); + free(key); + return 0; + } + + if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) + asprintf(&fname, "%s/rsa_key.priv", confbase); + + if(is_safe_path(fname)) { + fp = fopen(fname, "r"); + + if(!fp) { + syslog(LOG_ERR, _("Error reading RSA private key file `%s': %s"), + fname, strerror(errno)); + free(fname); + return -1; + } + + free(fname); + myself->connection->rsa_key = + PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL); + fclose(fp); + + if(!myself->connection->rsa_key) { + syslog(LOG_ERR, _("Reading RSA private key file `%s' failed: %s"), + fname, strerror(errno)); + return -1; + } + + return 0; + } + + free(fname); + return -1; } /* @@ -226,313 +230,289 @@ int read_rsa_private_key(void) */ int setup_myself(void) { - config_t *cfg; - subnet_t *subnet; - char *name, *hostname, *mode, *afname, *cipher, *digest; - char *address = NULL; - struct addrinfo hint, *ai, *aip; - int choice, err; - cp(); - myself = new_node(); - myself->connection = new_connection(); - init_configuration(&myself->connection->config_tree); - - asprintf(&myself->hostname, _("MYSELF")); - asprintf(&myself->connection->hostname, _("MYSELF")); - - myself->connection->options = 0; - myself->connection->protocol_version = PROT_CURRENT; - - if(!get_config_string(lookup_config(config_tree, "Name"), &name)) /* Not acceptable */ - { - syslog(LOG_ERR, _("Name for tinc daemon required!")); - return -1; - } - - if(check_id(name)) - { - syslog(LOG_ERR, _("Invalid name for myself!")); - free(name); - return -1; - } - - myself->name = name; - myself->connection->name = xstrdup(name); - - cp(); - if(read_rsa_private_key()) - return -1; - - if(read_connection_config(myself->connection)) - { - syslog(LOG_ERR, _("Cannot open host configuration file for myself!")); - return -1; - } - - if(read_rsa_public_key(myself->connection)) - return -1; - cp(); - - if(!get_config_string(lookup_config(myself->connection->config_tree, "Port"), &myport)) - asprintf(&myport, "655"); - -/* Read in all the subnets specified in the host configuration file */ - - cfg = lookup_config(myself->connection->config_tree, "Subnet"); - - while(cfg) - { - if(!get_config_subnet(cfg, &subnet)) - return -1; - - subnet_add(myself, subnet); - - cfg = lookup_config_next(myself->connection->config_tree, cfg); - } - - cp(); - /* Check some options */ - - if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice)) - if(choice) - myself->options |= OPTION_INDIRECT; - - if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice)) - if(choice) - myself->options |= OPTION_TCPONLY; - - if(get_config_bool(lookup_config(myself->connection->config_tree, "IndirectData"), &choice)) - if(choice) - myself->options |= OPTION_INDIRECT; - - if(get_config_bool(lookup_config(myself->connection->config_tree, "TCPOnly"), &choice)) - if(choice) - myself->options |= OPTION_TCPONLY; - - if(myself->options & OPTION_TCPONLY) - myself->options |= OPTION_INDIRECT; - - if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) - { - if(!strcasecmp(mode, "router")) - routing_mode = RMODE_ROUTER; - else if (!strcasecmp(mode, "switch")) - routing_mode = RMODE_SWITCH; - else if (!strcasecmp(mode, "hub")) - routing_mode = RMODE_HUB; - else - { - syslog(LOG_ERR, _("Invalid routing mode!")); - return -1; - } - free(mode); - } - else - routing_mode = RMODE_ROUTER; - - get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance); + config_t *cfg; + subnet_t *subnet; + char *name, *hostname, *mode, *afname, *cipher, *digest; + char *address = NULL; + struct addrinfo hint, *ai, *aip; + int choice, err; + + cp(); + + myself = new_node(); + myself->connection = new_connection(); + init_configuration(&myself->connection->config_tree); + + asprintf(&myself->hostname, _("MYSELF")); + asprintf(&myself->connection->hostname, _("MYSELF")); + + myself->connection->options = 0; + myself->connection->protocol_version = PROT_CURRENT; + + if(!get_config_string(lookup_config(config_tree, "Name"), &name)) { /* Not acceptable */ + syslog(LOG_ERR, _("Name for tinc daemon required!")); + return -1; + } + + if(check_id(name)) { + syslog(LOG_ERR, _("Invalid name for myself!")); + free(name); + return -1; + } + + myself->name = name; + myself->connection->name = xstrdup(name); + + if(read_rsa_private_key()) + return -1; + + if(read_connection_config(myself->connection)) { + syslog(LOG_ERR, _("Cannot open host configuration file for myself!")); + return -1; + } + + if(read_rsa_public_key(myself->connection)) + return -1; + + if(!get_config_string + (lookup_config(myself->connection->config_tree, "Port"), &myport)) + asprintf(&myport, "655"); + + /* Read in all the subnets specified in the host configuration file */ + + cfg = lookup_config(myself->connection->config_tree, "Subnet"); + + while(cfg) { + if(!get_config_subnet(cfg, &subnet)) + return -1; + + subnet_add(myself, subnet); + + cfg = lookup_config_next(myself->connection->config_tree, cfg); + } + + /* Check some options */ + + if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice)) + if(choice) + myself->options |= OPTION_INDIRECT; + + if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice)) + if(choice) + myself->options |= OPTION_TCPONLY; + + if(get_config_bool + (lookup_config(myself->connection->config_tree, "IndirectData"), + &choice)) + if(choice) + myself->options |= OPTION_INDIRECT; + + if(get_config_bool + (lookup_config(myself->connection->config_tree, "TCPOnly"), &choice)) + if(choice) + myself->options |= OPTION_TCPONLY; + + if(myself->options & OPTION_TCPONLY) + myself->options |= OPTION_INDIRECT; + + if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) { + if(!strcasecmp(mode, "router")) + routing_mode = RMODE_ROUTER; + else if(!strcasecmp(mode, "switch")) + routing_mode = RMODE_SWITCH; + else if(!strcasecmp(mode, "hub")) + routing_mode = RMODE_HUB; + else { + syslog(LOG_ERR, _("Invalid routing mode!")); + return -1; + } + free(mode); + } else + routing_mode = RMODE_ROUTER; + + get_config_bool(lookup_config(config_tree, "PriorityInheritance"), + &priorityinheritance); #if !defined(SOL_IP) || !defined(IP_TOS) - if(priorityinheritance) - syslog(LOG_WARNING, _("PriorityInheritance not supported on this platform")); + if(priorityinheritance) + syslog(LOG_WARNING, _("PriorityInheritance not supported on this platform")); #endif - if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire)) - macexpire= 600; - - if(get_config_int(lookup_config(myself->connection->config_tree, "MaxTimeout"), &maxtimeout)) - { - if(maxtimeout <= 0) - { - syslog(LOG_ERR, _("Bogus maximum timeout!")); - return -1; - } - } - else - maxtimeout = 900; - - if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) - { - if(!strcasecmp(afname, "IPv4")) - addressfamily = AF_INET; - else if (!strcasecmp(afname, "IPv6")) - addressfamily = AF_INET6; - else if (!strcasecmp(afname, "any")) - addressfamily = AF_UNSPEC; - else - { - syslog(LOG_ERR, _("Invalid address family!")); - return -1; - } - free(afname); - } - else - addressfamily = AF_INET; - - get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames); - cp(); - /* Generate packet encryption key */ - - if(get_config_string(lookup_config(myself->connection->config_tree, "Cipher"), &cipher)) - { - if(!strcasecmp(cipher, "none")) - { - myself->cipher = NULL; - } - else - { - myself->cipher = EVP_get_cipherbyname(cipher); - - if(!myself->cipher) - { - syslog(LOG_ERR, _("Unrecognized cipher type!")); - return -1; - } - } - } - else - myself->cipher = EVP_bf_cbc(); - - if(myself->cipher) - myself->keylength = myself->cipher->key_len + myself->cipher->iv_len; - else - myself->keylength = 1; - - myself->connection->outcipher = EVP_bf_ofb(); - - myself->key = (char *)xmalloc(myself->keylength); - RAND_pseudo_bytes(myself->key, myself->keylength); - - if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) - keylifetime = 3600; - - keyexpires = now + keylifetime; - - /* Check if we want to use message authentication codes... */ - - if(get_config_string(lookup_config(myself->connection->config_tree, "Digest"), &digest)) - { - if(!strcasecmp(digest, "none")) - { - myself->digest = NULL; - } - else - { - myself->digest = EVP_get_digestbyname(digest); - - if(!myself->digest) - { - syslog(LOG_ERR, _("Unrecognized digest type!")); - return -1; - } - } - } - else - myself->digest = EVP_sha1(); - - myself->connection->outdigest = EVP_sha1(); - - if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength)) - { - if(myself->digest) - { - if(myself->maclength > myself->digest->md_size) - { - syslog(LOG_ERR, _("MAC length exceeds size of digest!")); - return -1; - } - else if (myself->maclength < 0) - { - syslog(LOG_ERR, _("Bogus MAC length!")); - return -1; - } - } - } - else - myself->maclength = 4; - - myself->connection->outmaclength = 0; - - /* Compression */ - - if(get_config_int(lookup_config(myself->connection->config_tree, "Compression"), &myself->compression)) - { - if(myself->compression < 0 || myself->compression > 9) - { - syslog(LOG_ERR, _("Bogus compression level!")); - return -1; - } - } - else - myself->compression = 0; - - myself->connection->outcompression = 0; - cp(); - /* Done */ - - myself->nexthop = myself; - myself->via = myself; - myself->status.active = 1; - myself->status.reachable = 1; - node_add(myself); - - graph(); - - cp(); - /* Open sockets */ - - memset(&hint, 0, sizeof(hint)); - - get_config_string(lookup_config(config_tree, "BindToAddress"), &address); - - hint.ai_family = addressfamily; - hint.ai_socktype = SOCK_STREAM; - hint.ai_protocol = IPPROTO_TCP; - hint.ai_flags = AI_PASSIVE; - - err = getaddrinfo(address, myport, &hint, &ai); - - if(err || !ai) - { - syslog(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", gai_strerror(err)); - return -1; - } - - listen_sockets = 0; - - for(aip = ai; aip; aip = aip->ai_next) - { - listen_socket[listen_sockets].tcp = setup_listen_socket((sockaddr_t *)aip->ai_addr); - - if(listen_socket[listen_sockets].tcp < 0) - continue; - - listen_socket[listen_sockets].udp = setup_vpn_in_socket((sockaddr_t *)aip->ai_addr); - - if(listen_socket[listen_sockets].udp < 0) - continue; - - if(debug_lvl >= DEBUG_CONNECTIONS) - { - hostname = sockaddr2hostname((sockaddr_t *)aip->ai_addr); - syslog(LOG_NOTICE, _("Listening on %s"), hostname); - free(hostname); + if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire)) + macexpire = 600; + + if(get_config_int + (lookup_config(myself->connection->config_tree, "MaxTimeout"), + &maxtimeout)) { + if(maxtimeout <= 0) { + syslog(LOG_ERR, _("Bogus maximum timeout!")); + return -1; + } + } else + maxtimeout = 900; + + if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) { + if(!strcasecmp(afname, "IPv4")) + addressfamily = AF_INET; + else if(!strcasecmp(afname, "IPv6")) + addressfamily = AF_INET6; + else if(!strcasecmp(afname, "any")) + addressfamily = AF_UNSPEC; + else { + syslog(LOG_ERR, _("Invalid address family!")); + return -1; + } + free(afname); + } else + addressfamily = AF_INET; + + get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames); + + /* Generate packet encryption key */ + + if(get_config_string + (lookup_config(myself->connection->config_tree, "Cipher"), &cipher)) { + if(!strcasecmp(cipher, "none")) { + myself->cipher = NULL; + } else { + myself->cipher = EVP_get_cipherbyname(cipher); + + if(!myself->cipher) { + syslog(LOG_ERR, _("Unrecognized cipher type!")); + return -1; + } + } + } else + myself->cipher = EVP_bf_cbc(); + + if(myself->cipher) + myself->keylength = myself->cipher->key_len + myself->cipher->iv_len; + else + myself->keylength = 1; + + myself->connection->outcipher = EVP_bf_ofb(); + + myself->key = (char *) xmalloc(myself->keylength); + RAND_pseudo_bytes(myself->key, myself->keylength); + + if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) + keylifetime = 3600; + + keyexpires = now + keylifetime; + + /* Check if we want to use message authentication codes... */ + + if(get_config_string + (lookup_config(myself->connection->config_tree, "Digest"), &digest)) { + if(!strcasecmp(digest, "none")) { + myself->digest = NULL; + } else { + myself->digest = EVP_get_digestbyname(digest); + + if(!myself->digest) { + syslog(LOG_ERR, _("Unrecognized digest type!")); + return -1; + } + } + } else + myself->digest = EVP_sha1(); + + myself->connection->outdigest = EVP_sha1(); + + if(get_config_int + (lookup_config(myself->connection->config_tree, "MACLength"), + &myself->maclength)) { + if(myself->digest) { + if(myself->maclength > myself->digest->md_size) { + syslog(LOG_ERR, _("MAC length exceeds size of digest!")); + return -1; + } else if(myself->maclength < 0) { + syslog(LOG_ERR, _("Bogus MAC length!")); + return -1; + } + } + } else + myself->maclength = 4; + + myself->connection->outmaclength = 0; + + /* Compression */ + + if(get_config_int + (lookup_config(myself->connection->config_tree, "Compression"), + &myself->compression)) { + if(myself->compression < 0 || myself->compression > 9) { + syslog(LOG_ERR, _("Bogus compression level!")); + return -1; + } + } else + myself->compression = 0; + + myself->connection->outcompression = 0; + + /* Done */ + + myself->nexthop = myself; + myself->via = myself; + myself->status.active = 1; + myself->status.reachable = 1; + node_add(myself); + + graph(); + + /* Open sockets */ + + memset(&hint, 0, sizeof(hint)); + + get_config_string(lookup_config(config_tree, "BindToAddress"), &address); + + hint.ai_family = addressfamily; + hint.ai_socktype = SOCK_STREAM; + hint.ai_protocol = IPPROTO_TCP; + hint.ai_flags = AI_PASSIVE; + + err = getaddrinfo(address, myport, &hint, &ai); + + if(err || !ai) { + syslog(LOG_ERR, _("System call `%s' failed: %s"), "getaddrinfo", + gai_strerror(err)); + return -1; + } + + listen_sockets = 0; + + for(aip = ai; aip; aip = aip->ai_next) { + listen_socket[listen_sockets].tcp = + setup_listen_socket((sockaddr_t *) aip->ai_addr); + + if(listen_socket[listen_sockets].tcp < 0) + continue; + + listen_socket[listen_sockets].udp = + setup_vpn_in_socket((sockaddr_t *) aip->ai_addr); + + if(listen_socket[listen_sockets].udp < 0) + continue; + + if(debug_lvl >= DEBUG_CONNECTIONS) { + hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr); + syslog(LOG_NOTICE, _("Listening on %s"), hostname); + free(hostname); + } + + listen_socket[listen_sockets].sa.sa = *aip->ai_addr; + listen_sockets++; } - listen_socket[listen_sockets].sa.sa = *aip->ai_addr; - listen_sockets++; - } - - freeaddrinfo(ai); - - if(listen_sockets) - syslog(LOG_NOTICE, _("Ready")); - else - { - syslog(LOG_ERR, _("Unable to create any listening socket!")); - return -1; - } - cp(); - return 0; + freeaddrinfo(ai); + + if(listen_sockets) + syslog(LOG_NOTICE, _("Ready")); + else { + syslog(LOG_ERR, _("Unable to create any listening socket!")); + return -1; + } + + return 0; } /* @@ -540,48 +520,47 @@ int setup_myself(void) */ int setup_network_connections(void) { - char *envp[4]; - int i; - cp(); - now = time(NULL); - - init_connections(); - init_subnets(); - init_nodes(); - init_edges(); - init_events(); - init_requests(); - - if(get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout)) - { - if(pingtimeout < 1) - { - pingtimeout = 86400; - } - } - else - pingtimeout = 60; - - if(setup_device() < 0) - return -1; - - /* Run tinc-up script to further initialize the tap interface */ - asprintf(&envp[0], "NETNAME=%s", netname?:""); - asprintf(&envp[1], "DEVICE=%s", device?:""); - asprintf(&envp[2], "INTERFACE=%s", interface?:""); - envp[3] = NULL; - - execute_script("tinc-up", envp); - - for(i = 0; i < 4; i++) - free(envp[i]); - - if(setup_myself() < 0) - return -1; - - try_outgoing_connections(); - cp(); - return 0; + char *envp[4]; + int i; + + cp(); + + now = time(NULL); + + init_connections(); + init_subnets(); + init_nodes(); + init_edges(); + init_events(); + init_requests(); + + if(get_config_int(lookup_config(config_tree, "PingTimeout"), &pingtimeout)) { + if(pingtimeout < 1) { + pingtimeout = 86400; + } + } else + pingtimeout = 60; + + if(setup_device() < 0) + return -1; + + /* Run tinc-up script to further initialize the tap interface */ + asprintf(&envp[0], "NETNAME=%s", netname ? : ""); + asprintf(&envp[1], "DEVICE=%s", device ? : ""); + asprintf(&envp[2], "INTERFACE=%s", interface ? : ""); + envp[3] = NULL; + + execute_script("tinc-up", envp); + + for(i = 0; i < 4; i++) + free(envp[i]); + + if(setup_myself() < 0) + return -1; + + try_outgoing_connections(); + + return 0; } /* @@ -589,47 +568,48 @@ int setup_network_connections(void) */ void close_network_connections(void) { - avl_node_t *node, *next; - connection_t *c; - char *envp[4]; - int i; - cp(); - for(node = connection_tree->head; node; node = next) - { - next = node->next; - c = (connection_t *)node->data; - if(c->outgoing) - free(c->outgoing->name), free(c->outgoing), c->outgoing = NULL; - terminate_connection(c, 0); - } - - if(myself && myself->connection) - terminate_connection(myself->connection, 0); - - for(i = 0; i < listen_sockets; i++) - { - close(listen_socket[i].tcp); - close(listen_socket[i].udp); - } - - exit_requests(); - exit_events(); - exit_edges(); - exit_subnets(); - exit_nodes(); - exit_connections(); - - asprintf(&envp[0], "NETNAME=%s", netname?:""); - asprintf(&envp[1], "DEVICE=%s", device?:""); - asprintf(&envp[2], "INTERFACE=%s", interface?:""); - envp[3] = NULL; - - execute_script("tinc-down", envp); - - for(i = 0; i < 4; i++) - free(envp[i]); - - close_device(); - cp(); - return; + avl_node_t *node, *next; + connection_t *c; + char *envp[4]; + int i; + + cp(); + + for(node = connection_tree->head; node; node = next) { + next = node->next; + c = (connection_t *) node->data; + + if(c->outgoing) + free(c->outgoing->name), free(c->outgoing), c->outgoing = NULL; + terminate_connection(c, 0); + } + + if(myself && myself->connection) + terminate_connection(myself->connection, 0); + + for(i = 0; i < listen_sockets; i++) { + close(listen_socket[i].tcp); + close(listen_socket[i].udp); + } + + exit_requests(); + exit_events(); + exit_edges(); + exit_subnets(); + exit_nodes(); + exit_connections(); + + asprintf(&envp[0], "NETNAME=%s", netname ? : ""); + asprintf(&envp[1], "DEVICE=%s", device ? : ""); + asprintf(&envp[2], "INTERFACE=%s", interface ? : ""); + envp[3] = NULL; + + execute_script("tinc-down", envp); + + for(i = 0; i < 4; i++) + free(envp[i]); + + close_device(); + + return; } diff --git a/src/net_socket.c b/src/net_socket.c index cbe9e68..96a58b0 100644 --- a/src/net_socket.c +++ b/src/net_socket.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: net_socket.c,v 1.1.2.19 2002/09/09 19:39:59 guus Exp $ + $Id: net_socket.c,v 1.1.2.20 2002/09/09 21:24:41 guus Exp $ */ #include "config.h" @@ -27,13 +27,13 @@ #include #include #ifdef HAVE_NETINET_IN_SYSTM_H - #include +#include #endif #ifdef HAVE_NETINET_IP_H - #include +#include #endif #ifdef HAVE_NETINET_TCP_H - #include +#include #endif #include #include @@ -84,357 +84,369 @@ int listen_sockets; /* Setup sockets */ -int setup_listen_socket(sockaddr_t *sa) +int setup_listen_socket(sockaddr_t * sa) { - int nfd, flags; - char *addrstr; - int option; + int nfd, flags; + char *addrstr; + int option; #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) - char *interface; - struct ifreq ifr; + char *interface; + struct ifreq ifr; #endif - cp(); - nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP); - if(nfd < 0) - { - syslog(LOG_ERR, _("Creating metasocket failed: %s"), strerror(errno)); - return -1; - } + cp(); - flags = fcntl(nfd, F_GETFL); - if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) - { - close(nfd); - syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", strerror(errno)); - return -1; - } + nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP); - /* Optimize TCP settings */ + if(nfd < 0) { + syslog(LOG_ERR, _("Creating metasocket failed: %s"), strerror(errno)); + return -1; + } + + flags = fcntl(nfd, F_GETFL); + + if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) { + close(nfd); + syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", + strerror(errno)); + return -1; + } + + /* Optimize TCP settings */ - option = 1; - setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); + option = 1; + setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); #if defined(SOL_TCP) && defined(TCP_NODELAY) - setsockopt(nfd, SOL_TCP, TCP_NODELAY, &option, sizeof(option)); + setsockopt(nfd, SOL_TCP, TCP_NODELAY, &option, sizeof(option)); #endif #if defined(SOL_IP) && defined(IP_TOS) && defined(IPTOS_LOWDELAY) - option = IPTOS_LOWDELAY; - setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option)); + option = IPTOS_LOWDELAY; + setsockopt(nfd, SOL_IP, IP_TOS, &option, sizeof(option)); #endif - if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface)) - { + if(get_config_string + (lookup_config(config_tree, "BindToInterface"), &interface)) { #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ); - if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) - { - close(nfd); - syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, strerror(errno)); - return -1; - } + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ); + + if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) { + close(nfd); + syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, + strerror(errno)); + return -1; + } #else - syslog(LOG_WARNING, _("BindToDevice not supported on this platform")); + syslog(LOG_WARNING, _("BindToDevice not supported on this platform")); #endif - } - - if(bind(nfd, &sa->sa, SALEN(sa->sa))) - { - close(nfd); - addrstr = sockaddr2hostname(sa); - syslog(LOG_ERR, _("Can't bind to %s/tcp: %s"), addrstr, strerror(errno)); - free(addrstr); - return -1; - } - - if(listen(nfd, 3)) - { - close(nfd); - syslog(LOG_ERR, _("System call `%s' failed: %s"), "listen", strerror(errno)); - return -1; - } - cp(); - return nfd; + } + + if(bind(nfd, &sa->sa, SALEN(sa->sa))) { + close(nfd); + addrstr = sockaddr2hostname(sa); + syslog(LOG_ERR, _("Can't bind to %s/tcp: %s"), addrstr, + strerror(errno)); + free(addrstr); + return -1; + } + + if(listen(nfd, 3)) { + close(nfd); + syslog(LOG_ERR, _("System call `%s' failed: %s"), "listen", + strerror(errno)); + return -1; + } + + return nfd; } -int setup_vpn_in_socket(sockaddr_t *sa) +int setup_vpn_in_socket(sockaddr_t * sa) { - int nfd, flags; - char *addrstr; - int option; + int nfd, flags; + char *addrstr; + int option; #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) - char *interface; - struct ifreq ifr; + char *interface; + struct ifreq ifr; #endif - cp(); - nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP); - - if(nfd < 0) - { - syslog(LOG_ERR, _("Creating UDP socket failed: %s"), strerror(errno)); - return -1; - } - - flags = fcntl(nfd, F_GETFL); - if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) - { - close(nfd); - syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", strerror(errno)); - return -1; - } - - option = 1; - setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); + + cp(); + + nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP); + + if(nfd < 0) { + syslog(LOG_ERR, _("Creating UDP socket failed: %s"), strerror(errno)); + return -1; + } + + flags = fcntl(nfd, F_GETFL); + if(fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0) { + close(nfd); + syslog(LOG_ERR, _("System call `%s' failed: %s"), "fcntl", + strerror(errno)); + return -1; + } + + option = 1; + setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) - if(get_config_string(lookup_config(config_tree, "BindToInterface"), &interface)) - { - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ); - if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) - { - close(nfd); - syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, strerror(errno)); - return -1; + if(get_config_string + (lookup_config(config_tree, "BindToInterface"), &interface)) { + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ); + + if(setsockopt(nfd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr))) { + close(nfd); + syslog(LOG_ERR, _("Can't bind to interface %s: %s"), interface, + strerror(errno)); + return -1; + } } - } #endif - if(bind(nfd, &sa->sa, SALEN(sa->sa))) - { - close(nfd); - addrstr = sockaddr2hostname(sa); - syslog(LOG_ERR, _("Can't bind to %s/udp: %s"), addrstr, strerror(errno)); - free(addrstr); - return -1; - } - cp(); - return nfd; + if(bind(nfd, &sa->sa, SALEN(sa->sa))) { + close(nfd); + addrstr = sockaddr2hostname(sa); + syslog(LOG_ERR, _("Can't bind to %s/udp: %s"), addrstr, + strerror(errno)); + free(addrstr); + return -1; + } + + return nfd; } -void retry_outgoing(outgoing_t *outgoing) +void retry_outgoing(outgoing_t * outgoing) { - event_t *event; - cp(); - outgoing->timeout += 5; - if(outgoing->timeout > maxtimeout) - outgoing->timeout = maxtimeout; - - event = new_event(); - event->handler = (event_handler_t)setup_outgoing_connection; - event->time = now + outgoing->timeout; - event->data = outgoing; - event_add(event); - - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_NOTICE, _("Trying to re-establish outgoing connection in %d seconds"), outgoing->timeout); - cp(); + event_t *event; + + cp(); + + outgoing->timeout += 5; + + if(outgoing->timeout > maxtimeout) + outgoing->timeout = maxtimeout; + + event = new_event(); + event->handler = (event_handler_t) setup_outgoing_connection; + event->time = now + outgoing->timeout; + event->data = outgoing; + event_add(event); + + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_NOTICE, + _("Trying to re-establish outgoing connection in %d seconds"), + outgoing->timeout); } -int setup_outgoing_socket(connection_t *c) +int setup_outgoing_socket(connection_t * c) { - int option; - cp(); - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname); + int option; - c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); + cp(); - if(c->socket == -1) - { - syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, strerror(errno)); - return -1; - } + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, + c->hostname); - /* Optimize TCP settings */ + c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); + + if(c->socket == -1) { + syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, + strerror(errno)); + return -1; + } + + /* Optimize TCP settings */ #if defined(SOL_TCP) && defined(TCP_NODELAY) - option = 1; - setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option)); + option = 1; + setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option)); #endif #if defined(SOL_IP) && defined(IP_TOS) - option = IPTOS_LOWDELAY; - setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option)); + option = IPTOS_LOWDELAY; + setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option)); #endif - /* Connect */ + /* Connect */ + + if(connect(c->socket, &c->address.sa, SALEN(c->address.sa)) == -1) { + close(c->socket); + syslog(LOG_ERR, _("Error while connecting to %s (%s): %s"), c->name, + c->hostname, strerror(errno)); + return -1; + } - if(connect(c->socket, &c->address.sa, SALEN(c->address.sa)) == -1) - { - close(c->socket); - syslog(LOG_ERR, _("Error while connecting to %s (%s): %s"), c->name, c->hostname, strerror(errno)); - return -1; - } + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname); - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname); - cp(); - return 0; + return 0; } -void finish_connecting(connection_t *c) +void finish_connecting(connection_t * c) { - cp(); - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname); + cp(); + + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname); - c->last_ping_time = now; + c->last_ping_time = now; - send_id(c); - cp(); + send_id(c); } -void do_outgoing_connection(connection_t *c) +void do_outgoing_connection(connection_t * c) { - char *address, *port; - int option, result, flags; - cp(); -begin: - if(!c->outgoing->ai) - { - if(!c->outgoing->cfg) - { - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_ERR, _("Could not set up a meta connection to %s"), c->name); - c->status.remove = 1; - retry_outgoing(c->outgoing); - return; - } - - get_config_string(c->outgoing->cfg, &address); + char *address, *port; + int option, result, flags; - if(!get_config_string(lookup_config(c->config_tree, "Port"), &port)) - asprintf(&port, "655"); + cp(); - c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM); - free(address); - free(port); - - c->outgoing->aip = c->outgoing->ai; - c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg); - } +begin: + if(!c->outgoing->ai) { + if(!c->outgoing->cfg) { + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_ERR, _("Could not set up a meta connection to %s"), + c->name); + c->status.remove = 1; + retry_outgoing(c->outgoing); + return; + } + + get_config_string(c->outgoing->cfg, &address); + + if(!get_config_string(lookup_config(c->config_tree, "Port"), &port)) + asprintf(&port, "655"); + + c->outgoing->ai = str2addrinfo(address, port, SOCK_STREAM); + free(address); + free(port); + + c->outgoing->aip = c->outgoing->ai; + c->outgoing->cfg = lookup_config_next(c->config_tree, c->outgoing->cfg); + } - if(!c->outgoing->aip) - { - freeaddrinfo(c->outgoing->ai); - c->outgoing->ai = NULL; - goto begin; - } + if(!c->outgoing->aip) { + freeaddrinfo(c->outgoing->ai); + c->outgoing->ai = NULL; + goto begin; + } - memcpy(&c->address, c->outgoing->aip->ai_addr, c->outgoing->aip->ai_addrlen); - c->outgoing->aip = c->outgoing->aip->ai_next; + memcpy(&c->address, c->outgoing->aip->ai_addr, + c->outgoing->aip->ai_addrlen); + c->outgoing->aip = c->outgoing->aip->ai_next; - if(c->hostname) - free(c->hostname); + if(c->hostname) + free(c->hostname); - c->hostname = sockaddr2hostname(&c->address); + c->hostname = sockaddr2hostname(&c->address); - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, c->hostname); + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_INFO, _("Trying to connect to %s (%s)"), c->name, + c->hostname); - c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); + c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP); - if(c->socket == -1) - { - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, strerror(errno)); + if(c->socket == -1) { + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, + strerror(errno)); - goto begin; - } + goto begin; + } - /* Optimize TCP settings */ + /* Optimize TCP settings */ #if defined(SOL_TCP) && defined(TCP_NODELAY) - option = 1; - setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option)); + option = 1; + setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option)); #endif #if defined(SOL_IP) && defined(IP_TOS) - option = IPTOS_LOWDELAY; - setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option)); + option = IPTOS_LOWDELAY; + setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option)); #endif - /* Non-blocking */ + /* Non-blocking */ - flags = fcntl(c->socket, F_GETFL); + flags = fcntl(c->socket, F_GETFL); - if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) - { - syslog(LOG_ERR, _("fcntl for %s: %s"), c->hostname, strerror(errno)); - } + if(fcntl(c->socket, F_SETFL, flags | O_NONBLOCK) < 0) { + syslog(LOG_ERR, _("fcntl for %s: %s"), c->hostname, strerror(errno)); + } - /* Connect */ + /* Connect */ - result = connect(c->socket, &c->address.sa, SALEN(c->address.sa)); + result = connect(c->socket, &c->address.sa, SALEN(c->address.sa)); - if(result == -1) - { - if(errno == EINPROGRESS) - { - c->status.connecting = 1; - return; - } + if(result == -1) { + if(errno == EINPROGRESS) { + c->status.connecting = 1; + return; + } - close(c->socket); + close(c->socket); - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_ERR, _("%s: %s"), c->hostname, strerror(errno)); + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_ERR, _("%s: %s"), c->hostname, strerror(errno)); + + goto begin; + } - goto begin; - } + finish_connecting(c); - finish_connecting(c); - return; - cp(); + return; } -void setup_outgoing_connection(outgoing_t *outgoing) +void setup_outgoing_connection(outgoing_t * outgoing) { - connection_t *c; - node_t *n; - cp(); - n = lookup_node(outgoing->name); - - if(n) - if(n->connection) - { - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_INFO, _("Already connected to %s"), outgoing->name); - n->connection->outgoing = outgoing; - return; - } - - c = new_connection(); - c->name = xstrdup(outgoing->name); - c->outcipher = myself->connection->outcipher; - c->outdigest = myself->connection->outdigest; - c->outmaclength = myself->connection->outmaclength; - c->outcompression = myself->connection->outcompression; - - init_configuration(&c->config_tree); - read_connection_config(c); - - outgoing->cfg = lookup_config(c->config_tree, "Address"); - - if(!outgoing->cfg) - { - syslog(LOG_ERR, _("No address specified for %s"), c->name); - free_connection(c); - free(outgoing->name); - free(outgoing); - return; - } - - c->outgoing = outgoing; - c->last_ping_time = now; - - connection_add(c); - - do_outgoing_connection(c); + connection_t *c; + node_t *n; + + cp(); + + n = lookup_node(outgoing->name); + + if(n) + if(n->connection) { + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_INFO, _("Already connected to %s"), outgoing->name); + + n->connection->outgoing = outgoing; + return; + } + + c = new_connection(); + c->name = xstrdup(outgoing->name); + c->outcipher = myself->connection->outcipher; + c->outdigest = myself->connection->outdigest; + c->outmaclength = myself->connection->outmaclength; + c->outcompression = myself->connection->outcompression; + + init_configuration(&c->config_tree); + read_connection_config(c); + + outgoing->cfg = lookup_config(c->config_tree, "Address"); + + if(!outgoing->cfg) { + syslog(LOG_ERR, _("No address specified for %s"), c->name); + free_connection(c); + free(outgoing->name); + free(outgoing); + return; + } + + c->outgoing = outgoing; + c->last_ping_time = now; + + connection_add(c); + + do_outgoing_connection(c); } /* @@ -443,61 +455,66 @@ void setup_outgoing_connection(outgoing_t *outgoing) */ int handle_new_meta_connection(int sock) { - connection_t *c; - sockaddr_t sa; - int fd, len = sizeof(sa); - cp(); - fd = accept(sock, &sa.sa, &len); - - if(fd < 0) - { - syslog(LOG_ERR, _("Accepting a new connection failed: %s"), strerror(errno)); - return -1; - } - - sockaddrunmap(&sa); - - c = new_connection(); - c->outcipher = myself->connection->outcipher; - c->outdigest = myself->connection->outdigest; - c->outmaclength = myself->connection->outmaclength; - c->outcompression = myself->connection->outcompression; - - c->address = sa; - c->hostname = sockaddr2hostname(&sa); - c->socket = fd; - c->last_ping_time = now; - - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_NOTICE, _("Connection from %s"), c->hostname); - - connection_add(c); - - c->allow_request = ID; - send_id(c); - cp(); - return 0; + connection_t *c; + sockaddr_t sa; + int fd, len = sizeof(sa); + + cp(); + + fd = accept(sock, &sa.sa, &len); + + if(fd < 0) { + syslog(LOG_ERR, _("Accepting a new connection failed: %s"), + strerror(errno)); + return -1; + } + + sockaddrunmap(&sa); + + c = new_connection(); + c->outcipher = myself->connection->outcipher; + c->outdigest = myself->connection->outdigest; + c->outmaclength = myself->connection->outmaclength; + c->outcompression = myself->connection->outcompression; + + c->address = sa; + c->hostname = sockaddr2hostname(&sa); + c->socket = fd; + c->last_ping_time = now; + + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_NOTICE, _("Connection from %s"), c->hostname); + + connection_add(c); + + c->allow_request = ID; + send_id(c); + + return 0; } void try_outgoing_connections(void) { - static config_t *cfg = NULL; - char *name; - outgoing_t *outgoing; - cp(); - for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; cfg = lookup_config_next(config_tree, cfg)) - { - get_config_string(cfg, &name); - - if(check_id(name)) - { - syslog(LOG_ERR, _("Invalid name for outgoing connection in %s line %d"), cfg->file, cfg->line); - free(name); - continue; - } - - outgoing = xmalloc_and_zero(sizeof(*outgoing)); - outgoing->name = name; - setup_outgoing_connection(outgoing); - } + static config_t *cfg = NULL; + char *name; + outgoing_t *outgoing; + + cp(); + + for(cfg = lookup_config(config_tree, "ConnectTo"); cfg; + cfg = lookup_config_next(config_tree, cfg)) { + get_config_string(cfg, &name); + + if(check_id(name)) { + syslog(LOG_ERR, + _("Invalid name for outgoing connection in %s line %d"), + cfg->file, cfg->line); + free(name); + continue; + } + + outgoing = xmalloc_and_zero(sizeof(*outgoing)); + outgoing->name = name; + setup_outgoing_connection(outgoing); + } } diff --git a/src/netbsd/device.c b/src/netbsd/device.c index 33896aa..53bd9da 100644 --- a/src/netbsd/device.c +++ b/src/netbsd/device.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: device.c,v 1.1.2.4 2002/06/21 10:11:36 guus Exp $ + $Id: device.c,v 1.1.2.5 2002/09/09 21:25:23 guus Exp $ */ #include "config.h" @@ -63,93 +63,80 @@ extern subnet_t mymac; */ int setup_device(void) { - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = DEFAULT_DEVICE; - - if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) - interface = rindex(device, '/')?rindex(device, '/')+1:device; -cp - if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) - { - syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return -1; - } -cp - /* Set default MAC address for ethertap devices */ - - mymac.type = SUBNET_MAC; - mymac.net.mac.address.x[0] = 0xfe; - mymac.net.mac.address.x[1] = 0xfd; - mymac.net.mac.address.x[2] = 0x00; - mymac.net.mac.address.x[3] = 0x00; - mymac.net.mac.address.x[4] = 0x00; - mymac.net.mac.address.x[5] = 0x00; - - device_info = _("NetBSD tun device"); - - syslog(LOG_INFO, _("%s is a %s"), device, device_info); -cp - return 0; + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) + device = DEFAULT_DEVICE; + + if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) + interface = rindex(device, '/') ? rindex(device, '/') + 1 : device; + cp if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) { + syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); + return -1; + } + cp + /* Set default MAC address for ethertap devices */ + mymac.type = SUBNET_MAC; + mymac.net.mac.address.x[0] = 0xfe; + mymac.net.mac.address.x[1] = 0xfd; + mymac.net.mac.address.x[2] = 0x00; + mymac.net.mac.address.x[3] = 0x00; + mymac.net.mac.address.x[4] = 0x00; + mymac.net.mac.address.x[5] = 0x00; + + device_info = _("NetBSD tun device"); + + syslog(LOG_INFO, _("%s is a %s"), device, device_info); + cp return 0; } void close_device(void) { -cp - close(device_fd); -cp -} + cp close(device_fd); +cp} -int read_packet(vpn_packet_t *packet) +int read_packet(vpn_packet_t * packet) { - int lenin; -cp - - if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } + int lenin; + cp if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) { + syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, + device, strerror(errno)); + return -1; + } - memcpy(packet->data, mymac.net.mac.address.x, 6); - memcpy(packet->data + 6, mymac.net.mac.address.x, 6); - packet->data[12] = 0x08; - packet->data[13] = 0x00; + memcpy(packet->data, mymac.net.mac.address.x, 6); + memcpy(packet->data + 6, mymac.net.mac.address.x, 6); + packet->data[12] = 0x08; + packet->data[13] = 0x00; - packet->len = lenin + 14; + packet->len = lenin + 14; - device_total_in += packet->len; + device_total_in += packet->len; - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info); - } + if(debug_lvl >= DEBUG_TRAFFIC) { + syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, + device_info); + } - return 0; -cp -} + return 0; +cp} -int write_packet(vpn_packet_t *packet) +int write_packet(vpn_packet_t * packet) { -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), - packet->len, device_info); - - if(write(device_fd, packet->data + 14, packet->len - 14) < 0) - { - syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - device_total_out += packet->len; -cp -} + cp if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), + packet->len, device_info); + + if(write(device_fd, packet->data + 14, packet->len - 14) < 0) { + syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, + strerror(errno)); + return -1; + } + + device_total_out += packet->len; +cp} void dump_device_stats(void) { -cp - syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); - syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); - syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); -cp -} + cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); + syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); + syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); +cp} diff --git a/src/netutl.c b/src/netutl.c index 35a3fef..e5c969e 100644 --- a/src/netutl.c +++ b/src/netutl.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: netutl.c,v 1.12.4.42 2002/09/09 19:39:59 guus Exp $ + $Id: netutl.c,v 1.12.4.43 2002/09/09 21:24:41 guus Exp $ */ #include "config.h" @@ -28,7 +28,7 @@ #include #include #ifdef HAVE_INTTYPES_H - #include +#include #endif #include #include @@ -54,211 +54,232 @@ int hostnames = 0; */ struct addrinfo *str2addrinfo(char *address, char *service, int socktype) { - struct addrinfo hint, *ai; - int err; - cp(); - memset(&hint, 0, sizeof(hint)); - - hint.ai_family = addressfamily; - hint.ai_socktype = socktype; - - err = getaddrinfo(address, service, &hint, &ai); - - if(err) - { - if(debug_lvl >= DEBUG_ERROR) - syslog(LOG_WARNING, _("Error looking up %s port %s: %s\n"), address, service, gai_strerror(err)); - cp_trace(); - return NULL; - } - - cp(); - return ai; + struct addrinfo hint, *ai; + int err; + + cp(); + + memset(&hint, 0, sizeof(hint)); + + hint.ai_family = addressfamily; + hint.ai_socktype = socktype; + + err = getaddrinfo(address, service, &hint, &ai); + + if(err) { + if(debug_lvl >= DEBUG_ERROR) + syslog(LOG_WARNING, _("Error looking up %s port %s: %s\n"), address, + service, gai_strerror(err)); + cp_trace(); + return NULL; + } + + return ai; } sockaddr_t str2sockaddr(char *address, char *port) { - struct addrinfo hint, *ai; - sockaddr_t result; - int err; - cp(); - memset(&hint, 0, sizeof(hint)); - - hint.ai_family = AF_UNSPEC; - hint.ai_flags = AI_NUMERICHOST; - hint.ai_socktype = SOCK_STREAM; - - err = getaddrinfo(address, port, &hint, &ai); - - if(err || !ai) - { - syslog(LOG_ERR, _("Error looking up %s port %s: %s\n"), address, port, gai_strerror(err)); - cp_trace(); - raise(SIGFPE); - exit(0); - } - - result = *(sockaddr_t *)ai->ai_addr; - freeaddrinfo(ai); - cp(); - return result; + struct addrinfo hint, *ai; + sockaddr_t result; + int err; + + cp(); + + memset(&hint, 0, sizeof(hint)); + + hint.ai_family = AF_UNSPEC; + hint.ai_flags = AI_NUMERICHOST; + hint.ai_socktype = SOCK_STREAM; + + err = getaddrinfo(address, port, &hint, &ai); + + if(err || !ai) { + syslog(LOG_ERR, _("Error looking up %s port %s: %s\n"), address, port, + gai_strerror(err)); + cp_trace(); + raise(SIGFPE); + exit(0); + } + + result = *(sockaddr_t *) ai->ai_addr; + freeaddrinfo(ai); + + return result; } -void sockaddr2str(sockaddr_t *sa, char **addrstr, char **portstr) +void sockaddr2str(sockaddr_t * sa, char **addrstr, char **portstr) { - char address[NI_MAXHOST]; - char port[NI_MAXSERV]; - char *scopeid; - int err; - cp(); - err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV); - - if(err) - { - syslog(LOG_ERR, _("Error while translating addresses: %s"), gai_strerror(err)); - cp_trace(); - raise(SIGFPE); - exit(0); - } - - scopeid = strchr(address, '%'); - - if(scopeid) - *scopeid = '\0'; /* Descope. */ - - *addrstr = xstrdup(address); - *portstr = xstrdup(port); - cp(); + char address[NI_MAXHOST]; + char port[NI_MAXSERV]; + char *scopeid; + int err; + + cp(); + + err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV); + + if(err) { + syslog(LOG_ERR, _("Error while translating addresses: %s"), + gai_strerror(err)); + cp_trace(); + raise(SIGFPE); + exit(0); + } + + scopeid = strchr(address, '%'); + + if(scopeid) + *scopeid = '\0'; /* Descope. */ + + *addrstr = xstrdup(address); + *portstr = xstrdup(port); } -char *sockaddr2hostname(sockaddr_t *sa) +char *sockaddr2hostname(sockaddr_t * sa) { - char *str; - char address[NI_MAXHOST] = "unknown"; - char port[NI_MAXSERV] = "unknown"; - int err; - cp(); - err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), hostnames?0:(NI_NUMERICHOST|NI_NUMERICSERV)); - if(err) - { - syslog(LOG_ERR, _("Error while looking up hostname: %s"), gai_strerror(err)); - } - - asprintf(&str, _("%s port %s"), address, port); - cp(); - return str; + char *str; + char address[NI_MAXHOST] = "unknown"; + char port[NI_MAXSERV] = "unknown"; + int err; + + cp(); + + err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), + hostnames ? 0 : (NI_NUMERICHOST | NI_NUMERICSERV)); + if(err) { + syslog(LOG_ERR, _("Error while looking up hostname: %s"), + gai_strerror(err)); + } + + asprintf(&str, _("%s port %s"), address, port); + + return str; } -int sockaddrcmp(sockaddr_t *a, sockaddr_t *b) +int sockaddrcmp(sockaddr_t * a, sockaddr_t * b) { - int result; - cp(); - result = a->sa.sa_family - b->sa.sa_family; - - if(result) - return result; - - switch(a->sa.sa_family) - { - case AF_UNSPEC: - return 0; - case AF_INET: - result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr)); - if(result) - return result; - return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof(a->in.sin_port)); - case AF_INET6: - result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)); + int result; + + cp(); + + result = a->sa.sa_family - b->sa.sa_family; + if(result) - return result; - return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof(a->in6.sin6_port)); - default: - syslog(LOG_ERR, _("sockaddrcmp() was called with unknown address family %d, exitting!"), a->sa.sa_family); - cp_trace(); - raise(SIGFPE); - exit(0); - } - cp(); + return result; + + switch (a->sa.sa_family) { + case AF_UNSPEC: + return 0; + + case AF_INET: + result = memcmp(&a->in.sin_addr, &b->in.sin_addr, sizeof(a->in.sin_addr)); + + if(result) + return result; + + return memcmp(&a->in.sin_port, &b->in.sin_port, sizeof(a->in.sin_port)); + + case AF_INET6: + result = memcmp(&a->in6.sin6_addr, &b->in6.sin6_addr, sizeof(a->in6.sin6_addr)); + + if(result) + return result; + + return memcmp(&a->in6.sin6_port, &b->in6.sin6_port, sizeof(a->in6.sin6_port)); + + default: + syslog(LOG_ERR, _("sockaddrcmp() was called with unknown address family %d, exitting!"), + a->sa.sa_family); + cp_trace(); + raise(SIGFPE); + exit(0); + } } -void sockaddrunmap(sockaddr_t *sa) +void sockaddrunmap(sockaddr_t * sa) { - 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; - } + 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; + } } /* Subnet mask handling */ int maskcmp(void *va, void *vb, int masklen, int len) { - int i, m, result; - char *a = va; - char *b = vb; - cp(); - for(m = masklen, i = 0; m >= 8; m -= 8, i++) - { - result = a[i] - b[i]; - if(result) - return result; - } - - if(m) - return (a[i] & (0x100 - (1 << (8 - m)))) - (b[i] & (0x100 - (1 << (8 - m)))); - - return 0; + int i, m, result; + char *a = va; + char *b = vb; + + cp(); + + for(m = masklen, i = 0; m >= 8; m -= 8, i++) { + result = a[i] - b[i]; + if(result) + return result; + } + + if(m) + return (a[i] & (0x100 - (1 << (8 - m)))) - + (b[i] & (0x100 - (1 << (8 - m)))); + + return 0; } void mask(void *va, int masklen, int len) { - int i; - char *a = va; - cp(); - i = masklen / 8; - masklen %= 8; - - if(masklen) - a[i++] &= (0x100 - (1 << masklen)); - - for(; i < len; i++) - a[i] = 0; + int i; + char *a = va; + + cp(); + + i = masklen / 8; + masklen %= 8; + + if(masklen) + a[i++] &= (0x100 - (1 << masklen)); + + for(; i < len; i++) + a[i] = 0; } void maskcpy(void *va, void *vb, int masklen, int len) { - int i, m; - char *a = va; - char *b = vb; - cp(); - for(m = masklen, i = 0; m >= 8; m -= 8, i++) - a[i] = b[i]; - - if(m) - { - a[i] = b[i] & (0x100 - (1 << m)); - i++; - } - - for(; i < len; i++) - a[i] = 0; + int i, m; + char *a = va; + char *b = vb; + + cp(); + + for(m = masklen, i = 0; m >= 8; m -= 8, i++) + a[i] = b[i]; + + if(m) { + a[i] = b[i] & (0x100 - (1 << m)); + i++; + } + + for(; i < len; i++) + a[i] = 0; } int maskcheck(void *va, int masklen, int len) { - int i; - char *a = va; - cp(); - i = masklen / 8; - masklen %= 8; + int i; + char *a = va; + + cp(); + + i = masklen / 8; + masklen %= 8; - if(masklen && a[i++] & (0xff >> masklen)) - return -1; + if(masklen && a[i++] & (0xff >> masklen)) + return -1; - for(; i < len; i++) - if(a[i] != 0) - return -2; + for(; i < len; i++) + if(a[i] != 0) + return -2; - return 0; + return 0; } diff --git a/src/netutl.h b/src/netutl.h index db5e214..5554b27 100644 --- a/src/netutl.h +++ b/src/netutl.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: netutl.h,v 1.2.4.13 2002/06/21 10:11:13 guus Exp $ + $Id: netutl.h,v 1.2.4.14 2002/09/09 21:24:41 guus Exp $ */ #ifndef __TINC_NETUTL_H__ @@ -42,4 +42,4 @@ extern void maskcpy(void *, void *, int, int); extern void mask(void *, int, int); extern int maskcheck(void *, int, int); -#endif /* __TINC_NETUTL_H__ */ +#endif /* __TINC_NETUTL_H__ */ diff --git a/src/node.c b/src/node.c index 4fdb99c..89b1689 100644 --- a/src/node.c +++ b/src/node.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: node.c,v 1.1.2.16 2002/09/09 19:39:59 guus Exp $ + $Id: node.c,v 1.1.2.17 2002/09/09 21:24:41 guus Exp $ */ #include "config.h" @@ -34,140 +34,151 @@ #include "system.h" -avl_tree_t *node_tree; /* Known nodes, sorted by name */ -avl_tree_t *node_udp_tree; /* Known nodes, sorted by address and port */ +avl_tree_t *node_tree; /* Known nodes, sorted by name */ +avl_tree_t *node_udp_tree; /* Known nodes, sorted by address and port */ node_t *myself; -int node_compare(node_t *a, node_t *b) +int node_compare(node_t * a, node_t * b) { - return strcmp(a->name, b->name); + return strcmp(a->name, b->name); } -int node_udp_compare(node_t *a, node_t *b) +int node_udp_compare(node_t * a, node_t * b) { - int result; - cp(); - result = sockaddrcmp(&a->address, &b->address); + int result; - if(result) - return result; + cp(); - return (a->name && b->name)?strcmp(a->name, b->name):0; + result = sockaddrcmp(&a->address, &b->address); + + if(result) + return result; + + return (a->name && b->name) ? strcmp(a->name, b->name) : 0; } void init_nodes(void) { - cp(); - node_tree = avl_alloc_tree((avl_compare_t)node_compare, NULL); - node_udp_tree = avl_alloc_tree((avl_compare_t)node_udp_compare, NULL); - cp(); + cp(); + + node_tree = avl_alloc_tree((avl_compare_t) node_compare, NULL); + node_udp_tree = avl_alloc_tree((avl_compare_t) node_udp_compare, NULL); } void exit_nodes(void) { - cp(); - avl_delete_tree(node_tree); - avl_delete_tree(node_udp_tree); - cp(); + cp(); + + avl_delete_tree(node_tree); + avl_delete_tree(node_udp_tree); } node_t *new_node(void) { - node_t *n = (node_t *)xmalloc_and_zero(sizeof(*n)); - cp(); - n->subnet_tree = new_subnet_tree(); - n->edge_tree = new_edge_tree(); - n->queue = list_alloc((list_action_t)free); - cp(); - return n; + node_t *n = (node_t *) xmalloc_and_zero(sizeof(*n)); + + cp(); + + n->subnet_tree = new_subnet_tree(); + n->edge_tree = new_edge_tree(); + n->queue = list_alloc((list_action_t) free); + + return n; } -void free_node(node_t *n) +void free_node(node_t * n) { - cp(); - if(n->queue) - list_delete_list(n->queue); - if(n->name) - free(n->name); - if(n->hostname) - free(n->hostname); - if(n->key) - free(n->key); - if(n->subnet_tree) - free_subnet_tree(n->subnet_tree); - if(n->edge_tree) - free_edge_tree(n->edge_tree); - free(n); - cp(); + cp(); + + if(n->queue) + list_delete_list(n->queue); + + if(n->name) + free(n->name); + + if(n->hostname) + free(n->hostname); + + if(n->key) + free(n->key); + + if(n->subnet_tree) + free_subnet_tree(n->subnet_tree); + + if(n->edge_tree) + free_edge_tree(n->edge_tree); + + free(n); } -void node_add(node_t *n) +void node_add(node_t * n) { - cp(); - avl_insert(node_tree, n); - avl_insert(node_udp_tree, n); - cp(); + cp(); + + avl_insert(node_tree, n); + avl_insert(node_udp_tree, n); } -void node_del(node_t *n) +void node_del(node_t * n) { - avl_node_t *node, *next; - edge_t *e; - subnet_t *s; - cp(); - for(node = n->subnet_tree->head; node; node = next) - { - next = node->next; - s = (subnet_t *)node->data; - subnet_del(n, s); - } - - for(node = n->edge_tree->head; node; node = next) - { - next = node->next; - e = (edge_t *)node->data; - edge_del(e); - } - cp(); - avl_delete(node_tree, n); - avl_delete(node_udp_tree, n); - cp(); + avl_node_t *node, *next; + edge_t *e; + subnet_t *s; + + cp(); + + for(node = n->subnet_tree->head; node; node = next) { + next = node->next; + s = (subnet_t *) node->data; + subnet_del(n, s); + } + + for(node = n->edge_tree->head; node; node = next) { + next = node->next; + e = (edge_t *) node->data; + edge_del(e); + } + + avl_delete(node_tree, n); + avl_delete(node_udp_tree, n); } node_t *lookup_node(char *name) { - node_t n; - cp(); - n.name = name; - return avl_search(node_tree, &n); + node_t n; + cp(); + n.name = name; + return avl_search(node_tree, &n); } -node_t *lookup_node_udp(sockaddr_t *sa) +node_t *lookup_node_udp(sockaddr_t * sa) { - node_t n; - cp(); - n.address = *sa; - n.name = NULL; + node_t n; + cp(); + n.address = *sa; + n.name = NULL; - return avl_search(node_udp_tree, &n); + return avl_search(node_udp_tree, &n); } void dump_nodes(void) { - avl_node_t *node; - node_t *n; - cp(); - syslog(LOG_DEBUG, _("Nodes:")); - - for(node = node_tree->head; node; node = node->next) - { - n = (node_t *)node->data; - syslog(LOG_DEBUG, _(" %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s"), - n->name, n->hostname, n->cipher?n->cipher->nid:0, n->digest?n->digest->type:0, n->maclength, n->compression, n->options, - n->status, n->nexthop?n->nexthop->name:"-", n->via?n->via->name:"-"); - } - - syslog(LOG_DEBUG, _("End of nodes.")); - cp(); + avl_node_t *node; + node_t *n; + + cp(); + + syslog(LOG_DEBUG, _("Nodes:")); + + for(node = node_tree->head; node; node = node->next) { + n = (node_t *) node->data; + syslog(LOG_DEBUG, _(" %s at %s cipher %d digest %d maclength %d compression %d options %lx status %04x nexthop %s via %s"), + n->name, n->hostname, n->cipher ? n->cipher->nid : 0, + n->digest ? n->digest->type : 0, n->maclength, n->compression, + n->options, n->status, n->nexthop ? n->nexthop->name : "-", + n->via ? n->via->name : "-"); + } + + syslog(LOG_DEBUG, _("End of nodes.")); } diff --git a/src/node.h b/src/node.h index 8f6b30f..e4dcd52 100644 --- a/src/node.h +++ b/src/node.h @@ -17,14 +17,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: node.h,v 1.1.2.19 2002/09/04 13:48:52 guus Exp $ + $Id: node.h,v 1.1.2.20 2002/09/09 21:24:41 guus Exp $ */ #ifndef __TINC_NODE_H__ #define __TINC_NODE_H__ #ifdef HAVE_INTTYPES_H - #include +#include #endif #include @@ -33,46 +33,46 @@ #include "connection.h" typedef struct node_status_t { - int active:1; /* 1 if active.. */ - int validkey:1; /* 1 if we currently have a valid key for him */ - int waitingforkey:1; /* 1 if we already sent out a request */ - int visited:1; /* 1 if this node has been visited by one of the graph algorithms */ - int reachable:1; /* 1 if this node is reachable in the graph */ - int indirect:1; /* 1 if this node is not directly reachable by us */ - int unused:26; + int active:1; /* 1 if active.. */ + int validkey:1; /* 1 if we currently have a valid key for him */ + int waitingforkey:1; /* 1 if we already sent out a request */ + int visited:1; /* 1 if this node has been visited by one of the graph algorithms */ + int reachable:1; /* 1 if this node is reachable in the graph */ + int indirect:1; /* 1 if this node is not directly reachable by us */ + int unused:26; } node_status_t; typedef struct node_t { - char *name; /* name of this node */ - long int options; /* options turned on for this node */ + char *name; /* name of this node */ + long int options; /* options turned on for this node */ - sockaddr_t address; /* his real (internet) ip to send UDP packets to */ - char *hostname; /* the hostname of its real ip */ + sockaddr_t address; /* his real (internet) ip to send UDP packets to */ + char *hostname; /* the hostname of its real ip */ - struct node_status_t status; + struct node_status_t status; - const EVP_CIPHER *cipher; /* Cipher type for UDP packets */ - char *key; /* Cipher key and iv */ - int keylength; /* Cipher key and iv length*/ + const EVP_CIPHER *cipher; /* Cipher type for UDP packets */ + char *key; /* Cipher key and iv */ + int keylength; /* Cipher key and iv length */ - const EVP_MD *digest; /* Digest type for MAC */ - int maclength; /* Length of MAC */ + const EVP_MD *digest; /* Digest type for MAC */ + int maclength; /* Length of MAC */ - int compression; /* Compressionlevel, 0 = no compression */ + int compression; /* Compressionlevel, 0 = no compression */ - list_t *queue; /* Queue for packets awaiting to be encrypted */ + list_t *queue; /* Queue for packets awaiting to be encrypted */ - struct node_t *nexthop; /* nearest node from us to him */ - struct node_t *via; /* next hop for UDP packets */ - - avl_tree_t *subnet_tree; /* Pointer to a tree of subnets belonging to this node */ + struct node_t *nexthop; /* nearest node from us to him */ + struct node_t *via; /* next hop for UDP packets */ - avl_tree_t *edge_tree; /* Edges with this node as one of the endpoints */ + avl_tree_t *subnet_tree; /* Pointer to a tree of subnets belonging to this node */ - struct connection_t *connection; /* Connection associated with this node (if a direct connection exists) */ + avl_tree_t *edge_tree; /* Edges with this node as one of the endpoints */ - uint32_t sent_seqno; /* Sequence number last sent to this node */ - uint32_t received_seqno; /* Sequence number last received from this node */ + struct connection_t *connection; /* Connection associated with this node (if a direct connection exists) */ + + uint32_t sent_seqno; /* Sequence number last sent to this node */ + uint32_t received_seqno; /* Sequence number last received from this node */ } node_t; extern struct node_t *myself; @@ -89,4 +89,4 @@ extern node_t *lookup_node(char *); extern node_t *lookup_node_udp(sockaddr_t *); extern void dump_nodes(void); -#endif /* __TINC_NODE_H__ */ +#endif /* __TINC_NODE_H__ */ diff --git a/src/openbsd/device.c b/src/openbsd/device.c index 1a339a5..dee8fa0 100644 --- a/src/openbsd/device.c +++ b/src/openbsd/device.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: device.c,v 1.1.2.9 2002/06/21 10:11:36 guus Exp $ + $Id: device.c,v 1.1.2.10 2002/09/09 21:25:26 guus Exp $ */ #include "config.h" @@ -63,133 +63,125 @@ extern subnet_t mymac; */ int setup_device(void) { - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = DEFAULT_DEVICE; - - if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) - interface = rindex(device, '/')?rindex(device, '/')+1:device; -cp - if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) - { - syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return -1; - } -cp - /* Set default MAC address for ethertap devices */ - - mymac.type = SUBNET_MAC; - mymac.net.mac.address.x[0] = 0xfe; - mymac.net.mac.address.x[1] = 0xfd; - mymac.net.mac.address.x[2] = 0x00; - mymac.net.mac.address.x[3] = 0x00; - mymac.net.mac.address.x[4] = 0x00; - mymac.net.mac.address.x[5] = 0x00; - - device_info = _("OpenBSD tun device"); - - syslog(LOG_INFO, _("%s is a %s"), device, device_info); -cp - return 0; + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) + device = DEFAULT_DEVICE; + + if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) + interface = rindex(device, '/') ? rindex(device, '/') + 1 : device; + cp if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) { + syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); + return -1; + } + cp + /* Set default MAC address for ethertap devices */ + mymac.type = SUBNET_MAC; + mymac.net.mac.address.x[0] = 0xfe; + mymac.net.mac.address.x[1] = 0xfd; + mymac.net.mac.address.x[2] = 0x00; + mymac.net.mac.address.x[3] = 0x00; + mymac.net.mac.address.x[4] = 0x00; + mymac.net.mac.address.x[5] = 0x00; + + device_info = _("OpenBSD tun device"); + + syslog(LOG_INFO, _("%s is a %s"), device, device_info); + cp return 0; } void close_device(void) { -cp - close(device_fd); -cp -} + cp close(device_fd); +cp} -int read_packet(vpn_packet_t *packet) +int read_packet(vpn_packet_t * packet) { - int lenin; - u_int32_t type; - struct iovec vector[2] = {{&type, sizeof(type)}, {packet->data + 14, MTU - 14}}; -cp - - if((lenin = readv(device_fd, vector, 2)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - memcpy(packet->data, mymac.net.mac.address.x, 6); - memcpy(packet->data + 6, mymac.net.mac.address.x, 6); - - switch(ntohl(type)) - { - case AF_INET: - packet->data[12] = 0x8; - packet->data[13] = 0x0; - break; - case AF_INET6: - packet->data[12] = 0x86; - packet->data[13] = 0xDD; - break; - default: - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_ERR, _("Unknown address family %d while reading packet from %s %s"), ntohl(type), device_info, device); - return -1; - } - - packet->len = lenin + 10; - - device_total_in += packet->len; - - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info); - } - - return 0; -cp -} - -int write_packet(vpn_packet_t *packet) + int lenin; + u_int32_t type; + struct iovec vector[2] = { {&type, sizeof(type)} + , {packet->data + 14, MTU - 14} + }; + cp if((lenin = readv(device_fd, vector, 2)) <= 0) { + syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, + device, strerror(errno)); + return -1; + } + + memcpy(packet->data, mymac.net.mac.address.x, 6); + memcpy(packet->data + 6, mymac.net.mac.address.x, 6); + + switch (ntohl(type)) { + case AF_INET: + packet->data[12] = 0x8; + packet->data[13] = 0x0; + break; + case AF_INET6: + packet->data[12] = 0x86; + packet->data[13] = 0xDD; + break; + default: + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_ERR, + _ + ("Unknown address family %d while reading packet from %s %s"), + ntohl(type), device_info, device); + return -1; + } + + packet->len = lenin + 10; + + device_total_in += packet->len; + + if(debug_lvl >= DEBUG_TRAFFIC) { + syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, + device_info); + } + + return 0; +cp} + +int write_packet(vpn_packet_t * packet) { - u_int32_t type; - struct iovec vector[2]; - int af; -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), - packet->len, device_info); - - af = (packet->data[12] << 8) + packet->data[13]; - - switch(af) - { - case 0x800: - type = htonl(AF_INET); - break; - case 0x86DD: - type = htonl(AF_INET6); - break; - default: - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_ERR, _("Unknown address family %d while writing packet to %s %s"), af, device_info, device); - return -1; - } - - vector[0].iov_base = &type; - vector[0].iov_len = sizeof(type); - vector[1].iov_base = packet->data + 14; - vector[1].iov_len = packet->len - 14; - - if(writev(device_fd, vector, 2) < 0) - { - syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - device_total_out += packet->len; -cp -} + u_int32_t type; + struct iovec vector[2]; + int af; + cp if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), + packet->len, device_info); + + af = (packet->data[12] << 8) + packet->data[13]; + + switch (af) { + case 0x800: + type = htonl(AF_INET); + break; + case 0x86DD: + type = htonl(AF_INET6); + break; + default: + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_ERR, + _("Unknown address family %d while writing packet to %s %s"), + af, device_info, device); + return -1; + } + + vector[0].iov_base = &type; + vector[0].iov_len = sizeof(type); + vector[1].iov_base = packet->data + 14; + vector[1].iov_len = packet->len - 14; + + if(writev(device_fd, vector, 2) < 0) { + syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, + strerror(errno)); + return -1; + } + + device_total_out += packet->len; +cp} void dump_device_stats(void) { -cp - syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); - syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); - syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); -cp -} + cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); + syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); + syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); +cp} diff --git a/src/process.c b/src/process.c index 3e07552..f149d7c 100644 --- a/src/process.c +++ b/src/process.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: process.c,v 1.1.2.45 2002/09/09 19:39:59 guus Exp $ + $Id: process.c,v 1.1.2.46 2002/09/09 21:24:41 guus Exp $ */ #include "config.h" @@ -66,9 +66,9 @@ extern int do_purge; void memory_full(int size) { - syslog(LOG_ERR, _("Memory exhausted (couldn't allocate %d bytes), exitting."), size); - cp_trace(); - exit(1); + syslog(LOG_ERR, _("Memory exhausted (couldn't allocate %d bytes), exitting."), size); + cp_trace(); + exit(1); } /* Some functions the less gifted operating systems might lack... */ @@ -76,13 +76,13 @@ void memory_full(int size) #ifndef HAVE_FCLOSEALL int fcloseall(void) { - fflush(stdin); - fflush(stdout); - fflush(stderr); - fclose(stdin); - fclose(stdout); - fclose(stderr); - return 0; + fflush(stdin); + fflush(stdout); + fflush(stderr); + fclose(stdin); + fclose(stdout); + fclose(stderr); + return 0; } #endif @@ -91,16 +91,17 @@ int fcloseall(void) */ void cleanup_and_exit(int c) { - cp(); - close_network_connections(); + cp(); - if(debug_lvl > DEBUG_NOTHING) - dump_device_stats(); + close_network_connections(); - syslog(LOG_NOTICE, _("Terminating")); + if(debug_lvl > DEBUG_NOTHING) + dump_device_stats(); - closelog(); - exit(c); + syslog(LOG_NOTICE, _("Terminating")); + + closelog(); + exit(c); } /* @@ -108,25 +109,26 @@ void cleanup_and_exit(int c) */ int write_pidfile(void) { - int pid; - cp(); - pid = check_pid(pidfilename); - - if(pid) - { - if(netname) - fprintf(stderr, _("A tincd is already running for net `%s' with pid %d.\n"), - netname, pid); - else - fprintf(stderr, _("A tincd is already running with pid %d.\n"), pid); - return 1; - } - - /* if it's locked, write-protected, or whatever */ - if(!write_pid(pidfilename)) - return 1; - cp(); - return 0; + int pid; + + cp(); + + pid = check_pid(pidfilename); + + if(pid) { + if(netname) + fprintf(stderr, _("A tincd is already running for net `%s' with pid %d.\n"), + netname, pid); + else + fprintf(stderr, _("A tincd is already running with pid %d.\n"), pid); + return 1; + } + + /* if it's locked, write-protected, or whatever */ + if(!write_pid(pidfilename)) + return 1; + + return 0; } /* @@ -134,33 +136,36 @@ int write_pidfile(void) */ int kill_other(int signal) { - int pid; - cp(); - pid = read_pid(pidfilename); - - if(!pid) - { - if(netname) - fprintf(stderr, _("No other tincd is running for net `%s'.\n"), netname); - else - fprintf(stderr, _("No other tincd is running.\n")); - return 1; - } - - errno = 0; /* No error, sometimes errno is only changed on error */ - /* ESRCH is returned when no process with that pid is found */ - if(kill(pid, signal) && errno == ESRCH) - { - if(netname) - fprintf(stderr, _("The tincd for net `%s' is no longer running. "), netname); - else - fprintf(stderr, _("The tincd is no longer running. ")); - - fprintf(stderr, _("Removing stale lock file.\n")); - remove_pid(pidfilename); - } - cp(); - return 0; + int pid; + + cp(); + + pid = read_pid(pidfilename); + + if(!pid) { + if(netname) + fprintf(stderr, _("No other tincd is running for net `%s'.\n"), + netname); + else + fprintf(stderr, _("No other tincd is running.\n")); + return 1; + } + + errno = 0; /* No error, sometimes errno is only changed on error */ + + /* ESRCH is returned when no process with that pid is found */ + if(kill(pid, signal) && errno == ESRCH) { + if(netname) + fprintf(stderr, _("The tincd for net `%s' is no longer running. "), + netname); + else + fprintf(stderr, _("The tincd is no longer running. ")); + + fprintf(stderr, _("Removing stale lock file.\n")); + remove_pid(pidfilename); + } + + return 0; } /* @@ -168,69 +173,73 @@ int kill_other(int signal) */ int detach(void) { - cp(); - setup_signals(); + cp(); - /* First check if we can open a fresh new pidfile */ - - if(write_pidfile()) - return -1; + setup_signals(); - /* If we succeeded in doing that, detach */ + /* First check if we can open a fresh new pidfile */ - closelog(); + if(write_pidfile()) + return -1; - if(do_detach) - { - if(daemon(0, 0) < 0) - { - fprintf(stderr, _("Couldn't detach from terminal: %s"), strerror(errno)); - return -1; + /* If we succeeded in doing that, detach */ + + closelog(); + + if(do_detach) { + if(daemon(0, 0) < 0) { + fprintf(stderr, _("Couldn't detach from terminal: %s"), + strerror(errno)); + return -1; + } + + /* Now UPDATE the pid in the pidfile, because we changed it... */ + + if(!write_pid(pidfilename)) + return -1; } - /* Now UPDATE the pid in the pidfile, because we changed it... */ - - if(!write_pid(pidfilename)) - return -1; - } - - openlog(identname, LOG_CONS | LOG_PID, LOG_DAEMON); - - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("tincd %s (%s %s) starting, debug level %d"), - VERSION, __DATE__, __TIME__, debug_lvl); - else - syslog(LOG_NOTICE, _("tincd %s starting"), VERSION); - - xalloc_fail_func = memory_full; - cp(); - return 0; + openlog(identname, LOG_CONS | LOG_PID, LOG_DAEMON); + + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("tincd %s (%s %s) starting, debug level %d"), + VERSION, __DATE__, __TIME__, debug_lvl); + else + syslog(LOG_NOTICE, _("tincd %s starting"), VERSION); + + xalloc_fail_func = memory_full; + + return 0; } /* Execute the program name, with sane environment. All output will be redirected to syslog. */ -void _execute_script(const char *scriptname, char **envp) __attribute__ ((noreturn)); +void _execute_script(const char *scriptname, char **envp) + __attribute__ ((noreturn)); void _execute_script(const char *scriptname, char **envp) { - char *s; - cp(); - while(*envp) - putenv(*envp++); - - chdir("/"); - - /* Close all file descriptors */ - closelog(); /* <- this means we cannot use syslog() here anymore! */ - fcloseall(); - - execl(scriptname, NULL); - /* No return on success */ - - openlog("tinc", LOG_CONS | LOG_PID, LOG_DAEMON); - syslog(LOG_ERR, _("Could not execute `%s': %s"), scriptname, strerror(errno)); - exit(errno); + char *s; + + cp(); + + while(*envp) + putenv(*envp++); + + chdir("/"); + + /* Close all file descriptors */ + closelog(); /* <- this means we cannot use syslog() here anymore! */ + fcloseall(); + + execl(scriptname, NULL); + /* No return on success */ + + openlog("tinc", LOG_CONS | LOG_PID, LOG_DAEMON); + syslog(LOG_ERR, _("Could not execute `%s': %s"), scriptname, + strerror(errno)); + exit(errno); } /* @@ -238,67 +247,62 @@ void _execute_script(const char *scriptname, char **envp) */ int execute_script(const char *name, char **envp) { - pid_t pid; - int status; - struct stat s; - char *scriptname; - cp(); - asprintf(&scriptname, "%s/%s", confbase, name); - - /* First check if there is a script */ - - if(stat(scriptname, &s)) - return 0; - - pid = fork(); - - if(pid < 0) - { - syslog(LOG_ERR, _("System call `%s' failed: %s"), "fork", strerror(errno)); - return -1; - } - - if(pid) - { - if(debug_lvl >= DEBUG_STATUS) - syslog(LOG_INFO, _("Executing script %s"), name); - - free(scriptname); - - if(waitpid(pid, &status, 0) == pid) - { - if(WIFEXITED(status)) /* Child exited by itself */ - { - if(WEXITSTATUS(status)) - { - syslog(LOG_ERR, _("Process %d (%s) exited with non-zero status %d"), pid, name, WEXITSTATUS(status)); - return -1; - } - else - return 0; - } - else if(WIFSIGNALED(status)) /* Child was killed by a signal */ - { - syslog(LOG_ERR, _("Process %d (%s) was killed by signal %d (%s)"), - pid, name, WTERMSIG(status), strsignal(WTERMSIG(status))); - return -1; - } - else /* Something strange happened */ - { - syslog(LOG_ERR, _("Process %d (%s) terminated abnormally"), pid, name); - return -1; - } - } - else - { - syslog(LOG_ERR, _("System call `%s' failed: %s"), "waitpid", strerror(errno)); - return -1; - } - } - cp(); - /* Child here */ - - _execute_script(scriptname, envp); + pid_t pid; + int status; + struct stat s; + char *scriptname; + + cp(); + + asprintf(&scriptname, "%s/%s", confbase, name); + + /* First check if there is a script */ + + if(stat(scriptname, &s)) + return 0; + + pid = fork(); + + if(pid < 0) { + syslog(LOG_ERR, _("System call `%s' failed: %s"), "fork", + strerror(errno)); + return -1; + } + + if(pid) { + if(debug_lvl >= DEBUG_STATUS) + syslog(LOG_INFO, _("Executing script %s"), name); + + free(scriptname); + + if(waitpid(pid, &status, 0) == pid) { + if(WIFEXITED(status)) { /* Child exited by itself */ + if(WEXITSTATUS(status)) { + syslog(LOG_ERR, _("Process %d (%s) exited with non-zero status %d"), + pid, name, WEXITSTATUS(status)); + return -1; + } else + return 0; + } else if(WIFSIGNALED(status)) { /* Child was killed by a signal */ + syslog(LOG_ERR, _("Process %d (%s) was killed by signal %d (%s)"), pid, + name, WTERMSIG(status), strsignal(WTERMSIG(status))); + return -1; + } else { /* Something strange happened */ + + syslog(LOG_ERR, _("Process %d (%s) terminated abnormally"), pid, + name); + return -1; + } + } else { + syslog(LOG_ERR, _("System call `%s' failed: %s"), "waitpid", + strerror(errno)); + return -1; + } + } + + /* Child here */ + + _execute_script(scriptname, envp); } @@ -306,186 +310,171 @@ int execute_script(const char *name, char **envp) Signal handlers. */ -RETSIGTYPE -sigterm_handler(int a) +RETSIGTYPE sigterm_handler(int a) { - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("Got TERM signal")); + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("Got TERM signal")); - cleanup_and_exit(0); + cleanup_and_exit(0); } -RETSIGTYPE -sigquit_handler(int a) +RETSIGTYPE sigquit_handler(int a) { - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("Got QUIT signal")); - cleanup_and_exit(0); + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("Got QUIT signal")); + cleanup_and_exit(0); } -RETSIGTYPE -fatal_signal_square(int a) +RETSIGTYPE fatal_signal_square(int a) { - syslog(LOG_ERR, _("Got another fatal signal %d (%s): not restarting."), a, strsignal(a)); - cp_trace(); - exit(1); + syslog(LOG_ERR, _("Got another fatal signal %d (%s): not restarting."), a, + strsignal(a)); + cp_trace(); + exit(1); } -RETSIGTYPE -fatal_signal_handler(int a) +RETSIGTYPE fatal_signal_handler(int a) { - struct sigaction act; - syslog(LOG_ERR, _("Got fatal signal %d (%s)"), a, strsignal(a)); - cp_trace(); - - if(do_detach) - { - syslog(LOG_NOTICE, _("Trying to re-execute in 5 seconds...")); - - act.sa_handler = fatal_signal_square; - act.sa_mask = emptysigset; - act.sa_flags = 0; - sigaction(SIGSEGV, &act, NULL); - - close_network_connections(); - sleep(5); - remove_pid(pidfilename); - execvp(g_argv[0], g_argv); - } - else - { - syslog(LOG_NOTICE, _("Not restarting.")); - exit(1); - } + struct sigaction act; + syslog(LOG_ERR, _("Got fatal signal %d (%s)"), a, strsignal(a)); + cp_trace(); + + if(do_detach) { + syslog(LOG_NOTICE, _("Trying to re-execute in 5 seconds...")); + + act.sa_handler = fatal_signal_square; + act.sa_mask = emptysigset; + act.sa_flags = 0; + sigaction(SIGSEGV, &act, NULL); + + close_network_connections(); + sleep(5); + remove_pid(pidfilename); + execvp(g_argv[0], g_argv); + } else { + syslog(LOG_NOTICE, _("Not restarting.")); + exit(1); + } } -RETSIGTYPE -sighup_handler(int a) +RETSIGTYPE sighup_handler(int a) { - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("Got HUP signal")); - sighup = 1; + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("Got HUP signal")); + sighup = 1; } -RETSIGTYPE -sigint_handler(int a) +RETSIGTYPE sigint_handler(int a) { - if(saved_debug_lvl) - { - syslog(LOG_NOTICE, _("Reverting to old debug level (%d)"), - saved_debug_lvl); - debug_lvl = saved_debug_lvl; - saved_debug_lvl = 0; - } - else - { - syslog(LOG_NOTICE, _("Temporarily setting debug level to 5. Kill me with SIGINT again to go back to level %d."), - debug_lvl); - saved_debug_lvl = debug_lvl; - debug_lvl = 5; - } + if(saved_debug_lvl) { + syslog(LOG_NOTICE, _("Reverting to old debug level (%d)"), + saved_debug_lvl); + debug_lvl = saved_debug_lvl; + saved_debug_lvl = 0; + } else { + syslog(LOG_NOTICE, + _ + ("Temporarily setting debug level to 5. Kill me with SIGINT again to go back to level %d."), + debug_lvl); + saved_debug_lvl = debug_lvl; + debug_lvl = 5; + } } -RETSIGTYPE -sigalrm_handler(int a) +RETSIGTYPE sigalrm_handler(int a) { - if(debug_lvl > DEBUG_NOTHING) - syslog(LOG_NOTICE, _("Got ALRM signal")); - sigalrm = 1; + if(debug_lvl > DEBUG_NOTHING) + syslog(LOG_NOTICE, _("Got ALRM signal")); + sigalrm = 1; } -RETSIGTYPE -sigusr1_handler(int a) +RETSIGTYPE sigusr1_handler(int a) { - dump_connections(); + dump_connections(); } -RETSIGTYPE -sigusr2_handler(int a) +RETSIGTYPE sigusr2_handler(int a) { - dump_device_stats(); - dump_nodes(); - dump_edges(); - dump_subnets(); + dump_device_stats(); + dump_nodes(); + dump_edges(); + dump_subnets(); } -RETSIGTYPE -sigwinch_handler(int a) +RETSIGTYPE sigwinch_handler(int a) { - extern int do_purge; - do_purge = 1; + extern int do_purge; + do_purge = 1; } -RETSIGTYPE -unexpected_signal_handler(int a) +RETSIGTYPE unexpected_signal_handler(int a) { - syslog(LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a)); - cp_trace(); + syslog(LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a)); + cp_trace(); } -RETSIGTYPE -ignore_signal_handler(int a) +RETSIGTYPE ignore_signal_handler(int a) { - if(debug_lvl >= DEBUG_SCARY_THINGS) - { - syslog(LOG_DEBUG, _("Ignored signal %d (%s)"), a, strsignal(a)); - cp_trace(); - } + if(debug_lvl >= DEBUG_SCARY_THINGS) { + syslog(LOG_DEBUG, _("Ignored signal %d (%s)"), a, strsignal(a)); + cp_trace(); + } } struct { - int signal; - void (*handler)(int); + int signal; + void (*handler) (int); } sighandlers[] = { - { SIGHUP, sighup_handler }, - { SIGTERM, sigterm_handler }, - { SIGQUIT, sigquit_handler }, - { SIGSEGV, fatal_signal_handler }, - { SIGBUS, fatal_signal_handler }, - { SIGILL, fatal_signal_handler }, - { SIGPIPE, ignore_signal_handler }, - { SIGINT, sigint_handler }, - { SIGUSR1, sigusr1_handler }, - { SIGUSR2, sigusr2_handler }, - { SIGCHLD, ignore_signal_handler }, - { SIGALRM, sigalrm_handler }, - { SIGWINCH, sigwinch_handler }, - { 0, NULL } + { + SIGHUP, sighup_handler}, { + SIGTERM, sigterm_handler}, { + SIGQUIT, sigquit_handler}, { + SIGSEGV, fatal_signal_handler}, { + SIGBUS, fatal_signal_handler}, { + SIGILL, fatal_signal_handler}, { + SIGPIPE, ignore_signal_handler}, { + SIGINT, sigint_handler}, { + SIGUSR1, sigusr1_handler}, { + SIGUSR2, sigusr2_handler}, { + SIGCHLD, ignore_signal_handler}, { + SIGALRM, sigalrm_handler}, { + SIGWINCH, sigwinch_handler}, { + 0, NULL} }; -void -setup_signals(void) +void setup_signals(void) { - int i; - struct sigaction act; - - sigemptyset(&emptysigset); - act.sa_handler = NULL; - act.sa_mask = emptysigset; - act.sa_flags = 0; - - /* Set a default signal handler for every signal, errors will be - ignored. */ - for(i = 0; i < NSIG; i++) - { - if(!do_detach) - act.sa_handler = SIG_DFL; - else - act.sa_handler = unexpected_signal_handler; - sigaction(i, &act, NULL); - } - - /* If we didn't detach, allow coredumps */ - if(!do_detach) - sighandlers[3].handler = SIG_DFL; - - /* Then, for each known signal that we want to catch, assign a - handler to the signal, with error checking this time. */ - for(i = 0; sighandlers[i].signal; i++) - { - act.sa_handler = sighandlers[i].handler; - if(sigaction(sighandlers[i].signal, &act, NULL) < 0) - fprintf(stderr, _("Installing signal handler for signal %d (%s) failed: %s\n"), - sighandlers[i].signal, strsignal(sighandlers[i].signal), strerror(errno)); - } + int i; + struct sigaction act; + + sigemptyset(&emptysigset); + act.sa_handler = NULL; + act.sa_mask = emptysigset; + act.sa_flags = 0; + + /* Set a default signal handler for every signal, errors will be + ignored. */ + for(i = 0; i < NSIG; i++) { + if(!do_detach) + act.sa_handler = SIG_DFL; + else + act.sa_handler = unexpected_signal_handler; + sigaction(i, &act, NULL); + } + + /* If we didn't detach, allow coredumps */ + if(!do_detach) + sighandlers[3].handler = SIG_DFL; + + /* Then, for each known signal that we want to catch, assign a + handler to the signal, with error checking this time. */ + for(i = 0; sighandlers[i].signal; i++) { + act.sa_handler = sighandlers[i].handler; + if(sigaction(sighandlers[i].signal, &act, NULL) < 0) + fprintf(stderr, + _ + ("Installing signal handler for signal %d (%s) failed: %s\n"), + sighandlers[i].signal, strsignal(sighandlers[i].signal), + strerror(errno)); + } } diff --git a/src/process.h b/src/process.h index 6620489..dd794e4 100644 --- a/src/process.h +++ b/src/process.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: process.h,v 1.1.2.12 2002/07/10 11:27:06 guus Exp $ + $Id: process.h,v 1.1.2.13 2002/09/09 21:24:41 guus Exp $ */ #ifndef __TINC_PROCESS_H__ @@ -33,4 +33,4 @@ extern int detach(void); extern int kill_other(int); extern void cleanup_and_exit(int); -#endif /* __TINC_PROCESS_H__ */ +#endif /* __TINC_PROCESS_H__ */ diff --git a/src/protocol.c b/src/protocol.c index 7a7e901..565087c 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: protocol.c,v 1.28.4.135 2002/09/09 19:39:59 guus Exp $ + $Id: protocol.c,v 1.28.4.136 2002/09/09 21:24:41 guus Exp $ */ #include "config.h" @@ -45,221 +45,221 @@ avl_tree_t *past_request_tree; int check_id(char *id) { - int i; + int i; - for (i = 0; i < strlen(id); i++) - if(!isalnum(id[i]) && id[i] != '_') - return -1; - - return 0; + for(i = 0; i < strlen(id); i++) + if(!isalnum(id[i]) && id[i] != '_') + return -1; + + return 0; } /* Generic request routines - takes care of logging and error detection as well */ -int send_request(connection_t *c, const char *format, ...) +int send_request(connection_t * c, const char *format, ...) { - va_list args; - char buffer[MAXBUFSIZE]; - int len, request; - - cp(); - /* Use vsnprintf instead of vasprintf: faster, no memory - fragmentation, cleanup is automatic, and there is a limit on the - input buffer anyway */ - - va_start(args, format); - len = vsnprintf(buffer, MAXBUFSIZE, format, args); - va_end(args); - - if(len < 0 || len > MAXBUFSIZE-1) - { - syslog(LOG_ERR, _("Output buffer overflow while sending request to %s (%s)"), c->name, c->hostname); - return -1; - } - - if(debug_lvl >= DEBUG_PROTOCOL) - { - sscanf(buffer, "%d", &request); - if(debug_lvl >= DEBUG_META) - syslog(LOG_DEBUG, _("Sending %s to %s (%s): %s"), request_name[request], c->name, c->hostname, buffer); - else - syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], c->name, c->hostname); - } - - buffer[len++] = '\n'; - cp(); - if(c == broadcast) - return broadcast_meta(NULL, buffer, len); - else - return send_meta(c, buffer, len); + va_list args; + char buffer[MAXBUFSIZE]; + int len, request; + + cp(); + + /* Use vsnprintf instead of vasprintf: faster, no memory + fragmentation, cleanup is automatic, and there is a limit on the + input buffer anyway */ + + va_start(args, format); + len = vsnprintf(buffer, MAXBUFSIZE, format, args); + va_end(args); + + if(len < 0 || len > MAXBUFSIZE - 1) { + syslog(LOG_ERR, _("Output buffer overflow while sending request to %s (%s)"), + c->name, c->hostname); + return -1; + } + + if(debug_lvl >= DEBUG_PROTOCOL) { + sscanf(buffer, "%d", &request); + if(debug_lvl >= DEBUG_META) + syslog(LOG_DEBUG, _("Sending %s to %s (%s): %s"), + request_name[request], c->name, c->hostname, buffer); + else + syslog(LOG_DEBUG, _("Sending %s to %s (%s)"), request_name[request], + c->name, c->hostname); + } + + buffer[len++] = '\n'; + + if(c == broadcast) + return broadcast_meta(NULL, buffer, len); + else + return send_meta(c, buffer, len); } -int forward_request(connection_t *from) +int forward_request(connection_t * from) { - int request; - cp(); - if(debug_lvl >= DEBUG_PROTOCOL) - { - sscanf(from->buffer, "%d", &request); - if(debug_lvl >= DEBUG_META) - syslog(LOG_DEBUG, _("Forwarding %s from %s (%s): %s"), request_name[request], from->name, from->hostname, from->buffer); - else - syslog(LOG_DEBUG, _("Forwarding %s from %s (%s)"), request_name[request], from->name, from->hostname); - } - - from->buffer[from->reqlen - 1] = '\n'; - cp(); - return broadcast_meta(from, from->buffer, from->reqlen); + int request; + cp(); + + cp(); + + if(debug_lvl >= DEBUG_PROTOCOL) { + sscanf(from->buffer, "%d", &request); + if(debug_lvl >= DEBUG_META) + syslog(LOG_DEBUG, _("Forwarding %s from %s (%s): %s"), + request_name[request], from->name, from->hostname, + from->buffer); + else + syslog(LOG_DEBUG, _("Forwarding %s from %s (%s)"), + request_name[request], from->name, from->hostname); + } + + from->buffer[from->reqlen - 1] = '\n'; + + return broadcast_meta(from, from->buffer, from->reqlen); } -int receive_request(connection_t *c) +int receive_request(connection_t * c) { - int request; - cp(); - if(sscanf(c->buffer, "%d", &request) == 1) - { - if((request < 0) || (request >= LAST) || !request_handlers[request]) - { - if(debug_lvl >= DEBUG_META) - syslog(LOG_DEBUG, _("Unknown request from %s (%s): %s"), - c->name, c->hostname, c->buffer); - else - syslog(LOG_ERR, _("Unknown request from %s (%s)"), - c->name, c->hostname); - - return -1; - } - else - { - if(debug_lvl >= DEBUG_PROTOCOL) - { - if(debug_lvl >= DEBUG_META) - syslog(LOG_DEBUG, _("Got %s from %s (%s): %s"), - request_name[request], c->name, c->hostname, c->buffer); - else - syslog(LOG_DEBUG, _("Got %s from %s (%s)"), - request_name[request], c->name, c->hostname); - } + int request; + + cp(); + + if(sscanf(c->buffer, "%d", &request) == 1) { + if((request < 0) || (request >= LAST) || !request_handlers[request]) { + if(debug_lvl >= DEBUG_META) + syslog(LOG_DEBUG, _("Unknown request from %s (%s): %s"), + c->name, c->hostname, c->buffer); + else + syslog(LOG_ERR, _("Unknown request from %s (%s)"), + c->name, c->hostname); + + return -1; + } else { + if(debug_lvl >= DEBUG_PROTOCOL) { + if(debug_lvl >= DEBUG_META) + syslog(LOG_DEBUG, _("Got %s from %s (%s): %s"), + request_name[request], c->name, c->hostname, + c->buffer); + else + syslog(LOG_DEBUG, _("Got %s from %s (%s)"), + request_name[request], c->name, c->hostname); + } + } + + if((c->allow_request != ALL) && (c->allow_request != request)) { + syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), c->name, + c->hostname); + return -1; + } + + if(request_handlers[request] (c)) + /* Something went wrong. Probably scriptkiddies. Terminate. */ + { + syslog(LOG_ERR, _("Error while processing %s from %s (%s)"), + request_name[request], c->name, c->hostname); + return -1; + } + } else { + syslog(LOG_ERR, _("Bogus data received from %s (%s)"), + c->name, c->hostname); + return -1; } - if((c->allow_request != ALL) && (c->allow_request != request)) - { - syslog(LOG_ERR, _("Unauthorized request from %s (%s)"), c->name, c->hostname); - return -1; - } - - if(request_handlers[request](c)) - /* Something went wrong. Probably scriptkiddies. Terminate. */ - { - syslog(LOG_ERR, _("Error while processing %s from %s (%s)"), - request_name[request], c->name, c->hostname); - return -1; - } - } - else - { - syslog(LOG_ERR, _("Bogus data received from %s (%s)"), - c->name, c->hostname); - return -1; - } - cp(); - return 0; + return 0; } -int past_request_compare(past_request_t *a, past_request_t *b) +int past_request_compare(past_request_t * a, past_request_t * b) { - cp(); - return strcmp(a->request, b->request); + return strcmp(a->request, b->request); } -void free_past_request(past_request_t *r) +void free_past_request(past_request_t * r) { - cp(); - if(r->request) - free(r->request); - free(r); - cp(); + cp(); + + if(r->request) + free(r->request); + + free(r); } void init_requests(void) { - cp(); - past_request_tree = avl_alloc_tree((avl_compare_t)past_request_compare, (avl_action_t)free_past_request); - cp(); + 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); - cp(); + cp(); + + avl_delete_tree(past_request_tree); } int seen_request(char *request) { - past_request_t p, *new; - cp(); - p.request = request; - - if(avl_search(past_request_tree, &p)) - { - if(debug_lvl >= DEBUG_SCARY_THINGS) - syslog(LOG_DEBUG, _("Already seen request")); - return 1; - } - else - { - new = (past_request_t *)xmalloc(sizeof(*new)); - new->request = xstrdup(request); - new->firstseen = now; - avl_insert(past_request_tree, new); - return 0; - } - cp(); + past_request_t p, *new; + + cp(); + + p.request = request; + + if(avl_search(past_request_tree, &p)) { + if(debug_lvl >= DEBUG_SCARY_THINGS) + syslog(LOG_DEBUG, _("Already seen request")); + return 1; + } else { + new = (past_request_t *) xmalloc(sizeof(*new)); + new->request = xstrdup(request); + new->firstseen = now; + avl_insert(past_request_tree, new); + return 0; + } } void age_past_requests(void) { - avl_node_t *node, *next; - past_request_t *p; - int left = 0, deleted = 0; - cp(); - for(node = past_request_tree->head; node; node = next) - { - next = node->next; - p = (past_request_t *)node->data; - if(p->firstseen + pingtimeout < now) - avl_delete_node(past_request_tree, node), deleted++; - else - left++; - } - - if(debug_lvl >= DEBUG_SCARY_THINGS && left + deleted) - syslog(LOG_DEBUG, _("Aging past requests: deleted %d, left %d\n"), deleted, left); - cp(); + avl_node_t *node, *next; + past_request_t *p; + int left = 0, deleted = 0; + + cp(); + + for(node = past_request_tree->head; node; node = next) { + next = node->next; + p = (past_request_t *) node->data; + + if(p->firstseen + pingtimeout < now) + avl_delete_node(past_request_tree, node), deleted++; + else + left++; + } + + if(debug_lvl >= DEBUG_SCARY_THINGS && left + deleted) + syslog(LOG_DEBUG, _("Aging past requests: deleted %d, left %d\n"), + deleted, left); } /* Jumptable for the request handlers */ -int (*request_handlers[])(connection_t*) = { - id_h, metakey_h, challenge_h, chal_reply_h, ack_h, - status_h, error_h, termreq_h, - ping_h, pong_h, - add_subnet_h, del_subnet_h, - add_edge_h, del_edge_h, - key_changed_h, req_key_h, ans_key_h, - tcppacket_h, +int (*request_handlers[]) (connection_t *) = { + id_h, metakey_h, challenge_h, chal_reply_h, ack_h, + status_h, error_h, termreq_h, + ping_h, pong_h, + add_subnet_h, del_subnet_h, + add_edge_h, del_edge_h, + key_changed_h, req_key_h, ans_key_h, tcppacket_h, }; /* Request names */ char (*request_name[]) = { - "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY", "ACK", - "STATUS", "ERROR", "TERMREQ", - "PING", "PONG", - "ADD_SUBNET", "DEL_SUBNET", - "ADD_EDGE", "DEL_EDGE", - "KEY_CHANGED", "REQ_KEY", "ANS_KEY", - "PACKET", + "ID", "METAKEY", "CHALLENGE", "CHAL_REPLY", "ACK", + "STATUS", "ERROR", "TERMREQ", + "PING", "PONG", + "ADD_SUBNET", "DEL_SUBNET", + "ADD_EDGE", "DEL_EDGE", "KEY_CHANGED", "REQ_KEY", "ANS_KEY", "PACKET", }; diff --git a/src/protocol.h b/src/protocol.h index 47f772c..f782523 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: protocol.h,v 1.5.4.34 2002/09/04 16:26:45 guus Exp $ + $Id: protocol.h,v 1.5.4.35 2002/09/09 21:24:42 guus Exp $ */ #ifndef __TINC_PROTOCOL_H__ @@ -37,21 +37,20 @@ /* Request numbers */ enum { - ALL = -1, /* Guardian for allow_request */ - ID = 0, METAKEY, CHALLENGE, CHAL_REPLY, ACK, - STATUS, ERROR, TERMREQ, - PING, PONG, -// ADD_NODE, DEL_NODE, - ADD_SUBNET, DEL_SUBNET, - ADD_EDGE, DEL_EDGE, - KEY_CHANGED, REQ_KEY, ANS_KEY, - PACKET, - LAST /* Guardian for the highest request number */ + ALL = -1, /* Guardian for allow_request */ + ID = 0, METAKEY, CHALLENGE, CHAL_REPLY, ACK, + STATUS, ERROR, TERMREQ, + PING, PONG, + ADD_SUBNET, DEL_SUBNET, + ADD_EDGE, DEL_EDGE, + KEY_CHANGED, REQ_KEY, ANS_KEY, + PACKET, + LAST /* Guardian for the highest request number */ }; typedef struct past_request_t { - char *request; - time_t firstseen; + char *request; + time_t firstseen; } past_request_t; /* Maximum size of strings in a request */ @@ -61,7 +60,7 @@ typedef struct past_request_t { /* Basic functions */ -extern int send_request(connection_t*, const char*, ...); +extern int send_request(connection_t *, const char *, ...); extern int forward_request(connection_t *); extern int receive_request(connection_t *); extern int check_id(char *); @@ -83,8 +82,6 @@ extern int send_error(connection_t *, int, char *); extern int send_termreq(connection_t *); extern int send_ping(connection_t *); extern int send_pong(connection_t *); -// extern int send_add_node(connection_t *, node_t *); -// extern int send_del_node(connection_t *, node_t *); extern int send_add_subnet(connection_t *, subnet_t *); extern int send_del_subnet(connection_t *, subnet_t *); extern int send_add_edge(connection_t *, edge_t *); @@ -96,7 +93,7 @@ extern int send_tcppacket(connection_t *, vpn_packet_t *); /* Request handlers */ -extern int (*request_handlers[])(connection_t *); +extern int (*request_handlers[]) (connection_t *); extern int id_h(connection_t *); extern int metakey_h(connection_t *); @@ -108,8 +105,6 @@ extern int error_h(connection_t *); extern int termreq_h(connection_t *); extern int ping_h(connection_t *); extern int pong_h(connection_t *); -// extern int add_node_h(connection_t *); -// extern int del_node_h(connection_t *); extern int add_subnet_h(connection_t *); extern int del_subnet_h(connection_t *); extern int add_edge_h(connection_t *); @@ -119,4 +114,4 @@ extern int req_key_h(connection_t *); extern int ans_key_h(connection_t *); extern int tcppacket_h(connection_t *); -#endif /* __TINC_PROTOCOL_H__ */ +#endif /* __TINC_PROTOCOL_H__ */ diff --git a/src/protocol_auth.c b/src/protocol_auth.c index 8fe8b38..fc0c3aa 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: protocol_auth.c,v 1.1.4.15 2002/09/09 19:39:59 guus Exp $ + $Id: protocol_auth.c,v 1.1.4.16 2002/09/09 21:24:45 guus Exp $ */ #include "config.h" @@ -53,533 +53,544 @@ #include "system.h" -int send_id(connection_t *c) +int send_id(connection_t * c) { - cp(); - return send_request(c, "%d %s %d", ID, myself->connection->name, myself->connection->protocol_version); + cp(); + + return send_request(c, "%d %s %d", ID, myself->connection->name, + myself->connection->protocol_version); } -int id_h(connection_t *c) +int id_h(connection_t * c) { - char name[MAX_STRING_SIZE]; - int bla; - cp(); - if(sscanf(c->buffer, "%*d "MAX_STRING" %d", name, &c->protocol_version) != 2) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ID", c->name, c->hostname); - return -1; - } - - /* Check if identity is a valid name */ - - if(check_id(name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ID", c->name, c->hostname, "invalid name"); - return -1; - } - - /* If we set c->name in advance, make sure we are connected to the right host */ - - if(c->name) - { - if(strcmp(c->name, name)) - { - syslog(LOG_ERR, _("Peer %s is %s instead of %s"), c->hostname, name, c->name); - return -1; - } - } - else - c->name = xstrdup(name); - - /* Check if version matches */ - - if(c->protocol_version != myself->connection->protocol_version) - { - syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"), - c->name, c->hostname, c->protocol_version); - return -1; - } - - if(bypass_security) - { - if(!c->config_tree) - init_configuration(&c->config_tree); - c->allow_request = ACK; - return send_ack(c); - } - - if(!c->config_tree) - { - init_configuration(&c->config_tree); - - bla = read_connection_config(c); - - if(bla) - { - syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), c->hostname, c->name); - return -1; - } - } - - if(read_rsa_public_key(c)) - { - return -1; - } - - /* Check some options */ - - if((get_config_bool(lookup_config(c->config_tree, "IndirectData"), &bla) && bla) || myself->options & OPTION_INDIRECT) - c->options |= OPTION_INDIRECT; - - if((get_config_bool(lookup_config(c->config_tree, "TCPOnly"), &bla) && bla) || myself->options & OPTION_TCPONLY) - c->options |= OPTION_TCPONLY | OPTION_INDIRECT; - - c->allow_request = METAKEY; - cp(); - return send_metakey(c); + char name[MAX_STRING_SIZE]; + int bla; + + cp(); + + if(sscanf(c->buffer, "%*d " MAX_STRING " %d", name, &c->protocol_version) != 2) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ID", c->name, + c->hostname); + return -1; + } + + /* Check if identity is a valid name */ + + if(check_id(name)) { + syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ID", c->name, + c->hostname, "invalid name"); + return -1; + } + + /* If we set c->name in advance, make sure we are connected to the right host */ + + if(c->name) { + if(strcmp(c->name, name)) { + syslog(LOG_ERR, _("Peer %s is %s instead of %s"), c->hostname, name, + c->name); + return -1; + } + } else + c->name = xstrdup(name); + + /* Check if version matches */ + + if(c->protocol_version != myself->connection->protocol_version) { + syslog(LOG_ERR, _("Peer %s (%s) uses incompatible version %d"), + c->name, c->hostname, c->protocol_version); + return -1; + } + + if(bypass_security) { + if(!c->config_tree) + init_configuration(&c->config_tree); + c->allow_request = ACK; + return send_ack(c); + } + + if(!c->config_tree) { + init_configuration(&c->config_tree); + + bla = read_connection_config(c); + + if(bla) { + syslog(LOG_ERR, _("Peer %s had unknown identity (%s)"), c->hostname, + c->name); + return -1; + } + } + + if(read_rsa_public_key(c)) { + return -1; + } + + /* Check some options */ + + if((get_config_bool(lookup_config(c->config_tree, "IndirectData"), &bla) && bla) || myself->options & OPTION_INDIRECT) + c->options |= OPTION_INDIRECT; + + if((get_config_bool(lookup_config(c->config_tree, "TCPOnly"), &bla) && bla) || myself->options & OPTION_TCPONLY) + c->options |= OPTION_TCPONLY | OPTION_INDIRECT; + + c->allow_request = METAKEY; + + return send_metakey(c); } -int send_metakey(connection_t *c) +int send_metakey(connection_t * c) { - char buffer[MAX_STRING_SIZE]; - int len, x; - cp(); - len = RSA_size(c->rsa_key); - - /* Allocate buffers for the meta key */ - - if(!c->outkey) - c->outkey = xmalloc(len); - - if(!c->outctx) - c->outctx = xmalloc(sizeof(*c->outctx)); - cp(); - /* Copy random data to the buffer */ - - RAND_bytes(c->outkey, len); - - /* The message we send must be smaller than the modulus of the RSA key. - By definition, for a key of k bits, the following formula holds: - - 2^(k-1) <= modulus < 2^(k) - - Where ^ means "to the power of", not "xor". - This means that to be sure, we must choose our message < 2^(k-1). - This can be done by setting the most significant bit to zero. - */ - - c->outkey[0] &= 0x7F; - - if(debug_lvl >= DEBUG_SCARY_THINGS) - { - bin2hex(c->outkey, buffer, len); - buffer[len*2] = '\0'; - syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), buffer); - } - - /* Encrypt the random data - - We do not use one of the PKCS padding schemes here. - This is allowed, because we encrypt a totally random string - with a length equal to that of the modulus of the RSA key. - */ - - if(RSA_public_encrypt(len, c->outkey, buffer, c->rsa_key, RSA_NO_PADDING) != len) - { - syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), c->name, c->hostname); - return -1; - } - cp(); - /* Convert the encrypted random data to a hexadecimal formatted string */ - - bin2hex(buffer, buffer, len); - buffer[len*2] = '\0'; - - /* Send the meta key */ - - x = send_request(c, "%d %d %d %d %d %s", METAKEY, - c->outcipher?c->outcipher->nid:0, c->outdigest?c->outdigest->type:0, - c->outmaclength, c->outcompression, buffer); - - /* Further outgoing requests are encrypted with the key we just generated */ - - if(c->outcipher) - { - EVP_EncryptInit(c->outctx, c->outcipher, - c->outkey + len - c->outcipher->key_len, - c->outkey + len - c->outcipher->key_len - c->outcipher->iv_len); - - c->status.encryptout = 1; - } - cp(); - return x; + char buffer[MAX_STRING_SIZE]; + int len, x; + + cp(); + + len = RSA_size(c->rsa_key); + + /* Allocate buffers for the meta key */ + + if(!c->outkey) + c->outkey = xmalloc(len); + + if(!c->outctx) + c->outctx = xmalloc(sizeof(*c->outctx)); + cp(); + /* Copy random data to the buffer */ + + RAND_bytes(c->outkey, len); + + /* The message we send must be smaller than the modulus of the RSA key. + By definition, for a key of k bits, the following formula holds: + + 2^(k-1) <= modulus < 2^(k) + + Where ^ means "to the power of", not "xor". + This means that to be sure, we must choose our message < 2^(k-1). + This can be done by setting the most significant bit to zero. + */ + + c->outkey[0] &= 0x7F; + + if(debug_lvl >= DEBUG_SCARY_THINGS) { + bin2hex(c->outkey, buffer, len); + buffer[len * 2] = '\0'; + syslog(LOG_DEBUG, _("Generated random meta key (unencrypted): %s"), + buffer); + } + + /* Encrypt the random data + + We do not use one of the PKCS padding schemes here. + This is allowed, because we encrypt a totally random string + with a length equal to that of the modulus of the RSA key. + */ + + if(RSA_public_encrypt(len, c->outkey, buffer, c->rsa_key, RSA_NO_PADDING) != len) { + syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), + c->name, c->hostname); + return -1; + } + + /* Convert the encrypted random data to a hexadecimal formatted string */ + + bin2hex(buffer, buffer, len); + buffer[len * 2] = '\0'; + + /* Send the meta key */ + + x = send_request(c, "%d %d %d %d %d %s", METAKEY, + c->outcipher ? c->outcipher->nid : 0, + c->outdigest ? c->outdigest->type : 0, c->outmaclength, + c->outcompression, buffer); + + /* Further outgoing requests are encrypted with the key we just generated */ + + if(c->outcipher) { + EVP_EncryptInit(c->outctx, c->outcipher, + c->outkey + len - c->outcipher->key_len, + c->outkey + len - c->outcipher->key_len - + c->outcipher->iv_len); + + c->status.encryptout = 1; + } + + return x; } -int metakey_h(connection_t *c) +int metakey_h(connection_t * c) { - char buffer[MAX_STRING_SIZE]; - 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) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "METAKEY", c->name, c->hostname); - return -1; - } - cp(); - len = RSA_size(myself->connection->rsa_key); - - /* Check if the length of the meta key is all right */ - - if(strlen(buffer) != len*2) - { - syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, "wrong keylength"); - return -1; - } - - /* Allocate buffers for the meta key */ - cp(); - if(!c->inkey) - c->inkey = xmalloc(len); - - if(!c->inctx) - c->inctx = xmalloc(sizeof(*c->inctx)); - - /* Convert the challenge from hexadecimal back to binary */ - cp(); - hex2bin(buffer,buffer,len); - - /* Decrypt the meta key */ - cp(); - if(RSA_private_decrypt(len, buffer, c->inkey, myself->connection->rsa_key, RSA_NO_PADDING) != len) /* See challenge() */ - { - syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), c->name, c->hostname); - return -1; - } - - if(debug_lvl >= DEBUG_SCARY_THINGS) - { - bin2hex(c->inkey, buffer, len); - buffer[len*2] = '\0'; - syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), buffer); - } - - /* All incoming requests will now be encrypted. */ - cp(); - /* Check and lookup cipher and digest algorithms */ - - if(cipher) - { - c->incipher = EVP_get_cipherbynid(cipher); - if(!c->incipher) - { - syslog(LOG_ERR, _("%s (%s) uses unknown cipher!"), c->name, c->hostname); - return -1; + char buffer[MAX_STRING_SIZE]; + 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) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "METAKEY", c->name, + c->hostname); + return -1; + } + + len = RSA_size(myself->connection->rsa_key); + + /* Check if the length of the meta key is all right */ + + if(strlen(buffer) != len * 2) { + syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, + c->hostname, "wrong keylength"); + return -1; + } + + /* Allocate buffers for the meta key */ + + if(!c->inkey) + c->inkey = xmalloc(len); + + if(!c->inctx) + c->inctx = xmalloc(sizeof(*c->inctx)); + + /* Convert the challenge from hexadecimal back to binary */ + + hex2bin(buffer, buffer, len); + + /* Decrypt the meta key */ + + if(RSA_private_decrypt(len, buffer, c->inkey, myself->connection->rsa_key, RSA_NO_PADDING) != len) { /* See challenge() */ + syslog(LOG_ERR, _("Error during encryption of meta key for %s (%s)"), + c->name, c->hostname); + return -1; + } + + if(debug_lvl >= DEBUG_SCARY_THINGS) { + bin2hex(c->inkey, buffer, len); + buffer[len * 2] = '\0'; + syslog(LOG_DEBUG, _("Received random meta key (unencrypted): %s"), + buffer); } - EVP_DecryptInit(c->inctx, c->incipher, - c->inkey + len - c->incipher->key_len, - c->inkey + len - c->incipher->key_len - c->incipher->iv_len); - - c->status.decryptin = 1; - } - else - { - c->incipher = NULL; - } - - c->inmaclength = maclength; - - if(digest) - { - c->indigest = EVP_get_digestbynid(digest); - if(!c->indigest) - { - syslog(LOG_ERR, _("Node %s (%s) uses unknown digest!"), c->name, c->hostname); - return -1; + /* All incoming requests will now be encrypted. */ + + /* Check and lookup cipher and digest algorithms */ + + if(cipher) { + c->incipher = EVP_get_cipherbynid(cipher); + + if(!c->incipher) { + syslog(LOG_ERR, _("%s (%s) uses unknown cipher!"), c->name, + c->hostname); + return -1; + } + + EVP_DecryptInit(c->inctx, c->incipher, + c->inkey + len - c->incipher->key_len, + c->inkey + len - c->incipher->key_len - + c->incipher->iv_len); + + c->status.decryptin = 1; + } else { + c->incipher = NULL; } - - if(c->inmaclength > c->indigest->md_size || c->inmaclength < 0) - { - syslog(LOG_ERR, _("%s (%s) uses bogus MAC length!"), c->name, c->hostname); - return -1; + + c->inmaclength = maclength; + + if(digest) { + c->indigest = EVP_get_digestbynid(digest); + + if(!c->indigest) { + syslog(LOG_ERR, _("Node %s (%s) uses unknown digest!"), c->name, + c->hostname); + return -1; + } + + if(c->inmaclength > c->indigest->md_size || c->inmaclength < 0) { + syslog(LOG_ERR, _("%s (%s) uses bogus MAC length!"), c->name, + c->hostname); + return -1; + } + } else { + c->indigest = NULL; } - } - else - { - c->indigest = NULL; - } - c->incompression = compression; + c->incompression = compression; + + c->allow_request = CHALLENGE; - c->allow_request = CHALLENGE; - cp(); - return send_challenge(c); + return send_challenge(c); } -int send_challenge(connection_t *c) +int send_challenge(connection_t * c) { - char buffer[MAX_STRING_SIZE]; - int len, x; - cp(); - /* CHECKME: what is most reasonable value for len? */ + char buffer[MAX_STRING_SIZE]; + int len, x; - len = RSA_size(c->rsa_key); + cp(); - /* Allocate buffers for the challenge */ + /* CHECKME: what is most reasonable value for len? */ - if(!c->hischallenge) - c->hischallenge = xmalloc(len); - cp(); - /* Copy random data to the buffer */ + len = RSA_size(c->rsa_key); - RAND_bytes(c->hischallenge, len); + /* Allocate buffers for the challenge */ - cp(); - /* Convert to hex */ + if(!c->hischallenge) + c->hischallenge = xmalloc(len); - bin2hex(c->hischallenge, buffer, len); - buffer[len*2] = '\0'; + /* Copy random data to the buffer */ - cp(); - /* Send the challenge */ + RAND_bytes(c->hischallenge, len); - x = send_request(c, "%d %s", CHALLENGE, buffer); - cp(); - return x; + /* Convert to hex */ + + bin2hex(c->hischallenge, buffer, len); + buffer[len * 2] = '\0'; + + /* Send the challenge */ + + x = send_request(c, "%d %s", CHALLENGE, buffer); + + return x; } -int challenge_h(connection_t *c) +int challenge_h(connection_t * c) { - char buffer[MAX_STRING_SIZE]; - int len; - cp(); - if(sscanf(c->buffer, "%*d "MAX_STRING, buffer) != 1) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "CHALLENGE", c->name, c->hostname); - return -1; - } + char buffer[MAX_STRING_SIZE]; + int len; - len = RSA_size(myself->connection->rsa_key); + cp(); - /* Check if the length of the challenge is all right */ + if(sscanf(c->buffer, "%*d " MAX_STRING, buffer) != 1) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "CHALLENGE", c->name, + c->hostname); + return -1; + } + + len = RSA_size(myself->connection->rsa_key); - if(strlen(buffer) != len*2) - { - syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, "wrong challenge length"); - return -1; - } + /* Check if the length of the challenge is all right */ + + if(strlen(buffer) != len * 2) { + syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, + c->hostname, "wrong challenge length"); + return -1; + } - /* Allocate buffers for the challenge */ + /* Allocate buffers for the challenge */ - if(!c->mychallenge) - c->mychallenge = xmalloc(len); + if(!c->mychallenge) + c->mychallenge = xmalloc(len); - /* Convert the challenge from hexadecimal back to binary */ + /* Convert the challenge from hexadecimal back to binary */ - hex2bin(buffer,c->mychallenge,len); + hex2bin(buffer, c->mychallenge, len); - c->allow_request = CHAL_REPLY; + c->allow_request = CHAL_REPLY; - /* Rest is done by send_chal_reply() */ - cp(); - return send_chal_reply(c); + /* Rest is done by send_chal_reply() */ + + return send_chal_reply(c); } -int send_chal_reply(connection_t *c) +int send_chal_reply(connection_t * c) { - char hash[EVP_MAX_MD_SIZE*2+1]; - EVP_MD_CTX ctx; - cp(); - /* Calculate the hash from the challenge we received */ + char hash[EVP_MAX_MD_SIZE * 2 + 1]; + EVP_MD_CTX ctx; + + cp(); - EVP_DigestInit(&ctx, c->indigest); - EVP_DigestUpdate(&ctx, c->mychallenge, RSA_size(myself->connection->rsa_key)); - EVP_DigestFinal(&ctx, hash, NULL); + /* Calculate the hash from the challenge we received */ - /* Convert the hash to a hexadecimal formatted string */ + EVP_DigestInit(&ctx, c->indigest); + EVP_DigestUpdate(&ctx, c->mychallenge, + RSA_size(myself->connection->rsa_key)); + EVP_DigestFinal(&ctx, hash, NULL); - bin2hex(hash,hash,c->indigest->md_size); - hash[c->indigest->md_size*2] = '\0'; + /* Convert the hash to a hexadecimal formatted string */ - /* Send the reply */ + bin2hex(hash, hash, c->indigest->md_size); + hash[c->indigest->md_size * 2] = '\0'; - cp(); - return send_request(c, "%d %s", CHAL_REPLY, hash); + /* Send the reply */ + + return send_request(c, "%d %s", CHAL_REPLY, hash); } -int chal_reply_h(connection_t *c) +int chal_reply_h(connection_t * c) { - char hishash[MAX_STRING_SIZE]; - char myhash[EVP_MAX_MD_SIZE]; - EVP_MD_CTX ctx; - cp(); - if(sscanf(c->buffer, "%*d "MAX_STRING, hishash) != 1) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "CHAL_REPLY", c->name, c->hostname); - return -1; - } - - /* Check if the length of the hash is all right */ - - if(strlen(hishash) != c->outdigest->md_size*2) - { - syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, _("wrong challenge reply length")); - return -1; - } - - /* Convert the hash to binary format */ - - hex2bin(hishash, hishash, c->outdigest->md_size); - - /* Calculate the hash from the challenge we sent */ - - EVP_DigestInit(&ctx, c->outdigest); - EVP_DigestUpdate(&ctx, c->hischallenge, RSA_size(c->rsa_key)); - EVP_DigestFinal(&ctx, myhash, NULL); - - /* Verify the incoming hash with the calculated hash */ - - if(memcmp(hishash, myhash, c->outdigest->md_size)) - { - syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, c->hostname, _("wrong challenge reply")); - if(debug_lvl >= DEBUG_SCARY_THINGS) - { - bin2hex(myhash, hishash, SHA_DIGEST_LENGTH); - hishash[SHA_DIGEST_LENGTH*2] = '\0'; - syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash); - } - return -1; - } - - /* Identity has now been positively verified. - Send an acknowledgement with the rest of the information needed. - */ - - c->allow_request = ACK; - cp(); - return send_ack(c); + char hishash[MAX_STRING_SIZE]; + char myhash[EVP_MAX_MD_SIZE]; + EVP_MD_CTX ctx; + + cp(); + + if(sscanf(c->buffer, "%*d " MAX_STRING, hishash) != 1) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "CHAL_REPLY", c->name, + c->hostname); + return -1; + } + + /* Check if the length of the hash is all right */ + + if(strlen(hishash) != c->outdigest->md_size * 2) { + syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, + c->hostname, _("wrong challenge reply length")); + return -1; + } + + /* Convert the hash to binary format */ + + hex2bin(hishash, hishash, c->outdigest->md_size); + + /* Calculate the hash from the challenge we sent */ + + EVP_DigestInit(&ctx, c->outdigest); + EVP_DigestUpdate(&ctx, c->hischallenge, RSA_size(c->rsa_key)); + EVP_DigestFinal(&ctx, myhash, NULL); + + /* Verify the incoming hash with the calculated hash */ + + if(memcmp(hishash, myhash, c->outdigest->md_size)) { + syslog(LOG_ERR, _("Possible intruder %s (%s): %s"), c->name, + c->hostname, _("wrong challenge reply")); + + if(debug_lvl >= DEBUG_SCARY_THINGS) { + bin2hex(myhash, hishash, SHA_DIGEST_LENGTH); + hishash[SHA_DIGEST_LENGTH * 2] = '\0'; + syslog(LOG_DEBUG, _("Expected challenge reply: %s"), hishash); + } + + return -1; + } + + /* Identity has now been positively verified. + Send an acknowledgement with the rest of the information needed. + */ + + c->allow_request = ACK; + + return send_ack(c); } -int send_ack(connection_t *c) +int send_ack(connection_t * c) { - /* ACK message contains rest of the information the other end needs - to create node_t and edge_t structures. */ - - int x; - struct timeval now; - cp(); - /* Estimate weight */ - - gettimeofday(&now, NULL); - c->estimated_weight = (now.tv_sec - c->start.tv_sec) * 1000 + (now.tv_usec - c->start.tv_usec) / 1000; - x = send_request(c, "%d %s %d %lx", ACK, myport, c->estimated_weight, c->options); - cp(); - return x; + /* ACK message contains rest of the information the other end needs + to create node_t and edge_t structures. */ + + int x; + struct timeval now; + + cp(); + + /* Estimate weight */ + + gettimeofday(&now, NULL); + c->estimated_weight = + (now.tv_sec - c->start.tv_sec) * 1000 + (now.tv_usec - + c->start.tv_usec) / 1000; + x = send_request(c, "%d %s %d %lx", ACK, myport, c->estimated_weight, + c->options); + + return x; } -void send_everything(connection_t *c) +void send_everything(connection_t * c) { - avl_node_t *node, *node2; - node_t *n; - subnet_t *s; - edge_t *e; - - /* Send all known subnets and edges */ - - for(node = node_tree->head; node; node = node->next) - { - n = (node_t *)node->data; - - for(node2 = n->subnet_tree->head; node2; node2 = node2->next) - { - s = (subnet_t *)node2->data; - send_add_subnet(c, s); - } - - for(node2 = n->edge_tree->head; node2; node2 = node2->next) - { - e = (edge_t *)node2->data; - send_add_edge(c, e); - } - } + avl_node_t *node, *node2; + node_t *n; + subnet_t *s; + edge_t *e; + + /* Send all known subnets and edges */ + + for(node = node_tree->head; node; node = node->next) { + n = (node_t *) node->data; + + for(node2 = n->subnet_tree->head; node2; node2 = node2->next) { + s = (subnet_t *) node2->data; + send_add_subnet(c, s); + } + + for(node2 = n->edge_tree->head; node2; node2 = node2->next) { + e = (edge_t *) node2->data; + send_add_edge(c, e); + } + } } -int ack_h(connection_t *c) +int ack_h(connection_t * c) { - char hisport[MAX_STRING_SIZE]; - char *hisaddress, *dummy; - int weight; - long int options; - node_t *n; - cp(); - if(sscanf(c->buffer, "%*d "MAX_STRING" %d %lx", hisport, &weight, &options) != 3) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ACK", c->name, c->hostname); - return -1; - } - - /* Check if we already have a node_t for him */ - - n = lookup_node(c->name); - - if(!n) - { - n = new_node(); - n->name = xstrdup(c->name); - node_add(n); - } - else - { - if(n->connection) - { - /* Oh dear, we already have a connection to this node. */ - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_DEBUG, _("Established a second connection with %s (%s), closing old connection"), n->name, n->hostname); - terminate_connection(n->connection, 0); - } - } - - n->connection = c; - c->node = n; - c->options |= options; - - /* Activate this connection */ - - c->allow_request = ALL; - c->status.active = 1; - - if(debug_lvl >= DEBUG_CONNECTIONS) - syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), c->name, c->hostname); - - /* Send him everything we know */ - - send_everything(c); - - /* 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); - c->edge->address = str2sockaddr(hisaddress, hisport); - free(hisaddress); - free(dummy); - c->edge->weight = (weight + c->estimated_weight) / 2; - c->edge->connection = c; - c->edge->options = c->options; - cp(); - edge_add(c->edge); - - cp(); - /* Notify everyone of the new edge */ - - send_add_edge(broadcast, c->edge); - - /* Run MST and SSSP algorithms */ - - graph(); - cp(); - return 0; + char hisport[MAX_STRING_SIZE]; + char *hisaddress, *dummy; + int weight; + long int options; + node_t *n; + + cp(); + + if(sscanf + (c->buffer, "%*d " MAX_STRING " %d %lx", hisport, &weight, &options) != 3) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ACK", c->name, + c->hostname); + return -1; + } + + /* Check if we already have a node_t for him */ + + n = lookup_node(c->name); + + if(!n) { + n = new_node(); + n->name = xstrdup(c->name); + node_add(n); + } else { + if(n->connection) { + /* Oh dear, we already have a connection to this node. */ + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_DEBUG, _("Established a second connection with %s (%s), closing old connection"), + n->name, n->hostname); + terminate_connection(n->connection, 0); + } + } + + n->connection = c; + c->node = n; + c->options |= options; + + /* Activate this connection */ + + c->allow_request = ALL; + c->status.active = 1; + + if(debug_lvl >= DEBUG_CONNECTIONS) + syslog(LOG_NOTICE, _("Connection with %s (%s) activated"), c->name, + c->hostname); + + /* Send him everything we know */ + + send_everything(c); + + /* 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); + c->edge->address = str2sockaddr(hisaddress, hisport); + free(hisaddress); + free(dummy); + c->edge->weight = (weight + c->estimated_weight) / 2; + c->edge->connection = c; + c->edge->options = c->options; + + edge_add(c->edge); + + /* Notify everyone of the new edge */ + + send_add_edge(broadcast, c->edge); + + /* Run MST and SSSP algorithms */ + + graph(); + + return 0; } diff --git a/src/protocol_edge.c b/src/protocol_edge.c index 7a04f08..bd473f1 100644 --- a/src/protocol_edge.c +++ b/src/protocol_edge.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: protocol_edge.c,v 1.1.4.11 2002/09/09 19:40:04 guus Exp $ + $Id: protocol_edge.c,v 1.1.4.12 2002/09/09 21:24:48 guus Exp $ */ #include "config.h" @@ -45,225 +45,231 @@ #include "system.h" -int send_add_edge(connection_t *c, edge_t *e) +int send_add_edge(connection_t * c, edge_t * e) { - int x; - char *address, *port; - cp(); - sockaddr2str(&e->address, &address, &port); - x = send_request(c, "%d %lx %s %s %s %s %lx %d", ADD_EDGE, random(), - e->from->name, e->to->name, address, port, - e->options, e->weight); - free(address); - free(port); - cp(); - return x; + int x; + char *address, *port; + + cp(); + + sockaddr2str(&e->address, &address, &port); + + x = send_request(c, "%d %lx %s %s %s %s %lx %d", ADD_EDGE, random(), + e->from->name, e->to->name, address, port, + e->options, e->weight); + free(address); + free(port); + + return x; } -int add_edge_h(connection_t *c) +int add_edge_h(connection_t * c) { - edge_t *e; - node_t *from, *to; - char from_name[MAX_STRING_SIZE]; - char to_name[MAX_STRING_SIZE]; - char to_address[MAX_STRING_SIZE]; - char to_port[MAX_STRING_SIZE]; - sockaddr_t address; - 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) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_EDGE", c->name, c->hostname); - return -1; - } - - /* Check if names are valid */ - - if(check_id(from_name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name, c->hostname, _("invalid name")); - return -1; - } - - if(check_id(to_name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name, c->hostname, _("invalid name")); - return -1; - } - - if(seen_request(c->buffer)) - return 0; - - /* Lookup nodes */ - - from = lookup_node(from_name); - - if(!from) - { - from = new_node(); - from->name = xstrdup(from_name); - node_add(from); - } - - to = lookup_node(to_name); - - if(!to) - { - to = new_node(); - to->name = xstrdup(to_name); - node_add(to); - } - - /* Convert addresses */ - - address = str2sockaddr(to_address, to_port); - - /* Check if edge already exists */ - - e = lookup_edge(from, to); - - if(e) - { - if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) - { - if(from == myself) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself which does not match existing entry"), "ADD_EDGE", c->name, c->hostname); - send_add_edge(c, e); - return 0; - } - else - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) which does not match existing entry"), "ADD_EDGE", c->name, c->hostname); - edge_del(e); - } - } - else - return 0; - } - else if(from == myself) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself which does not exist"), "ADD_EDGE", c->name, c->hostname); - e = new_edge(); - e->from = from; - e->to = to; - send_del_edge(c, e); - free_edge(e); - return 0; - } - - e = new_edge(); - e->from = from; - e->to = to; - e->address = address; - e->options = options; - e->weight = weight; - edge_add(e); - - /* Tell the rest about the new edge */ - - forward_request(c); - - /* Run MST before or after we tell the rest? */ - - graph(); - cp(); - return 0; + edge_t *e; + node_t *from, *to; + char from_name[MAX_STRING_SIZE]; + char to_name[MAX_STRING_SIZE]; + char to_address[MAX_STRING_SIZE]; + char to_port[MAX_STRING_SIZE]; + sockaddr_t address; + 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) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_EDGE", c->name, + c->hostname); + return -1; + } + + /* Check if names are valid */ + + if(check_id(from_name)) { + syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name, + c->hostname, _("invalid name")); + return -1; + } + + if(check_id(to_name)) { + syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_EDGE", c->name, + c->hostname, _("invalid name")); + return -1; + } + + if(seen_request(c->buffer)) + return 0; + + /* Lookup nodes */ + + from = lookup_node(from_name); + + if(!from) { + from = new_node(); + from->name = xstrdup(from_name); + node_add(from); + } + + to = lookup_node(to_name); + + if(!to) { + to = new_node(); + to->name = xstrdup(to_name); + node_add(to); + } + + /* Convert addresses */ + + address = str2sockaddr(to_address, to_port); + + /* Check if edge already exists */ + + e = lookup_edge(from, to); + + if(e) { + if(e->weight != weight || e->options != options || sockaddrcmp(&e->address, &address)) { + if(from == myself) { + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself which does not match existing entry"), + "ADD_EDGE", c->name, c->hostname); + send_add_edge(c, e); + return 0; + } else { + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_WARNING, _("Got %s from %s (%s) which does not match existing entry"), + "ADD_EDGE", c->name, c->hostname); + edge_del(e); + } + } else + return 0; + } else if(from == myself) { + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself which does not exist"), + "ADD_EDGE", c->name, c->hostname); + e = new_edge(); + e->from = from; + e->to = to; + send_del_edge(c, e); + free_edge(e); + return 0; + } + + e = new_edge(); + e->from = from; + e->to = to; + e->address = address; + e->options = options; + e->weight = weight; + edge_add(e); + + /* Tell the rest about the new edge */ + + forward_request(c); + + /* Run MST before or after we tell the rest? */ + + graph(); + + return 0; } -int send_del_edge(connection_t *c, edge_t *e) +int send_del_edge(connection_t * c, edge_t * e) { - cp(); - return send_request(c, "%d %lx %s %s", DEL_EDGE, random(), - e->from->name, e->to->name); + cp(); + + return send_request(c, "%d %lx %s %s", DEL_EDGE, random(), + e->from->name, e->to->name); } -int del_edge_h(connection_t *c) +int del_edge_h(connection_t * c) { - edge_t *e; - char from_name[MAX_STRING_SIZE]; - 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) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_EDGE", - c->name, c->hostname); - return -1; - } - - /* Check if names are valid */ - - if(check_id(from_name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name, c->hostname, _("invalid name")); - return -1; - } - - if(check_id(to_name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name, c->hostname, _("invalid name")); - return -1; - } - - if(seen_request(c->buffer)) - return 0; - - /* Lookup nodes */ - - from = lookup_node(from_name); - - if(!from) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_ERR, _("Got %s from %s (%s) which does not appear in the edge tree"), "DEL_EDGE", c->name, c->hostname); - return 0; - } - - to = lookup_node(to_name); - - if(!to) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_ERR, _("Got %s from %s (%s) which does not appear in the edge tree"), "DEL_EDGE", c->name, c->hostname); - return 0; - } - - /* Check if edge exists */ - - e = lookup_edge(from, to); - - if(!e) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) which does not appear in the edge tree"), "DEL_EDGE", c->name, c->hostname); - return 0; - } - - if(e->from == myself) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), "DEL_EDGE", c->name, c->hostname); - send_add_edge(c, e); /* Send back a correction */ - return 0; - } - - /* Tell the rest about the deleted edge */ - - forward_request(c); - - /* Delete the edge */ - - edge_del(e); - - /* Run MST before or after we tell the rest? */ - - graph(); - cp(); - return 0; + edge_t *e; + char from_name[MAX_STRING_SIZE]; + 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) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_EDGE", c->name, + c->hostname); + return -1; + } + + /* Check if names are valid */ + + if(check_id(from_name)) { + syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name, + c->hostname, _("invalid name")); + return -1; + } + + if(check_id(to_name)) { + syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_EDGE", c->name, + c->hostname, _("invalid name")); + return -1; + } + + if(seen_request(c->buffer)) + return 0; + + /* Lookup nodes */ + + from = lookup_node(from_name); + + if(!from) { + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_ERR, + _ + ("Got %s from %s (%s) which does not appear in the edge tree"), + "DEL_EDGE", c->name, c->hostname); + return 0; + } + + to = lookup_node(to_name); + + if(!to) { + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_ERR, + _ + ("Got %s from %s (%s) which does not appear in the edge tree"), + "DEL_EDGE", c->name, c->hostname); + return 0; + } + + /* Check if edge exists */ + + e = lookup_edge(from, to); + + if(!e) { + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_WARNING, + _ + ("Got %s from %s (%s) which does not appear in the edge tree"), + "DEL_EDGE", c->name, c->hostname); + return 0; + } + + if(e->from == myself) { + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), + "DEL_EDGE", c->name, c->hostname); + send_add_edge(c, e); /* Send back a correction */ + return 0; + } + + /* Tell the rest about the deleted edge */ + + forward_request(c); + + /* Delete the edge */ + + edge_del(e); + + /* Run MST before or after we tell the rest? */ + + graph(); + + return 0; } diff --git a/src/protocol_key.c b/src/protocol_key.c index 03131eb..66c9a90 100644 --- a/src/protocol_key.c +++ b/src/protocol_key.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: protocol_key.c,v 1.1.4.12 2002/09/09 19:40:05 guus Exp $ + $Id: protocol_key.c,v 1.1.4.13 2002/09/09 21:24:56 guus Exp $ */ #include "config.h" @@ -45,225 +45,217 @@ int mykeyused = 0; -int send_key_changed(connection_t *c, node_t *n) +int send_key_changed(connection_t * c, node_t * n) { - cp(); - /* Only send this message if some other daemon requested our key previously. - This reduces unnecessary key_changed broadcasts. - */ - - if(n == myself && !mykeyused) - return 0; - cp(); - return send_request(c, "%d %lx %s", KEY_CHANGED, random(), n->name); + cp(); + + /* Only send this message if some other daemon requested our key previously. + This reduces unnecessary key_changed broadcasts. + */ + + if(n == myself && !mykeyused) + return 0; + + return send_request(c, "%d %lx %s", KEY_CHANGED, random(), n->name); } -int key_changed_h(connection_t *c) +int key_changed_h(connection_t * c) { - char name[MAX_STRING_SIZE]; - node_t *n; - cp(); - if(sscanf(c->buffer, "%*d %*x "MAX_STRING, name) != 1) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "KEY_CHANGED", - c->name, c->hostname); - return -1; - } - - if(seen_request(c->buffer)) - return 0; - - n = lookup_node(name); - - if(!n) - { - syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist"), "KEY_CHANGED", - c->name, c->hostname, name); - return -1; - } - - n->status.validkey = 0; - n->status.waitingforkey = 0; - - /* Tell the others */ - - forward_request(c); - cp(); - return 0; + char name[MAX_STRING_SIZE]; + node_t *n; + + cp(); + + if(sscanf(c->buffer, "%*d %*x " MAX_STRING, name) != 1) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "KEY_CHANGED", + c->name, c->hostname); + return -1; + } + + if(seen_request(c->buffer)) + return 0; + + n = lookup_node(name); + + if(!n) { + syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist"), + "KEY_CHANGED", c->name, c->hostname, name); + return -1; + } + + n->status.validkey = 0; + n->status.waitingforkey = 0; + + /* Tell the others */ + + forward_request(c); + + return 0; } -int send_req_key(connection_t *c, node_t *from, node_t *to) +int send_req_key(connection_t * c, node_t * from, node_t * to) { - cp(); - return send_request(c, "%d %s %s", REQ_KEY, - from->name, to->name); + cp(); + + return send_request(c, "%d %s %s", REQ_KEY, from->name, to->name); } -int req_key_h(connection_t *c) +int req_key_h(connection_t * c) { - char from_name[MAX_STRING_SIZE]; - 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) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "REQ_KEY", - c->name, c->hostname); - return -1; - } - - from = lookup_node(from_name); - - if(!from) - { - syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist in our connection list"), "REQ_KEY", - c->name, c->hostname, from_name); - return -1; - } - - to = lookup_node(to_name); - - if(!to) - { - syslog(LOG_ERR, _("Got %s from %s (%s) destination %s which does not exist in our connection list"), "REQ_KEY", - c->name, c->hostname, to_name); - return -1; - } - - /* Check if this key request is for us */ - - if(to == myself) /* Yes, send our own key back */ - { - mykeyused = 1; - from->received_seqno = 0; - send_ans_key(c, myself, from); - } - else - { -/* Proxy keys - if(to->status.validkey) - { - send_ans_key(c, to, from); - } - else -*/ - send_req_key(to->nexthop->connection, from, to); - } + char from_name[MAX_STRING_SIZE]; + 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) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "REQ_KEY", c->name, + c->hostname); + return -1; + } + + from = lookup_node(from_name); + + if(!from) { + syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist in our connection list"), + "REQ_KEY", c->name, c->hostname, from_name); + return -1; + } + + to = lookup_node(to_name); + + if(!to) { + syslog(LOG_ERR, _("Got %s from %s (%s) destination %s which does not exist in our connection list"), + "REQ_KEY", c->name, c->hostname, to_name); + return -1; + } + + /* Check if this key request is for us */ + + if(to == myself) { /* Yes, send our own key back */ + mykeyused = 1; + from->received_seqno = 0; + send_ans_key(c, myself, from); + } else { + send_req_key(to->nexthop->connection, from, to); + } - cp(); - return 0; + return 0; } -int send_ans_key(connection_t *c, node_t *from, node_t *to) +int send_ans_key(connection_t * c, node_t * from, node_t * to) { - char key[MAX_STRING_SIZE]; - cp(); - bin2hex(from->key, key, from->keylength); - key[from->keylength * 2] = '\0'; - cp(); - return send_request(c, "%d %s %s %s %d %d %d %d", ANS_KEY, - from->name, to->name, key, from->cipher?from->cipher->nid:0, from->digest?from->digest->type:0, from->maclength, from->compression); + char key[MAX_STRING_SIZE]; + + cp(); + + bin2hex(from->key, key, from->keylength); + key[from->keylength * 2] = '\0'; + + return send_request(c, "%d %s %s %s %d %d %d %d", ANS_KEY, + from->name, to->name, key, + from->cipher ? from->cipher->nid : 0, + from->digest ? from->digest->type : 0, from->maclength, + from->compression); } -int ans_key_h(connection_t *c) +int ans_key_h(connection_t * c) { - char from_name[MAX_STRING_SIZE]; - char to_name[MAX_STRING_SIZE]; - char key[MAX_STRING_SIZE]; - 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) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ANS_KEY", - c->name, c->hostname); - return -1; - } - - from = lookup_node(from_name); - - if(!from) - { - syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist in our connection list"), "ANS_KEY", - c->name, c->hostname, from_name); - return -1; - } - - to = lookup_node(to_name); - - if(!to) - { - syslog(LOG_ERR, _("Got %s from %s (%s) destination %s which does not exist in our connection list"), "ANS_KEY", - c->name, c->hostname, to_name); - return -1; - } - - /* Forward it if necessary */ - - if(to != myself) - { - return send_request(to->nexthop->connection, "%s", c->buffer); - } - - /* Update our copy of the origin's packet key */ - - if(from->key) - free(from->key); - - from->key = xstrdup(key); - from->keylength = strlen(key) / 2; - hex2bin(from->key, from->key, from->keylength); - from->key[from->keylength] = '\0'; - - from->status.validkey = 1; - from->status.waitingforkey = 0; - from->sent_seqno = 0; - - /* Check and lookup cipher and digest algorithms */ - - if(cipher) - { - from->cipher = EVP_get_cipherbynid(cipher); - if(!from->cipher) - { - syslog(LOG_ERR, _("Node %s (%s) uses unknown cipher!"), from->name, from->hostname); - return -1; + char from_name[MAX_STRING_SIZE]; + char to_name[MAX_STRING_SIZE]; + char key[MAX_STRING_SIZE]; + 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) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ANS_KEY", c->name, + c->hostname); + return -1; } - if(from->keylength != from->cipher->key_len + from->cipher->iv_len) - { - syslog(LOG_ERR, _("Node %s (%s) uses wrong keylength!"), from->name, from->hostname); - return -1; - } - } - else - { - from->cipher = NULL; - } - - from->maclength = maclength; - - if(digest) - { - from->digest = EVP_get_digestbynid(digest); - if(!from->digest) - { - syslog(LOG_ERR, _("Node %s (%s) uses unknown digest!"), from->name, from->hostname); - return -1; + + from = lookup_node(from_name); + + if(!from) { + syslog(LOG_ERR, _("Got %s from %s (%s) origin %s which does not exist in our connection list"), + "ANS_KEY", c->name, c->hostname, from_name); + return -1; + } + + to = lookup_node(to_name); + + if(!to) { + syslog(LOG_ERR, _("Got %s from %s (%s) destination %s which does not exist in our connection list"), + "ANS_KEY", c->name, c->hostname, to_name); + return -1; } - if(from->maclength > from->digest->md_size || from->maclength < 0) - { - syslog(LOG_ERR, _("Node %s (%s) uses bogus MAC length!"), from->name, from->hostname); - return -1; + + /* Forward it if necessary */ + + if(to != myself) { + return send_request(to->nexthop->connection, "%s", c->buffer); } - } - else - { - from->digest = NULL; - } - - from->compression = compression; - - flush_queue(from); - cp(); - return 0; + + /* Update our copy of the origin's packet key */ + + if(from->key) + free(from->key); + + from->key = xstrdup(key); + from->keylength = strlen(key) / 2; + hex2bin(from->key, from->key, from->keylength); + from->key[from->keylength] = '\0'; + + from->status.validkey = 1; + from->status.waitingforkey = 0; + from->sent_seqno = 0; + + /* Check and lookup cipher and digest algorithms */ + + if(cipher) { + from->cipher = EVP_get_cipherbynid(cipher); + + if(!from->cipher) { + syslog(LOG_ERR, _("Node %s (%s) uses unknown cipher!"), from->name, + from->hostname); + return -1; + } + + if(from->keylength != from->cipher->key_len + from->cipher->iv_len) { + syslog(LOG_ERR, _("Node %s (%s) uses wrong keylength!"), from->name, + from->hostname); + return -1; + } + } else { + from->cipher = NULL; + } + + from->maclength = maclength; + + if(digest) { + from->digest = EVP_get_digestbynid(digest); + + if(!from->digest) { + syslog(LOG_ERR, _("Node %s (%s) uses unknown digest!"), from->name, + from->hostname); + return -1; + } + + if(from->maclength > from->digest->md_size || from->maclength < 0) { + syslog(LOG_ERR, _("Node %s (%s) uses bogus MAC length!"), + from->name, from->hostname); + return -1; + } + } else { + from->digest = NULL; + } + + from->compression = compression; + + flush_queue(from); + + return 0; } diff --git a/src/protocol_misc.c b/src/protocol_misc.c index 3e48970..4dcdd92 100644 --- a/src/protocol_misc.c +++ b/src/protocol_misc.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: protocol_misc.c,v 1.1.4.5 2002/09/09 19:40:08 guus Exp $ + $Id: protocol_misc.c,v 1.1.4.6 2002/09/09 21:25:02 guus Exp $ */ #include "config.h" @@ -42,157 +42,169 @@ /* Status and error notification routines */ -int send_status(connection_t *c, int statusno, char *statusstring) +int send_status(connection_t * c, int statusno, char *statusstring) { - cp(); - if(!statusstring) - statusstring = status_text[statusno]; - cp(); - return send_request(c, "%d %d %s", STATUS, statusno, statusstring); + cp(); + + if(!statusstring) + statusstring = status_text[statusno]; + + return send_request(c, "%d %d %s", STATUS, statusno, statusstring); } -int status_h(connection_t *c) +int status_h(connection_t * c) { - int statusno; - char statusstring[MAX_STRING_SIZE]; - cp(); - if(sscanf(c->buffer, "%*d %d "MAX_STRING, &statusno, statusstring) != 2) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "STATUS", - c->name, c->hostname); - return -1; - } - - if(debug_lvl >= DEBUG_STATUS) - { - syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"), - c->name, c->hostname, status_text[statusno], statusstring); - } - - cp(); - return 0; + int statusno; + char statusstring[MAX_STRING_SIZE]; + + cp(); + + if(sscanf(c->buffer, "%*d %d " MAX_STRING, &statusno, statusstring) != 2) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "STATUS", + c->name, c->hostname); + return -1; + } + + if(debug_lvl >= DEBUG_STATUS) { + syslog(LOG_NOTICE, _("Status message from %s (%s): %s: %s"), + c->name, c->hostname, status_text[statusno], statusstring); + } + + return 0; } -int send_error(connection_t *c, int err, char *errstring) +int send_error(connection_t * c, int err, char *errstring) { - cp(); - if(!errstring) - errstring = strerror(err); - return send_request(c, "%d %d %s", ERROR, err, errstring); + cp(); + + if(!errstring) + errstring = strerror(err); + + return send_request(c, "%d %d %s", ERROR, err, errstring); } -int error_h(connection_t *c) +int error_h(connection_t * c) { - int err; - char errorstring[MAX_STRING_SIZE]; - cp(); - if(sscanf(c->buffer, "%*d %d "MAX_STRING, &err, errorstring) != 2) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ERROR", - c->name, c->hostname); - return -1; - } - - if(debug_lvl >= DEBUG_ERROR) - { - syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"), - c->name, c->hostname, strerror(err), errorstring); - } - - terminate_connection(c, c->status.active); - cp(); - return 0; + int err; + char errorstring[MAX_STRING_SIZE]; + + cp(); + + if(sscanf(c->buffer, "%*d %d " MAX_STRING, &err, errorstring) != 2) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ERROR", + c->name, c->hostname); + return -1; + } + + if(debug_lvl >= DEBUG_ERROR) { + syslog(LOG_NOTICE, _("Error message from %s (%s): %s: %s"), + c->name, c->hostname, strerror(err), errorstring); + } + + terminate_connection(c, c->status.active); + + return 0; } -int send_termreq(connection_t *c) +int send_termreq(connection_t * c) { - cp(); - return send_request(c, "%d", TERMREQ); + cp(); + + return send_request(c, "%d", TERMREQ); } -int termreq_h(connection_t *c) +int termreq_h(connection_t * c) { - cp(); - terminate_connection(c, c->status.active); - cp(); - return 0; + cp(); + + terminate_connection(c, c->status.active); + + return 0; } -int send_ping(connection_t *c) +int send_ping(connection_t * c) { - cp(); - c->status.pinged = 1; - c->last_ping_time = now; - cp(); - return send_request(c, "%d", PING); + cp(); + + c->status.pinged = 1; + c->last_ping_time = now; + + return send_request(c, "%d", PING); } -int ping_h(connection_t *c) +int ping_h(connection_t * c) { - cp(); - return send_pong(c); + cp(); + + return send_pong(c); } -int send_pong(connection_t *c) +int send_pong(connection_t * c) { - cp(); - return send_request(c, "%d", PONG); + cp(); + + return send_request(c, "%d", PONG); } -int pong_h(connection_t *c) +int pong_h(connection_t * c) { - cp(); - c->status.pinged = 0; - - /* Succesful connection, reset timeout if this is an outgoing connection. */ - - if(c->outgoing) - c->outgoing->timeout = 0; - cp(); - return 0; + cp(); + + c->status.pinged = 0; + + /* Succesful connection, reset timeout if this is an outgoing connection. */ + + if(c->outgoing) + c->outgoing->timeout = 0; + + return 0; } /* Sending and receiving packets via TCP */ -int send_tcppacket(connection_t *c, vpn_packet_t *packet) +int send_tcppacket(connection_t * c, vpn_packet_t * packet) { - int x; - cp(); - /* Evil hack. */ + int x; - x = send_request(c, "%d %hd", PACKET, packet->len); + cp(); - if(x) - return x; - cp(); - return send_meta(c, packet->data, packet->len); + /* Evil hack. */ + + x = send_request(c, "%d %hd", PACKET, packet->len); + + if(x) + return x; + + return send_meta(c, packet->data, packet->len); } -int tcppacket_h(connection_t *c) +int tcppacket_h(connection_t * c) { - short int len; - cp(); - if(sscanf(c->buffer, "%*d %hd", &len) != 1) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "PACKET", c->name, c->hostname); - return -1; - } - - /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */ - - c->tcplen = len; - cp(); - return 0; + short int len; + + cp(); + + if(sscanf(c->buffer, "%*d %hd", &len) != 1) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "PACKET", c->name, + c->hostname); + return -1; + } + + /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */ + + c->tcplen = len; + + return 0; } /* Status strings */ char (*status_text[]) = { - "Warning", + "Warning", }; /* Error strings */ char (*error_text[]) = { - "Error", + "Error", }; diff --git a/src/protocol_node.c b/src/protocol_node.c index f95dec8..f6be38f 100644 --- a/src/protocol_node.c +++ b/src/protocol_node.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: protocol_node.c,v 1.1.4.7 2002/09/09 19:40:08 guus Exp $ + $Id: protocol_node.c,v 1.1.4.8 2002/09/09 21:25:02 guus Exp $ */ #include "config.h" @@ -43,204 +43,202 @@ #include "system.h" -int send_add_node(connection_t *c, node_t *n) +int send_add_node(connection_t * c, node_t * n) { - int x; - char *address, *port; - cp(); - if(!n->status.reachable) - return 0; - - sockaddr2str(&n->address, &address, &port); - x = send_request(c, "%d %s %s %s %lx %d %s %s", ADD_NODE, - n->name, address, port, - n->options, n->distance + 1, // Alternatively, use n->distance + c->estimated_weight - n->prevhop->name, n->via->name); - free(address); - free(port); - cp(); - return x; + int x; + char *address, *port; + cp(); + if(!n->status.reachable) + return 0; + + sockaddr2str(&n->address, &address, &port); + x = send_request(c, "%d %s %s %s %lx %d %s %s", ADD_NODE, n->name, address, port, n->options, n->distance + 1, // Alternatively, use n->distance + c->estimated_weight + n->prevhop->name, n->via->name); + free(address); + free(port); + cp(); + return x; } -int add_node_h(connection_t *c) +int add_node_h(connection_t * c) { - connection_t *other; - node_t *n, *prevhop, *via; - char name[MAX_STRING_SIZE]; - char address[MAX_STRING_SIZE]; - char port[MAX_STRING_SIZE]; - char prevhopname[MAX_STRING_SIZE]; - char vianame[MAX_STRING_SIZE]; - long int options; - int distance; - avl_node_t *node; - cp(); - if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d "MAX_STRING" "MAX_STRING, - name, address, port, &options, &distance, prevhopname, vianame) != 7) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_NODE", c->name, c->hostname); - return -1; - } - - /* Check if names are valid */ - - if(check_id(name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_NODE", c->name, c->hostname, _("invalid name")); - return -1; - } - - /* This node is indirect if it's nexthop is as well */ - - if(c->node->options & OPTION_INDIRECT) - options |= OPTION_INDIRECT; - - /* Lookup nodes */ - - prevhop = lookup_node(prevhopname); - - if(!prevhop) - { - prevhop = new_node(); - prevhop->name = xstrdup(prevhopname); - node_add(prevhop); - } - - via = lookup_node(vianame); - - if(!via) - { - via = new_node(); - via->name = xstrdup(vianame); - node_add(via); - } - - n = lookup_node(name); - - if(!n) - { - // It's a new node. Add it and tell the others. - n = new_node(); - n->name = xstrdup(name); - n->address = str2sockaddr(address, port); - n->hostname = sockaddr2hostname(&n->address); - n->options = options; - n->distance = distance; - n->nexthop = c->node; - n->prevhop = prevhop; - n->via = via; - node_add(n); - if(prevhop == myself) - { - syslog(LOG_WARNING, _("Got ADD_NODE %s prevhop %s via %s from %s, sending back a DEL_NODE!"), name, prevhopname, vianame, c->name); - // send_del_node(c, n); - return 0; - } - n->status.reachable = 1; - } - else - { - // If this ADD_NODE is closer or more direct, use it instead of the old one. - if(!n->status.reachable || ((n->options & OPTION_INDIRECT) && !(options & OPTION_INDIRECT)) || n->distance > distance) - { - if(prevhop == myself) - { - syslog(LOG_WARNING, _("Got ADD_NODE %s prevhop %s via %s from %s!"), name, prevhopname, vianame, c->name); - // send_del_node(c, n); - return 0; - } - node = avl_unlink(node_udp_tree, n); - n->address = str2sockaddr(address, port); - avl_insert_node(node_udp_tree, node); - if(n->hostname) - free(n->hostname); - n->hostname = sockaddr2hostname(&n->address); - n->options = options; - n->distance = distance; - n->via = n->nexthop = c->node; - n->status.reachable = 1; - n->status.validkey = 0; - n->status.waitingforkey = 0; - } - else - // Otherwise, just ignore it. - return 0; - } - - /* Tell the rest about the new node */ - - for(node = connection_tree->head; node; node = node->next) - { - other = (connection_t *)node->data; - if(other->status.active && other != c) - send_add_node(other, n); - } - - cp(); - return 0; + connection_t *other; + node_t *n, *prevhop, *via; + char name[MAX_STRING_SIZE]; + char address[MAX_STRING_SIZE]; + char port[MAX_STRING_SIZE]; + char prevhopname[MAX_STRING_SIZE]; + char vianame[MAX_STRING_SIZE]; + long int options; + int distance; + avl_node_t *node; + cp(); + if(sscanf + (c->buffer, + "%*d " MAX_STRING " " MAX_STRING " " MAX_STRING " %lx %d " MAX_STRING + " " MAX_STRING, name, address, port, &options, &distance, prevhopname, + vianame) != 7) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_NODE", c->name, + c->hostname); + return -1; + } + + /* Check if names are valid */ + + if(check_id(name)) { + syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_NODE", c->name, + c->hostname, _("invalid name")); + return -1; + } + + /* This node is indirect if it's nexthop is as well */ + + if(c->node->options & OPTION_INDIRECT) + options |= OPTION_INDIRECT; + + /* Lookup nodes */ + + prevhop = lookup_node(prevhopname); + + if(!prevhop) { + prevhop = new_node(); + prevhop->name = xstrdup(prevhopname); + node_add(prevhop); + } + + via = lookup_node(vianame); + + if(!via) { + via = new_node(); + via->name = xstrdup(vianame); + node_add(via); + } + + n = lookup_node(name); + + if(!n) { + // It's a new node. Add it and tell the others. + n = new_node(); + n->name = xstrdup(name); + n->address = str2sockaddr(address, port); + n->hostname = sockaddr2hostname(&n->address); + n->options = options; + n->distance = distance; + n->nexthop = c->node; + n->prevhop = prevhop; + n->via = via; + node_add(n); + if(prevhop == myself) { + syslog(LOG_WARNING, + _ + ("Got ADD_NODE %s prevhop %s via %s from %s, sending back a DEL_NODE!"), + name, prevhopname, vianame, c->name); + // send_del_node(c, n); + return 0; + } + n->status.reachable = 1; + } else { + // If this ADD_NODE is closer or more direct, use it instead of the old one. + if(!n->status.reachable + || ((n->options & OPTION_INDIRECT) && !(options & OPTION_INDIRECT)) + || n->distance > distance) { + if(prevhop == myself) { + syslog(LOG_WARNING, + _("Got ADD_NODE %s prevhop %s via %s from %s!"), name, + prevhopname, vianame, c->name); + // send_del_node(c, n); + return 0; + } + node = avl_unlink(node_udp_tree, n); + n->address = str2sockaddr(address, port); + avl_insert_node(node_udp_tree, node); + if(n->hostname) + free(n->hostname); + n->hostname = sockaddr2hostname(&n->address); + n->options = options; + n->distance = distance; + n->via = n->nexthop = c->node; + n->status.reachable = 1; + n->status.validkey = 0; + n->status.waitingforkey = 0; + } else + // Otherwise, just ignore it. + return 0; + } + + /* Tell the rest about the new node */ + + for(node = connection_tree->head; node; node = node->next) { + other = (connection_t *) node->data; + if(other->status.active && other != c) + send_add_node(other, n); + } + + cp(); + return 0; } -int send_del_node(connection_t *c, node_t *n) +int send_del_node(connection_t * c, node_t * n) { - cp(); - return send_request(c, "%d %s %s", DEL_NODE, n->name, n->prevhop->name); + cp(); + return send_request(c, "%d %s %s", DEL_NODE, n->name, n->prevhop->name); } -int del_node_h(connection_t *c) +int del_node_h(connection_t * c) { - char name[MAX_STRING_SIZE]; - char prevhopname[MAX_STRING_SIZE]; - node_t *n, *prevhop; - connection_t *other; - avl_node_t *node; - cp(); - if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING, name, prevhopname) != 2) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_NODE", - c->name, c->hostname); - return -1; - } - - /* Check if names are valid */ - - if(check_id(name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_NODE", c->name, c->hostname, _("invalid name")); - return -1; - } - - /* Lookup nodes */ - - n = lookup_node(name); - prevhop = lookup_node(prevhopname); - - if(!n || !prevhop) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) which does not appear in the node tree"), "DEL_NODE", c->name, c->hostname); - return 0; - } - - /* If we got a DEL_NODE but we know of a different route to it, tell the one who send the DEL_NODE */ - - if(n->nexthop != c->node) - { - return send_add_node(c, n); - } - - /* Otherwise, tell the rest about the deleted node */ - - for(node = connection_tree->head; node; node = node->next) - { - other = (connection_t *)node->data; - if(other->status.active && other != c) - send_del_node(other, n); - } - - /* "Delete" the node */ - - n->status.reachable = 0; - n->status.validkey = 0; - cp(); - return 0; + char name[MAX_STRING_SIZE]; + char prevhopname[MAX_STRING_SIZE]; + node_t *n, *prevhop; + connection_t *other; + avl_node_t *node; + cp(); + if(sscanf(c->buffer, "%*d " MAX_STRING " " MAX_STRING, name, prevhopname) != + 2) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_NODE", c->name, + c->hostname); + return -1; + } + + /* Check if names are valid */ + + if(check_id(name)) { + syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_NODE", c->name, + c->hostname, _("invalid name")); + return -1; + } + + /* Lookup nodes */ + + n = lookup_node(name); + prevhop = lookup_node(prevhopname); + + if(!n || !prevhop) { + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_WARNING, + _ + ("Got %s from %s (%s) which does not appear in the node tree"), + "DEL_NODE", c->name, c->hostname); + return 0; + } + + /* If we got a DEL_NODE but we know of a different route to it, tell the one who send the DEL_NODE */ + + if(n->nexthop != c->node) { + return send_add_node(c, n); + } + + /* Otherwise, tell the rest about the deleted node */ + + for(node = connection_tree->head; node; node = node->next) { + other = (connection_t *) node->data; + if(other->status.active && other != c) + send_del_node(other, n); + } + + /* "Delete" the node */ + + n->status.reachable = 0; + n->status.validkey = 0; + cp(); + return 0; } diff --git a/src/protocol_subnet.c b/src/protocol_subnet.c index ba617e5..81cd52c 100644 --- a/src/protocol_subnet.c +++ b/src/protocol_subnet.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: protocol_subnet.c,v 1.1.4.7 2002/09/09 19:40:09 guus Exp $ + $Id: protocol_subnet.c,v 1.1.4.8 2002/09/09 21:25:02 guus Exp $ */ #include "config.h" @@ -43,185 +43,191 @@ #include "system.h" -int send_add_subnet(connection_t *c, subnet_t *subnet) +int send_add_subnet(connection_t * c, subnet_t * subnet) { - int x; - char *netstr; - cp(); - x = send_request(c, "%d %lx %s %s", ADD_SUBNET, random(), - subnet->owner->name, netstr = net2str(subnet)); - free(netstr); - cp(); - return x; + int x; + char *netstr; + + cp(); + + x = send_request(c, "%d %lx %s %s", ADD_SUBNET, random(), + subnet->owner->name, netstr = net2str(subnet)); + + free(netstr); + + return x; } -int add_subnet_h(connection_t *c) +int add_subnet_h(connection_t * c) { - char subnetstr[MAX_STRING_SIZE]; - char name[MAX_STRING_SIZE]; - node_t *owner; - subnet_t *s; - cp(); - if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, name, subnetstr) != 2) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_SUBNET", c->name, c->hostname); - return -1; - } - - /* Check if owner name is a valid */ - - if(check_id(name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name, c->hostname, _("invalid name")); - return -1; - } - - /* Check if subnet string is valid */ - - s = str2net(subnetstr); - - if(!s) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name, c->hostname, _("invalid subnet string")); - return -1; - } - - if(seen_request(c->buffer)) - return 0; - - /* Check if the owner of the new subnet is in the connection list */ - - owner = lookup_node(name); - - if(!owner) - { - owner = new_node(); - owner->name = xstrdup(name); - node_add(owner); - } - - /* Check if we already know this subnet */ - - if(lookup_subnet(owner, s)) - { - free_subnet(s); - return 0; - } - - /* If we don't know this subnet, but we are the owner, retaliate with a DEL_SUBNET */ - - if(owner == myself) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), "ADD_SUBNET", c->name, c->hostname); - s->owner = myself; - send_del_subnet(c, s); - return 0; - } - - /* If everything is correct, add the subnet to the list of the owner */ - - subnet_add(owner, s); - - /* Tell the rest */ - - forward_request(c); - cp(); - return 0; + char subnetstr[MAX_STRING_SIZE]; + char name[MAX_STRING_SIZE]; + node_t *owner; + subnet_t *s; + + cp(); + + if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "ADD_SUBNET", c->name, + c->hostname); + return -1; + } + + /* Check if owner name is a valid */ + + if(check_id(name)) { + syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name, + c->hostname, _("invalid name")); + return -1; + } + + /* Check if subnet string is valid */ + + s = str2net(subnetstr); + + if(!s) { + syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "ADD_SUBNET", c->name, + c->hostname, _("invalid subnet string")); + return -1; + } + + if(seen_request(c->buffer)) + return 0; + + /* Check if the owner of the new subnet is in the connection list */ + + owner = lookup_node(name); + + if(!owner) { + owner = new_node(); + owner->name = xstrdup(name); + node_add(owner); + } + + /* Check if we already know this subnet */ + + if(lookup_subnet(owner, s)) { + free_subnet(s); + return 0; + } + + /* If we don't know this subnet, but we are the owner, retaliate with a DEL_SUBNET */ + + if(owner == myself) { + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), + "ADD_SUBNET", c->name, c->hostname); + s->owner = myself; + send_del_subnet(c, s); + return 0; + } + + /* If everything is correct, add the subnet to the list of the owner */ + + subnet_add(owner, s); + + /* Tell the rest */ + + forward_request(c); + + return 0; } -int send_del_subnet(connection_t *c, subnet_t *s) +int send_del_subnet(connection_t * c, subnet_t * s) { - int x; - char *netstr; - cp(); - netstr = net2str(s); - x = send_request(c, "%d %lx %s %s", DEL_SUBNET, random(), s->owner->name, netstr); - free(netstr); - cp(); - return x; + int x; + char *netstr; + + cp(); + + netstr = net2str(s); + + x = send_request(c, "%d %lx %s %s", DEL_SUBNET, random(), s->owner->name, netstr); + + free(netstr); + + return x; } -int del_subnet_h(connection_t *c) +int del_subnet_h(connection_t * c) { - char subnetstr[MAX_STRING_SIZE]; - char name[MAX_STRING_SIZE]; - node_t *owner; - subnet_t *s, *find; - cp(); - if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING, name, subnetstr) != 2) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_SUBNET", c->name, c->hostname); - return -1; - } - - /* Check if owner name is a valid */ - - if(check_id(name)) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name, c->hostname, _("invalid name")); - return -1; - } - - /* Check if the owner of the new subnet is in the connection list */ - - owner = lookup_node(name); - - if(!owner) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which is not in our node tree"), - "DEL_SUBNET", c->name, c->hostname, name); - return 0; - } - - /* Check if subnet string is valid */ - - s = str2net(subnetstr); - - if(!s) - { - syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name, c->hostname, _("invalid subnet string")); - return -1; - } - - if(seen_request(c->buffer)) - return 0; - - /* If everything is correct, delete the subnet from the list of the owner */ - - s->owner = owner; - - find = lookup_subnet(owner, s); - - free_subnet(s); - - if(!find) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which does not appear in his subnet tree"), - "DEL_SUBNET", c->name, c->hostname, name); - return 0; - } - - /* If we are the owner of this subnet, retaliate with an ADD_SUBNET */ - - if(owner == myself) - { - if(debug_lvl >= DEBUG_PROTOCOL) - syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), "DEL_SUBNET", c->name, c->hostname); - send_add_subnet(c, find); - return 0; - } - - /* Tell the rest */ - - forward_request(c); - - /* Finally, delete it. */ - - subnet_del(owner, find); - - cp(); - return 0; + char subnetstr[MAX_STRING_SIZE]; + char name[MAX_STRING_SIZE]; + node_t *owner; + subnet_t *s, *find; + + cp(); + + if(sscanf(c->buffer, "%*d %*x " MAX_STRING " " MAX_STRING, name, subnetstr) != 2) { + syslog(LOG_ERR, _("Got bad %s from %s (%s)"), "DEL_SUBNET", c->name, + c->hostname); + return -1; + } + + /* Check if owner name is a valid */ + + if(check_id(name)) { + syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name, + c->hostname, _("invalid name")); + return -1; + } + + /* Check if the owner of the new subnet is in the connection list */ + + owner = lookup_node(name); + + if(!owner) { + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which is not in our node tree"), + "DEL_SUBNET", c->name, c->hostname, name); + return 0; + } + + /* Check if subnet string is valid */ + + s = str2net(subnetstr); + + if(!s) { + syslog(LOG_ERR, _("Got bad %s from %s (%s): %s"), "DEL_SUBNET", c->name, + c->hostname, _("invalid subnet string")); + return -1; + } + + if(seen_request(c->buffer)) + return 0; + + /* If everything is correct, delete the subnet from the list of the owner */ + + s->owner = owner; + + find = lookup_subnet(owner, s); + + free_subnet(s); + + if(!find) { + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_WARNING, _("Got %s from %s (%s) for %s which does not appear in his subnet tree"), + "DEL_SUBNET", c->name, c->hostname, name); + return 0; + } + + /* If we are the owner of this subnet, retaliate with an ADD_SUBNET */ + + if(owner == myself) { + if(debug_lvl >= DEBUG_PROTOCOL) + syslog(LOG_WARNING, _("Got %s from %s (%s) for ourself"), + "DEL_SUBNET", c->name, c->hostname); + send_add_subnet(c, find); + return 0; + } + + /* Tell the rest */ + + forward_request(c); + + /* Finally, delete it. */ + + subnet_del(owner, find); + + return 0; } diff --git a/src/raw_socket/device.c b/src/raw_socket/device.c index 054afee..0f239e0 100644 --- a/src/raw_socket/device.c +++ b/src/raw_socket/device.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: device.c,v 1.1.2.1 2002/07/18 14:30:45 guus Exp $ + $Id: device.c,v 1.1.2.2 2002/09/09 21:25:28 guus Exp $ */ #include "config.h" @@ -60,115 +60,103 @@ extern subnet_t mymac; */ int setup_device(void) { - struct ifreq ifr; - struct sockaddr_ll sa; -cp - if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) - interface = "eth0"; - - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = interface; - - device_info = _("raw socket"); -cp - if((device_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) - { - syslog(LOG_ERR, _("Could not open %s: %s"), device_info, strerror(errno)); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ); - if(ioctl(device_fd, SIOCGIFINDEX, &ifr)) - { - close(device_fd); - syslog(LOG_ERR, _("Can't find interface %s: %s"), interface, strerror(errno)); - return -1; - } - - memset(&sa, '0', sizeof(sa)); - sa.sll_family = AF_PACKET; - sa.sll_protocol = htons(ETH_P_ALL); - sa.sll_ifindex = ifr.ifr_ifindex; - - if(bind(device_fd, (struct sockaddr *)&sa, (socklen_t)sizeof(sa))) - { - syslog(LOG_ERR, _("Could not bind to %s: %s"), device, strerror(errno)); - return -1; - } -cp - /* Set default MAC address for ethertap devices */ - - mymac.type = SUBNET_MAC; - mymac.net.mac.address.x[0] = 0xfe; - mymac.net.mac.address.x[1] = 0xfd; - mymac.net.mac.address.x[2] = 0x00; - mymac.net.mac.address.x[3] = 0x00; - mymac.net.mac.address.x[4] = 0x00; - mymac.net.mac.address.x[5] = 0x00; - - syslog(LOG_INFO, _("%s is a %s"), device, device_info); -cp - return 0; + struct ifreq ifr; + struct sockaddr_ll sa; + cp if(!get_config_string + (lookup_config(config_tree, "Interface"), &interface)) + interface = "eth0"; + + if(!get_config_string(lookup_config(config_tree, "Device"), &device)) + device = interface; + + device_info = _("raw socket"); + cp if((device_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) { + syslog(LOG_ERR, _("Could not open %s: %s"), device_info, + strerror(errno)); + return -1; + } + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_ifrn.ifrn_name, interface, IFNAMSIZ); + if(ioctl(device_fd, SIOCGIFINDEX, &ifr)) { + close(device_fd); + syslog(LOG_ERR, _("Can't find interface %s: %s"), interface, + strerror(errno)); + return -1; + } + + memset(&sa, '0', sizeof(sa)); + sa.sll_family = AF_PACKET; + sa.sll_protocol = htons(ETH_P_ALL); + sa.sll_ifindex = ifr.ifr_ifindex; + + if(bind(device_fd, (struct sockaddr *) &sa, (socklen_t) sizeof(sa))) { + syslog(LOG_ERR, _("Could not bind to %s: %s"), device, strerror(errno)); + return -1; + } + cp + /* Set default MAC address for ethertap devices */ + mymac.type = SUBNET_MAC; + mymac.net.mac.address.x[0] = 0xfe; + mymac.net.mac.address.x[1] = 0xfd; + mymac.net.mac.address.x[2] = 0x00; + mymac.net.mac.address.x[3] = 0x00; + mymac.net.mac.address.x[4] = 0x00; + mymac.net.mac.address.x[5] = 0x00; + + syslog(LOG_INFO, _("%s is a %s"), device, device_info); + cp return 0; } void close_device(void) { -cp - close(device_fd); + cp close(device_fd); } /* read, encrypt and send data that is available through the ethertap device */ -int read_packet(vpn_packet_t *packet) +int read_packet(vpn_packet_t * packet) { - int lenin; -cp + int lenin; + cp if((lenin = read(device_fd, packet->data, MTU)) <= 0) { + syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, + device, strerror(errno)); + return -1; + } - if((lenin = read(device_fd, packet->data, MTU)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } + packet->len = lenin; - packet->len = lenin; + device_total_in += packet->len; - device_total_in += packet->len; + if(debug_lvl >= DEBUG_TRAFFIC) { + syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, + device_info); + } - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info); - } + return 0; +cp} - return 0; -cp -} - -int write_packet(vpn_packet_t *packet) +int write_packet(vpn_packet_t * packet) { -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), - packet->len, device_info); - - if(write(device_fd, packet->data, packet->len) < 0) - { - syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - device_total_out += packet->len; -cp - return 0; + cp if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), + packet->len, device_info); + + if(write(device_fd, packet->data, packet->len) < 0) { + syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, device, + strerror(errno)); + return -1; + } + + device_total_out += packet->len; + cp return 0; } void dump_device_stats(void) { -cp - syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); - syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); - syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); -cp -} + cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); + syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); + syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); +cp} diff --git a/src/route.c b/src/route.c index ad62bc2..fa99a7e 100644 --- a/src/route.c +++ b/src/route.c @@ -17,24 +17,24 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: route.c,v 1.1.2.44 2002/09/09 19:40:11 guus Exp $ + $Id: route.c,v 1.1.2.45 2002/09/09 21:25:07 guus Exp $ */ #include "config.h" #ifdef HAVE_SYS_PARAM_H - #include +#include #endif #include #include #ifdef HAVE_NET_IF_H - #include +#include #endif #ifdef HAVE_NET_ETHERNET_H - #include +#include #endif #ifdef HAVE_NETINET_IN_SYSTM_H - #include +#include #endif #include #include @@ -44,7 +44,7 @@ #include #include #ifdef HAVE_INTTYPES_H - #include +#include #endif #include @@ -59,7 +59,7 @@ #include "system.h" #ifndef ETHER_ADDR_LEN - #define ETHER_ADDR_LEN 6 +#define ETHER_ADDR_LEN 6 #endif int routing_mode = RMODE_ROUTER; @@ -67,437 +67,437 @@ int priorityinheritance = 0; int macexpire = 600; subnet_t mymac; -void learn_mac(mac_t *address) +void learn_mac(mac_t * address) { - subnet_t *subnet; - avl_node_t *node; - connection_t *c; - cp(); - subnet = lookup_subnet_mac(address); - - /* If we don't know this MAC address yet, store it */ - - if(!subnet || subnet->owner!=myself) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_INFO, _("Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"), - address->x[0], address->x[1], address->x[2], address->x[3], address->x[4], address->x[5]); - - subnet = new_subnet(); - subnet->type = SUBNET_MAC; - memcpy(&subnet->net.mac.address, address, sizeof(mac_t)); - subnet_add(myself, subnet); - - /* And tell all other tinc daemons it's our MAC */ - - for(node = connection_tree->head; node; node = node->next) - { - c = (connection_t *)node->data; - if(c->status.active) - send_add_subnet(c, subnet); - } - } - - subnet->net.mac.lastseen = now; + subnet_t *subnet; + avl_node_t *node; + connection_t *c; + + cp(); + + subnet = lookup_subnet_mac(address); + + /* If we don't know this MAC address yet, store it */ + + if(!subnet || subnet->owner != myself) { + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_INFO, _("Learned new MAC address %hx:%hx:%hx:%hx:%hx:%hx"), + address->x[0], address->x[1], address->x[2], address->x[3], + address->x[4], address->x[5]); + + subnet = new_subnet(); + subnet->type = SUBNET_MAC; + memcpy(&subnet->net.mac.address, address, sizeof(mac_t)); + subnet_add(myself, subnet); + + /* And tell all other tinc daemons it's our MAC */ + + for(node = connection_tree->head; node; node = node->next) { + c = (connection_t *) node->data; + if(c->status.active) + send_add_subnet(c, subnet); + } + } + + subnet->net.mac.lastseen = now; } void age_mac(void) { - subnet_t *s; - connection_t *c; - avl_node_t *node, *next, *node2; - cp(); - for(node = myself->subnet_tree->head; node; node = next) - { - next = node->next; - s = (subnet_t *)node->data; - if(s->type == SUBNET_MAC && s->net.mac.lastseen && s->net.mac.lastseen + macexpire < now) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_INFO, _("MAC address %hx:%hx:%hx:%hx:%hx:%hx expired"), - s->net.mac.address.x[0], s->net.mac.address.x[1], s->net.mac.address.x[2], s->net.mac.address.x[3], s->net.mac.address.x[4], s->net.mac.address.x[5]); - for(node2 = connection_tree->head; node2; node2 = node2->next) - { - c = (connection_t *)node2->data; - if(c->status.active) - send_del_subnet(c, s); - } - subnet_del(myself, s); + subnet_t *s; + connection_t *c; + avl_node_t *node, *next, *node2; + + cp(); + + for(node = myself->subnet_tree->head; node; node = next) { + next = node->next; + s = (subnet_t *) node->data; + if(s->type == SUBNET_MAC && s->net.mac.lastseen && s->net.mac.lastseen + macexpire < now) { + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_INFO, _("MAC address %hx:%hx:%hx:%hx:%hx:%hx expired"), + s->net.mac.address.x[0], s->net.mac.address.x[1], + s->net.mac.address.x[2], s->net.mac.address.x[3], + s->net.mac.address.x[4], s->net.mac.address.x[5]); + + for(node2 = connection_tree->head; node2; node2 = node2->next) { + c = (connection_t *) node2->data; + if(c->status.active) + send_del_subnet(c, s); + } + + subnet_del(myself, s); + } } - } - cp(); } -node_t *route_mac(vpn_packet_t *packet) +node_t *route_mac(vpn_packet_t * packet) { - subnet_t *subnet; - cp(); - /* Learn source address */ - - learn_mac((mac_t *)(&packet->data[6])); - - /* Lookup destination address */ - - subnet = lookup_subnet_mac((mac_t *)(&packet->data[0])); - - if(subnet) - return subnet->owner; - else - return NULL; + subnet_t *subnet; + + cp(); + + /* Learn source address */ + + learn_mac((mac_t *) (&packet->data[6])); + + /* Lookup destination address */ + + subnet = lookup_subnet_mac((mac_t *) (&packet->data[0])); + + if(subnet) + return subnet->owner; + else + return NULL; } -node_t *route_ipv4(vpn_packet_t *packet) +node_t *route_ipv4(vpn_packet_t * packet) { - subnet_t *subnet; - cp(); - if(priorityinheritance) - packet->priority = packet->data[15]; - - subnet = lookup_subnet_ipv4((ipv4_t *)&packet->data[30]); - cp(); - if(!subnet) - { - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"), - packet->data[30], packet->data[31], packet->data[32], packet->data[33]); - } - - return NULL; - } - cp(); - return subnet->owner; + subnet_t *subnet; + + cp(); + + if(priorityinheritance) + packet->priority = packet->data[15]; + + subnet = lookup_subnet_ipv4((ipv4_t *) & packet->data[30]); + + if(!subnet) { + if(debug_lvl >= DEBUG_TRAFFIC) { + syslog(LOG_WARNING, _("Cannot route packet: unknown IPv4 destination address %d.%d.%d.%d"), + packet->data[30], packet->data[31], packet->data[32], + packet->data[33]); + } + + return NULL; + } + + return subnet->owner; } -node_t *route_ipv6(vpn_packet_t *packet) +node_t *route_ipv6(vpn_packet_t * packet) { - subnet_t *subnet; - cp(); - subnet = lookup_subnet_ipv6((ipv6_t *)&packet->data[38]); - cp(); - if(!subnet) - { - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"), - ntohs(*(uint16_t *)&packet->data[38]), - ntohs(*(uint16_t *)&packet->data[40]), - ntohs(*(uint16_t *)&packet->data[42]), - ntohs(*(uint16_t *)&packet->data[44]), - ntohs(*(uint16_t *)&packet->data[46]), - ntohs(*(uint16_t *)&packet->data[48]), - ntohs(*(uint16_t *)&packet->data[50]), - ntohs(*(uint16_t *)&packet->data[52])); - } - - return NULL; - } - cp(); - return subnet->owner; + subnet_t *subnet; + + cp(); + + subnet = lookup_subnet_ipv6((ipv6_t *) & packet->data[38]); + + if(!subnet) { + if(debug_lvl >= DEBUG_TRAFFIC) { + syslog(LOG_WARNING, _("Cannot route packet: unknown IPv6 destination address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"), + ntohs(*(uint16_t *) & packet->data[38]), + ntohs(*(uint16_t *) & packet->data[40]), + ntohs(*(uint16_t *) & packet->data[42]), + ntohs(*(uint16_t *) & packet->data[44]), + ntohs(*(uint16_t *) & packet->data[46]), + ntohs(*(uint16_t *) & packet->data[48]), + ntohs(*(uint16_t *) & packet->data[50]), + ntohs(*(uint16_t *) & packet->data[52])); + } + + return NULL; + } + + return subnet->owner; } -uint16_t inet_checksum(uint16_t *data, int len, uint16_t prevsum) +uint16_t inet_checksum(uint16_t * data, int len, uint16_t prevsum) { - uint32_t checksum = prevsum ^ 0xFFFF; + uint32_t checksum = prevsum ^ 0xFFFF; - while(len--) - checksum += ntohs(*data++); + while(len--) + checksum += ntohs(*data++); - while(checksum >> 16) - checksum = (checksum & 0xFFFF) + (checksum >> 16); + while(checksum >> 16) + checksum = (checksum & 0xFFFF) + (checksum >> 16); - return checksum ^ 0xFFFF; + return checksum ^ 0xFFFF; } -void route_neighborsol(vpn_packet_t *packet) +void route_neighborsol(vpn_packet_t * packet) { - struct ip6_hdr *hdr; - struct nd_neighbor_solicit *ns; - struct nd_opt_hdr *opt; - subnet_t *subnet; - uint16_t checksum; - - struct { - struct in6_addr ip6_src; /* source address */ - struct in6_addr ip6_dst; /* destination address */ - uint32_t length; - uint8_t junk[4]; - } pseudo; - - cp(); - hdr = (struct ip6_hdr *)(packet->data + 14); - ns = (struct nd_neighbor_solicit *)(packet->data + 14 + sizeof(*hdr)); - opt = (struct nd_opt_hdr *)(packet->data + 14 + sizeof(*hdr) + sizeof(*ns)); - - /* First, snatch the source address from the neighbor solicitation packet */ - - memcpy(mymac.net.mac.address.x, packet->data + 6, 6); - - /* Check if this is a valid neighbor solicitation request */ - - if(ns->nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT || - opt->nd_opt_type != ND_OPT_SOURCE_LINKADDR) - { - if(debug_lvl > DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: received unknown type neighbor solicitation request")); - } - return; - } - - /* Create pseudo header */ - - memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16); - memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16); - pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6); - pseudo.junk[0] = pseudo.junk[1] = pseudo.junk[2] = 0; - pseudo.junk[3] = IPPROTO_ICMPV6; - - /* Generate checksum */ - - checksum = inet_checksum((uint16_t *)&pseudo, sizeof(pseudo)/2, ~0); - checksum = inet_checksum((uint16_t *)ns, sizeof(*ns)/2 + 4, checksum); - - if(checksum) - { - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_WARNING, _("Cannot route packet: checksum error for neighbor solicitation request")); - return; - } - - /* Check if the IPv6 address exists on the VPN */ - - subnet = lookup_subnet_ipv6((ipv6_t *)&ns->nd_ns_target); - - if(!subnet) - { - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: neighbor solicitation request for unknown address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"), - ntohs(((uint16_t *)&ns->nd_ns_target)[0]), ntohs(((uint16_t *)&ns->nd_ns_target)[1]), ntohs(((uint16_t *)&ns->nd_ns_target)[2]), ntohs(((uint16_t *)&ns->nd_ns_target)[3]), - ntohs(((uint16_t *)&ns->nd_ns_target)[4]), ntohs(((uint16_t *)&ns->nd_ns_target)[5]), ntohs(((uint16_t *)&ns->nd_ns_target)[6]), ntohs(((uint16_t *)&ns->nd_ns_target)[7])); - } - - return; - } - - /* Check if it is for our own subnet */ - - if(subnet->owner == myself) - return; /* silently ignore */ - - /* Create neighbor advertation reply */ - - memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */ - packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */ - - memcpy(&hdr->ip6_dst, &hdr->ip6_src, 16); /* swap destination and source protocol address */ - memcpy(&hdr->ip6_src, &ns->nd_ns_target, 16); /* ... */ - - memcpy((char *)opt + sizeof(*opt), packet->data + ETHER_ADDR_LEN, 6); /* add fake source hard addr */ - - ns->nd_ns_hdr.icmp6_cksum = 0; - ns->nd_ns_hdr.icmp6_type = ND_NEIGHBOR_ADVERT; - ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[0] = 0x40; /* Set solicited flag */ - ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[1] = ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[2] = ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[3] = 0; - opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; - - /* Create pseudo header */ - - memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16); - memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16); - pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6); - pseudo.junk[0] = pseudo.junk[1] = pseudo.junk[2] = 0; - pseudo.junk[3] = IPPROTO_ICMPV6; - - /* Generate checksum */ - - checksum = inet_checksum((uint16_t *)&pseudo, sizeof(pseudo)/2, ~0); - checksum = inet_checksum((uint16_t *)ns, sizeof(*ns)/2 + 4, checksum); - - ns->nd_ns_hdr.icmp6_cksum = htons(checksum); - - write_packet(packet); - cp(); + struct ip6_hdr *hdr; + struct nd_neighbor_solicit *ns; + struct nd_opt_hdr *opt; + subnet_t *subnet; + uint16_t checksum; + + struct { + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* destination address */ + uint32_t length; + uint8_t junk[4]; + } pseudo; + + cp(); + + hdr = (struct ip6_hdr *) (packet->data + 14); + ns = (struct nd_neighbor_solicit *) (packet->data + 14 + sizeof(*hdr)); + opt = (struct nd_opt_hdr *) (packet->data + 14 + sizeof(*hdr) + sizeof(*ns)); + + /* First, snatch the source address from the neighbor solicitation packet */ + + memcpy(mymac.net.mac.address.x, packet->data + 6, 6); + + /* Check if this is a valid neighbor solicitation request */ + + if(ns->nd_ns_hdr.icmp6_type != ND_NEIGHBOR_SOLICIT || + opt->nd_opt_type != ND_OPT_SOURCE_LINKADDR) { + if(debug_lvl > DEBUG_TRAFFIC) { + syslog(LOG_WARNING, _("Cannot route packet: received unknown type neighbor solicitation request")); + } + return; + } + + /* Create pseudo header */ + + memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16); + memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16); + pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6); + pseudo.junk[0] = pseudo.junk[1] = pseudo.junk[2] = 0; + pseudo.junk[3] = IPPROTO_ICMPV6; + + /* Generate checksum */ + + checksum = inet_checksum((uint16_t *) & pseudo, sizeof(pseudo) / 2, ~0); + checksum = inet_checksum((uint16_t *) ns, sizeof(*ns) / 2 + 4, checksum); + + if(checksum) { + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_WARNING, _("Cannot route packet: checksum error for neighbor solicitation request")); + return; + } + + /* Check if the IPv6 address exists on the VPN */ + + subnet = lookup_subnet_ipv6((ipv6_t *) & ns->nd_ns_target); + + if(!subnet) { + if(debug_lvl >= DEBUG_TRAFFIC) { + syslog(LOG_WARNING, _("Cannot route packet: neighbor solicitation request for unknown address %hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"), + ntohs(((uint16_t *) & ns->nd_ns_target)[0]), + ntohs(((uint16_t *) & ns->nd_ns_target)[1]), + ntohs(((uint16_t *) & ns->nd_ns_target)[2]), + ntohs(((uint16_t *) & ns->nd_ns_target)[3]), + ntohs(((uint16_t *) & ns->nd_ns_target)[4]), + ntohs(((uint16_t *) & ns->nd_ns_target)[5]), + ntohs(((uint16_t *) & ns->nd_ns_target)[6]), + ntohs(((uint16_t *) & ns->nd_ns_target)[7])); + } + + return; + } + + /* Check if it is for our own subnet */ + + if(subnet->owner == myself) + return; /* silently ignore */ + + /* Create neighbor advertation reply */ + + memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */ + packet->data[ETHER_ADDR_LEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */ + + memcpy(&hdr->ip6_dst, &hdr->ip6_src, 16); /* swap destination and source protocol address */ + memcpy(&hdr->ip6_src, &ns->nd_ns_target, 16); /* ... */ + + memcpy((char *) opt + sizeof(*opt), packet->data + ETHER_ADDR_LEN, 6); /* add fake source hard addr */ + + ns->nd_ns_hdr.icmp6_cksum = 0; + ns->nd_ns_hdr.icmp6_type = ND_NEIGHBOR_ADVERT; + ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[0] = 0x40; /* Set solicited flag */ + ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[1] = + ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[2] = + ns->nd_ns_hdr.icmp6_dataun.icmp6_un_data8[3] = 0; + opt->nd_opt_type = ND_OPT_TARGET_LINKADDR; + + /* Create pseudo header */ + + memcpy(&pseudo.ip6_src, &hdr->ip6_src, 16); + memcpy(&pseudo.ip6_dst, &hdr->ip6_dst, 16); + pseudo.length = htonl(sizeof(*ns) + sizeof(*opt) + 6); + pseudo.junk[0] = pseudo.junk[1] = pseudo.junk[2] = 0; + pseudo.junk[3] = IPPROTO_ICMPV6; + + /* Generate checksum */ + + checksum = inet_checksum((uint16_t *) & pseudo, sizeof(pseudo) / 2, ~0); + checksum = inet_checksum((uint16_t *) ns, sizeof(*ns) / 2 + 4, checksum); + + ns->nd_ns_hdr.icmp6_cksum = htons(checksum); + + write_packet(packet); } -void route_arp(vpn_packet_t *packet) +void route_arp(vpn_packet_t * packet) { - struct ether_arp *arp; - subnet_t *subnet; - uint8_t ipbuf[4]; - cp(); - /* First, snatch the source address from the ARP packet */ - - memcpy(mymac.net.mac.address.x, packet->data + 6, 6); - - /* This routine generates replies to ARP requests. - You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD). - Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp) - */ - - arp = (struct ether_arp *)(packet->data + 14); - - /* Check if this is a valid ARP request */ - - if(ntohs(arp->arp_hrd) != ARPHRD_ETHER || - ntohs(arp->arp_pro) != ETHERTYPE_IP || - arp->arp_hln != ETHER_ADDR_LEN || - arp->arp_pln != 4 || - ntohs(arp->arp_op) != ARPOP_REQUEST ) - { - if(debug_lvl > DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request")); - } - return; - } - - /* Check if the IPv4 address exists on the VPN */ - - subnet = lookup_subnet_ipv4((ipv4_t *)arp->arp_tpa); - - if(!subnet) - { - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"), - arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], arp->arp_tpa[3]); - } - - return; - } - - /* Check if it is for our own subnet */ - - if(subnet->owner == myself) - return; /* silently ignore */ - - memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */ - packet->data[ETHER_ADDR_LEN*2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */ - - memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */ - memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */ - memcpy(arp->arp_spa, ipbuf, 4); /* ... */ - - memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */ - memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */ - arp->arp_op = htons(ARPOP_REPLY); - - write_packet(packet); - cp(); + struct ether_arp *arp; + subnet_t *subnet; + uint8_t ipbuf[4]; + + cp(); + + /* First, snatch the source address from the ARP packet */ + + memcpy(mymac.net.mac.address.x, packet->data + 6, 6); + + /* This routine generates replies to ARP requests. + You don't need to set NOARP flag on the interface anymore (which is broken on FreeBSD). + Most of the code here is taken from choparp.c by Takamichi Tateoka (tree@mma.club.uec.ac.jp) + */ + + arp = (struct ether_arp *) (packet->data + 14); + + /* Check if this is a valid ARP request */ + + if(ntohs(arp->arp_hrd) != ARPHRD_ETHER || ntohs(arp->arp_pro) != ETHERTYPE_IP || + arp->arp_hln != ETHER_ADDR_LEN || arp->arp_pln != 4 || ntohs(arp->arp_op) != ARPOP_REQUEST) { + if(debug_lvl > DEBUG_TRAFFIC) { + syslog(LOG_WARNING, _("Cannot route packet: received unknown type ARP request")); + } + return; + } + + /* Check if the IPv4 address exists on the VPN */ + + subnet = lookup_subnet_ipv4((ipv4_t *) arp->arp_tpa); + + if(!subnet) { + if(debug_lvl >= DEBUG_TRAFFIC) { + syslog(LOG_WARNING, _("Cannot route packet: ARP request for unknown address %d.%d.%d.%d"), + arp->arp_tpa[0], arp->arp_tpa[1], arp->arp_tpa[2], + arp->arp_tpa[3]); + } + + return; + } + + /* Check if it is for our own subnet */ + + if(subnet->owner == myself) + return; /* silently ignore */ + + memcpy(packet->data, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* copy destination address */ + packet->data[ETHER_ADDR_LEN * 2 - 1] ^= 0xFF; /* mangle source address so it looks like it's not from us */ + + memcpy(ipbuf, arp->arp_tpa, 4); /* save protocol addr */ + memcpy(arp->arp_tpa, arp->arp_spa, 4); /* swap destination and source protocol address */ + memcpy(arp->arp_spa, ipbuf, 4); /* ... */ + + memcpy(arp->arp_tha, arp->arp_sha, 10); /* set target hard/proto addr */ + memcpy(arp->arp_sha, packet->data + ETHER_ADDR_LEN, ETHER_ADDR_LEN); /* add fake source hard addr */ + arp->arp_op = htons(ARPOP_REPLY); + + write_packet(packet); } -void route_outgoing(vpn_packet_t *packet) +void route_outgoing(vpn_packet_t * packet) { - uint16_t type; - node_t *n = NULL; - cp(); - /* FIXME: multicast? */ - - switch(routing_mode) - { - case RMODE_ROUTER: - type = ntohs(*((uint16_t *)(&packet->data[12]))); - switch(type) - { - case 0x0800: - n = route_ipv4(packet); - break; - case 0x86DD: - if(packet->data[20] == IPPROTO_ICMPV6 && packet->data[54] == ND_NEIGHBOR_SOLICIT) - { - route_neighborsol(packet); - return; - } - n = route_ipv6(packet); - break; - case 0x0806: - route_arp(packet); - return; - default: - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type); - } - return; - } - if(n) - send_packet(n, packet); - break; - - case RMODE_SWITCH: - n = route_mac(packet); - if(n) - send_packet(n, packet); - else - broadcast_packet(myself, packet); - break; - - case RMODE_HUB: - broadcast_packet(myself, packet); - break; - } + uint16_t type; + node_t *n = NULL; + + cp(); + + /* FIXME: multicast? */ + + switch (routing_mode) { + case RMODE_ROUTER: + type = ntohs(*((uint16_t *) (&packet->data[12]))); + switch (type) { + case 0x0800: + n = route_ipv4(packet); + break; + + case 0x86DD: + if(packet->data[20] == IPPROTO_ICMPV6 && packet->data[54] == ND_NEIGHBOR_SOLICIT) { + route_neighborsol(packet); + return; + } + n = route_ipv6(packet); + break; + + case 0x0806: + route_arp(packet); + return; + + default: + if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_WARNING, _("Cannot route packet: unknown type %hx"), type); + return; + } + if(n) + send_packet(n, packet); + break; + + case RMODE_SWITCH: + n = route_mac(packet); + if(n) + send_packet(n, packet); + else + broadcast_packet(myself, packet); + break; + + case RMODE_HUB: + broadcast_packet(myself, packet); + break; + } } -void route_incoming(node_t *source, vpn_packet_t *packet) +void route_incoming(node_t * source, vpn_packet_t * packet) { - switch(routing_mode) - { - case RMODE_ROUTER: - { - node_t *n = NULL; - uint16_t type; - - type = ntohs(*((uint16_t *)(&packet->data[12]))); - switch(type) - { - case 0x0800: - n = route_ipv4(packet); - break; - case 0x86DD: - n = route_ipv6(packet); - break; - default: - n = myself; - break; - } - - if(n) - { - if(n == myself) - { - memcpy(packet->data, mymac.net.mac.address.x, 6); - write_packet(packet); - } - else - send_packet(n, packet); - } - } - break; - case RMODE_SWITCH: - { - subnet_t *subnet; - - subnet = lookup_subnet_mac((mac_t *)(&packet->data[0])); - - if(subnet) - { - if(subnet->owner == myself) - write_packet(packet); - else - send_packet(subnet->owner, packet); - } - else - { - broadcast_packet(source, packet); - write_packet(packet); - } - } - break; - case RMODE_HUB: - broadcast_packet(source, packet); /* Spread it on */ - write_packet(packet); - break; - } + switch (routing_mode) { + case RMODE_ROUTER: + { + node_t *n = NULL; + uint16_t type; + + type = ntohs(*((uint16_t *) (&packet->data[12]))); + switch (type) { + case 0x0800: + n = route_ipv4(packet); + break; + + case 0x86DD: + n = route_ipv6(packet); + break; + + default: + n = myself; + break; + } + + if(n) { + if(n == myself) { + memcpy(packet->data, mymac.net.mac.address.x, 6); + write_packet(packet); + } else + send_packet(n, packet); + } + } + break; + + case RMODE_SWITCH: + { + subnet_t *subnet; + + subnet = lookup_subnet_mac((mac_t *) (&packet->data[0])); + + if(subnet) { + if(subnet->owner == myself) + write_packet(packet); + else + send_packet(subnet->owner, packet); + } else { + broadcast_packet(source, packet); + write_packet(packet); + } + } + break; + + case RMODE_HUB: + broadcast_packet(source, packet); /* Spread it on */ + write_packet(packet); + break; + } } diff --git a/src/route.h b/src/route.h index 2883b03..1752d47 100644 --- a/src/route.h +++ b/src/route.h @@ -17,17 +17,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: route.h,v 1.1.2.8 2002/06/21 10:11:33 guus Exp $ + $Id: route.h,v 1.1.2.9 2002/09/09 21:25:07 guus Exp $ */ #ifndef __TINC_ROUTE_H__ #define __TINC_ROUTE_H__ -enum -{ - RMODE_HUB = 0, - RMODE_SWITCH, - RMODE_ROUTER, +enum { + RMODE_HUB = 0, + RMODE_SWITCH, + RMODE_ROUTER, }; extern int routing_mode; @@ -38,4 +37,4 @@ extern void age_mac(void); extern void route_incoming(node_t *, vpn_packet_t *); extern void route_outgoing(vpn_packet_t *); -#endif /* __TINC_ROUTE_H__ */ +#endif /* __TINC_ROUTE_H__ */ diff --git a/src/solaris/device.c b/src/solaris/device.c index c72662b..bab7236 100644 --- a/src/solaris/device.c +++ b/src/solaris/device.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: device.c,v 1.1.2.8 2002/06/21 10:11:37 guus Exp $ + $Id: device.c,v 1.1.2.9 2002/09/09 21:25:28 guus Exp $ */ @@ -61,136 +61,126 @@ subnet_t mymac; int setup_device(void) { - int ip_fd = -1, if_fd = -1; - int ppa; - char *ptr; - -cp - if(!get_config_string(lookup_config(config_tree, "Device"), &device)) - device = DEFAULT_DEVICE; - -cp - if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) - { - syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); - return -1; - } -cp - ppa = 0; - - ptr = device; - while(*ptr && !isdigit((int)*ptr)) ptr++; - ppa = atoi(ptr); - - if( (ip_fd = open("/dev/ip", O_RDWR, 0)) < 0){ - syslog(LOG_ERR, _("Could not open /dev/ip: %s"), strerror(errno)); - return -1; - } - - /* Assign a new PPA and get its unit number. */ - if( (ppa = ioctl(device_fd, TUNNEWPPA, ppa)) < 0){ - syslog(LOG_ERR, _("Can't assign new interface: %s"), strerror(errno)); - return -1; - } - - if( (if_fd = open(device, O_RDWR, 0)) < 0){ - syslog(LOG_ERR, _("Could not open %s twice: %s"), device, strerror(errno)); - return -1; - } - - if(ioctl(if_fd, I_PUSH, "ip") < 0){ - syslog(LOG_ERR, _("Can't push IP module: %s"), strerror(errno)); - return -1; - } - - /* Assign ppa according to the unit number returned by tun device */ - if(ioctl(if_fd, IF_UNITSEL, (char *)&ppa) < 0){ - syslog(LOG_ERR, _("Can't set PPA %d: %s"), ppa, strerror(errno)); - return -1; - } - - if(ioctl(ip_fd, I_LINK, if_fd) < 0){ - syslog(LOG_ERR, _("Can't link TUN device to IP: %s"), strerror(errno)); - return -1; - } - - if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) - asprintf(&interface, "tun%d", ppa); - - device_info = _("Solaris tun device"); - - /* Set default MAC address for ethertap devices */ - - mymac.type = SUBNET_MAC; - mymac.net.mac.address.x[0] = 0xfe; - mymac.net.mac.address.x[1] = 0xfd; - mymac.net.mac.address.x[2] = 0x00; - mymac.net.mac.address.x[3] = 0x00; - mymac.net.mac.address.x[4] = 0x00; - mymac.net.mac.address.x[5] = 0x00; - - syslog(LOG_INFO, _("%s is a %s"), device, device_info); -cp - return 0; + int ip_fd = -1, if_fd = -1; + int ppa; + char *ptr; + + cp if(!get_config_string(lookup_config(config_tree, "Device"), &device)) + device = DEFAULT_DEVICE; + + cp if((device_fd = open(device, O_RDWR | O_NONBLOCK)) < 0) { + syslog(LOG_ERR, _("Could not open %s: %s"), device, strerror(errno)); + return -1; + } + cp ppa = 0; + + ptr = device; + while(*ptr && !isdigit((int) *ptr)) + ptr++; + ppa = atoi(ptr); + + if((ip_fd = open("/dev/ip", O_RDWR, 0)) < 0) { + syslog(LOG_ERR, _("Could not open /dev/ip: %s"), strerror(errno)); + return -1; + } + + /* Assign a new PPA and get its unit number. */ + if((ppa = ioctl(device_fd, TUNNEWPPA, ppa)) < 0) { + syslog(LOG_ERR, _("Can't assign new interface: %s"), strerror(errno)); + return -1; + } + + if((if_fd = open(device, O_RDWR, 0)) < 0) { + syslog(LOG_ERR, _("Could not open %s twice: %s"), device, + strerror(errno)); + return -1; + } + + if(ioctl(if_fd, I_PUSH, "ip") < 0) { + syslog(LOG_ERR, _("Can't push IP module: %s"), strerror(errno)); + return -1; + } + + /* Assign ppa according to the unit number returned by tun device */ + if(ioctl(if_fd, IF_UNITSEL, (char *) &ppa) < 0) { + syslog(LOG_ERR, _("Can't set PPA %d: %s"), ppa, strerror(errno)); + return -1; + } + + if(ioctl(ip_fd, I_LINK, if_fd) < 0) { + syslog(LOG_ERR, _("Can't link TUN device to IP: %s"), strerror(errno)); + return -1; + } + + if(!get_config_string(lookup_config(config_tree, "Interface"), &interface)) + asprintf(&interface, "tun%d", ppa); + + device_info = _("Solaris tun device"); + + /* Set default MAC address for ethertap devices */ + + mymac.type = SUBNET_MAC; + mymac.net.mac.address.x[0] = 0xfe; + mymac.net.mac.address.x[1] = 0xfd; + mymac.net.mac.address.x[2] = 0x00; + mymac.net.mac.address.x[3] = 0x00; + mymac.net.mac.address.x[4] = 0x00; + mymac.net.mac.address.x[5] = 0x00; + + syslog(LOG_INFO, _("%s is a %s"), device, device_info); + cp return 0; } void close_device(void) { -cp - close(device_fd); + cp close(device_fd); } -int read_packet(vpn_packet_t *packet) +int read_packet(vpn_packet_t * packet) { - int lenin; -cp - if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) - { - syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, device, strerror(errno)); - return -1; - } - - memcpy(packet->data, mymac.net.mac.address.x, 6); - memcpy(packet->data + 6, mymac.net.mac.address.x, 6); - packet->data[12] = 0x08; - packet->data[13] = 0x00; - - packet->len = lenin + 14; - - device_total_in += packet->len; - - if(debug_lvl >= DEBUG_TRAFFIC) - { - syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, device_info); - } - - return 0; -cp -} + int lenin; + cp if((lenin = read(device_fd, packet->data + 14, MTU - 14)) <= 0) { + syslog(LOG_ERR, _("Error while reading from %s %s: %s"), device_info, + device, strerror(errno)); + return -1; + } + + memcpy(packet->data, mymac.net.mac.address.x, 6); + memcpy(packet->data + 6, mymac.net.mac.address.x, 6); + packet->data[12] = 0x08; + packet->data[13] = 0x00; + + packet->len = lenin + 14; + + device_total_in += packet->len; -int write_packet(vpn_packet_t *packet) + if(debug_lvl >= DEBUG_TRAFFIC) { + syslog(LOG_DEBUG, _("Read packet of %d bytes from %s"), packet->len, + device_info); + } + + return 0; +cp} + +int write_packet(vpn_packet_t * packet) { -cp - if(debug_lvl >= DEBUG_TRAFFIC) - syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), - packet->len, device_info); - - if(write(device_fd, packet->data + 14, packet->len - 14) < 0) - { - syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, packet->len, strerror(errno)); - return -1; - } - - device_total_out += packet->len; -cp - return 0; + cp if(debug_lvl >= DEBUG_TRAFFIC) + syslog(LOG_DEBUG, _("Writing packet of %d bytes to %s"), + packet->len, device_info); + + if(write(device_fd, packet->data + 14, packet->len - 14) < 0) { + syslog(LOG_ERR, _("Can't write to %s %s: %s"), device_info, packet->len, + strerror(errno)); + return -1; + } + + device_total_out += packet->len; + cp return 0; } void dump_device_stats(void) { -cp - syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); - syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); - syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); -cp -} + cp syslog(LOG_DEBUG, _("Statistics for %s %s:"), device_info, device); + syslog(LOG_DEBUG, _(" total bytes in: %10d"), device_total_in); + syslog(LOG_DEBUG, _(" total bytes out: %10d"), device_total_out); +cp} diff --git a/src/subnet.c b/src/subnet.c index e6d8b9b..4ceec9a 100644 --- a/src/subnet.c +++ b/src/subnet.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: subnet.c,v 1.1.2.40 2002/09/09 19:40:11 guus Exp $ + $Id: subnet.c,v 1.1.2.41 2002/09/09 21:25:10 guus Exp $ */ #include "config.h" @@ -48,366 +48,379 @@ avl_tree_t *subnet_tree; /* Subnet comparison */ -int subnet_compare_mac(subnet_t *a, subnet_t *b) +int subnet_compare_mac(subnet_t * a, subnet_t * b) { - int result; - cp(); - result = memcmp(&a->net.mac.address, &b->net.mac.address, sizeof(mac_t)); - - if(result || !a->owner || !b->owner) - return result; - - return strcmp(a->owner->name, b->owner->name); + int result; + + result = memcmp(&a->net.mac.address, &b->net.mac.address, sizeof(mac_t)); + + if(result || !a->owner || !b->owner) + return result; + + return strcmp(a->owner->name, b->owner->name); } -int subnet_compare_ipv4(subnet_t *a, subnet_t *b) +int subnet_compare_ipv4(subnet_t * a, subnet_t * b) { - int result; - cp(); - result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t)); - - if(result) - return result; - - result = a->net.ipv4.prefixlength - b->net.ipv4.prefixlength; - - if(result || !a->owner || !b->owner) - return result; - - return strcmp(a->owner->name, b->owner->name); + int result; + + result = memcmp(&a->net.ipv4.address, &b->net.ipv4.address, sizeof(ipv4_t)); + + if(result) + return result; + + result = a->net.ipv4.prefixlength - b->net.ipv4.prefixlength; + + if(result || !a->owner || !b->owner) + return result; + + return strcmp(a->owner->name, b->owner->name); } -int subnet_compare_ipv6(subnet_t *a, subnet_t *b) +int subnet_compare_ipv6(subnet_t * a, subnet_t * b) { - int result; - cp(); - result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t)); - - if(result) - return result; - - result = a->net.ipv6.prefixlength - b->net.ipv6.prefixlength; - - if(result || !a->owner || !b->owner) - return result; - - return strcmp(a->owner->name, b->owner->name); + int result; + + result = memcmp(&a->net.ipv6.address, &b->net.ipv6.address, sizeof(ipv6_t)); + + if(result) + return result; + + result = a->net.ipv6.prefixlength - b->net.ipv6.prefixlength; + + if(result || !a->owner || !b->owner) + return result; + + return strcmp(a->owner->name, b->owner->name); } -int subnet_compare(subnet_t *a, subnet_t *b) +int subnet_compare(subnet_t * a, subnet_t * b) { - int result; - cp(); - result = a->type - b->type; - - if(result) - return result; - - switch(a->type) - { - case SUBNET_MAC: - return subnet_compare_mac(a, b); - case SUBNET_IPV4: - return subnet_compare_ipv4(a, b); - case SUBNET_IPV6: - return subnet_compare_ipv6(a, b); - default: - syslog(LOG_ERR, _("subnet_compare() was called with unknown subnet type %d, exitting!"), a->type); - cp_trace(); - exit(0); - } - - return 0; + int result; + + result = a->type - b->type; + + if(result) + return result; + + switch (a->type) { + case SUBNET_MAC: + return subnet_compare_mac(a, b); + case SUBNET_IPV4: + return subnet_compare_ipv4(a, b); + case SUBNET_IPV6: + return subnet_compare_ipv6(a, b); + default: + syslog(LOG_ERR, + _ + ("subnet_compare() was called with unknown subnet type %d, exitting!"), + a->type); + cp_trace(); + exit(0); + } + + return 0; } /* Initialising trees */ void init_subnets(void) { - cp(); - subnet_tree = avl_alloc_tree((avl_compare_t)subnet_compare, (avl_action_t)free_subnet); - cp(); + cp(); + + subnet_tree = avl_alloc_tree((avl_compare_t) subnet_compare, (avl_action_t) free_subnet); } void exit_subnets(void) { - cp(); - avl_delete_tree(subnet_tree); - cp(); + cp(); + + avl_delete_tree(subnet_tree); } avl_tree_t *new_subnet_tree(void) { - cp(); - return avl_alloc_tree((avl_compare_t)subnet_compare, NULL); - cp(); + cp(); + + return avl_alloc_tree((avl_compare_t) subnet_compare, NULL); } -void free_subnet_tree(avl_tree_t *subnet_tree) +void free_subnet_tree(avl_tree_t * subnet_tree) { - cp(); - avl_delete_tree(subnet_tree); - cp(); + cp(); + + avl_delete_tree(subnet_tree); } /* Allocating and freeing space for subnets */ subnet_t *new_subnet(void) { - cp(); - return (subnet_t *)xmalloc_and_zero(sizeof(subnet_t)); + cp(); + + return (subnet_t *) xmalloc_and_zero(sizeof(subnet_t)); } -void free_subnet(subnet_t *subnet) +void free_subnet(subnet_t * subnet) { - cp(); - free(subnet); + cp(); + + free(subnet); } /* Adding and removing subnets */ -void subnet_add(node_t *n, subnet_t *subnet) +void subnet_add(node_t * n, subnet_t * subnet) { - cp(); - subnet->owner = n; + cp(); + + subnet->owner = n; - avl_insert(subnet_tree, subnet); - cp(); - avl_insert(n->subnet_tree, subnet); - cp(); + avl_insert(subnet_tree, subnet); + avl_insert(n->subnet_tree, subnet); } -void subnet_del(node_t *n, subnet_t *subnet) +void subnet_del(node_t * n, subnet_t * subnet) { - cp(); - avl_delete(n->subnet_tree, subnet); - cp(); - avl_delete(subnet_tree, subnet); - cp(); + cp(); + + avl_delete(n->subnet_tree, subnet); + avl_delete(subnet_tree, subnet); } /* Ascii representation of subnets */ subnet_t *str2net(char *subnetstr) { - int i, l; - subnet_t *subnet; - uint16_t x[8]; - cp(); - subnet = new_subnet(); - cp(); - if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d", - &x[0], &x[1], &x[2], &x[3], - &l) == 5) - { - subnet->type = SUBNET_IPV4; - subnet->net.ipv4.prefixlength = l; - for(i = 0; i < 4; i++) - subnet->net.ipv4.address.x[i] = x[i]; - return subnet; - } - - if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d", - &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], - &l) == 9) - { - subnet->type = SUBNET_IPV6; - subnet->net.ipv6.prefixlength = l; - for(i = 0; i < 8; i++) - subnet->net.ipv6.address.x[i] = htons(x[i]); - return subnet; - } - - if(sscanf(subnetstr, "%hu.%hu.%hu.%hu", - &x[0], &x[1], &x[2], &x[3]) == 4) - { - subnet->type = SUBNET_IPV4; - subnet->net.ipv4.prefixlength = 32; - for(i = 0; i < 4; i++) - subnet->net.ipv4.address.x[i] = x[i]; - return subnet; - } - - if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", - &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7]) == 8) - { - subnet->type = SUBNET_IPV6; - subnet->net.ipv6.prefixlength = 128; - for(i = 0; i < 8; i++) - subnet->net.ipv6.address.x[i] = htons(x[i]); - return subnet; - } - - if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx", - &x[0], &x[1], &x[2], &x[3], &x[4], &x[5]) == 6) - { - subnet->type = SUBNET_MAC; - for(i = 0; i < 6; i++) - subnet->net.mac.address.x[i] = x[i]; - return subnet; - } - - free(subnet); - return NULL; + int i, l; + subnet_t *subnet; + uint16_t x[8]; + + cp(); + + subnet = new_subnet(); + + if(sscanf(subnetstr, "%hu.%hu.%hu.%hu/%d", + &x[0], &x[1], &x[2], &x[3], &l) == 5) { + subnet->type = SUBNET_IPV4; + subnet->net.ipv4.prefixlength = l; + + for(i = 0; i < 4; i++) + subnet->net.ipv4.address.x[i] = x[i]; + + return subnet; + } + + if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d", + &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7], + &l) == 9) { + subnet->type = SUBNET_IPV6; + subnet->net.ipv6.prefixlength = l; + + for(i = 0; i < 8; i++) + subnet->net.ipv6.address.x[i] = htons(x[i]); + + return subnet; + } + + if(sscanf(subnetstr, "%hu.%hu.%hu.%hu", &x[0], &x[1], &x[2], &x[3]) == 4) { + subnet->type = SUBNET_IPV4; + subnet->net.ipv4.prefixlength = 32; + + for(i = 0; i < 4; i++) + subnet->net.ipv4.address.x[i] = x[i]; + + return subnet; + } + + if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", + &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7]) == 8) { + subnet->type = SUBNET_IPV6; + subnet->net.ipv6.prefixlength = 128; + + for(i = 0; i < 8; i++) + subnet->net.ipv6.address.x[i] = htons(x[i]); + + return subnet; + } + + if(sscanf(subnetstr, "%hx:%hx:%hx:%hx:%hx:%hx", + &x[0], &x[1], &x[2], &x[3], &x[4], &x[5]) == 6) { + subnet->type = SUBNET_MAC; + + for(i = 0; i < 6; i++) + subnet->net.mac.address.x[i] = x[i]; + + return subnet; + } + + free(subnet); + + return NULL; } -char *net2str(subnet_t *subnet) +char *net2str(subnet_t * subnet) { - char *netstr; - cp(); - switch(subnet->type) - { - case SUBNET_MAC: - asprintf(&netstr, "%hx:%hx:%hx:%hx:%hx:%hx", - subnet->net.mac.address.x[0], - subnet->net.mac.address.x[1], - subnet->net.mac.address.x[2], - subnet->net.mac.address.x[3], - subnet->net.mac.address.x[4], - subnet->net.mac.address.x[5]); - break; - case SUBNET_IPV4: - asprintf(&netstr, "%hu.%hu.%hu.%hu/%d", - subnet->net.ipv4.address.x[0], - subnet->net.ipv4.address.x[1], - subnet->net.ipv4.address.x[2], - subnet->net.ipv4.address.x[3], - subnet->net.ipv4.prefixlength); - break; - case SUBNET_IPV6: - asprintf(&netstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d", - ntohs(subnet->net.ipv6.address.x[0]), - ntohs(subnet->net.ipv6.address.x[1]), - ntohs(subnet->net.ipv6.address.x[2]), - ntohs(subnet->net.ipv6.address.x[3]), - ntohs(subnet->net.ipv6.address.x[4]), - ntohs(subnet->net.ipv6.address.x[5]), - ntohs(subnet->net.ipv6.address.x[6]), - ntohs(subnet->net.ipv6.address.x[7]), - subnet->net.ipv6.prefixlength); - break; - default: - syslog(LOG_ERR, _("net2str() was called with unknown subnet type %d, exiting!"), subnet->type); - cp_trace(); - exit(0); - } - cp(); - return netstr; + char *netstr; + + cp(); + + switch (subnet->type) { + case SUBNET_MAC: + asprintf(&netstr, "%hx:%hx:%hx:%hx:%hx:%hx", + subnet->net.mac.address.x[0], + subnet->net.mac.address.x[1], + subnet->net.mac.address.x[2], + subnet->net.mac.address.x[3], + subnet->net.mac.address.x[4], subnet->net.mac.address.x[5]); + break; + + case SUBNET_IPV4: + asprintf(&netstr, "%hu.%hu.%hu.%hu/%d", + subnet->net.ipv4.address.x[0], + subnet->net.ipv4.address.x[1], + subnet->net.ipv4.address.x[2], + subnet->net.ipv4.address.x[3], subnet->net.ipv4.prefixlength); + break; + + case SUBNET_IPV6: + asprintf(&netstr, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx/%d", + ntohs(subnet->net.ipv6.address.x[0]), + ntohs(subnet->net.ipv6.address.x[1]), + ntohs(subnet->net.ipv6.address.x[2]), + ntohs(subnet->net.ipv6.address.x[3]), + ntohs(subnet->net.ipv6.address.x[4]), + ntohs(subnet->net.ipv6.address.x[5]), + ntohs(subnet->net.ipv6.address.x[6]), + ntohs(subnet->net.ipv6.address.x[7]), + subnet->net.ipv6.prefixlength); + break; + + default: + syslog(LOG_ERR, + _("net2str() was called with unknown subnet type %d, exiting!"), + subnet->type); + cp_trace(); + exit(0); + } + + return netstr; } /* Subnet lookup routines */ -subnet_t *lookup_subnet(node_t *owner, subnet_t *subnet) +subnet_t *lookup_subnet(node_t * owner, subnet_t * subnet) { - cp(); - return avl_search(owner->subnet_tree, subnet); + cp(); + + return avl_search(owner->subnet_tree, subnet); } -subnet_t *lookup_subnet_mac(mac_t *address) +subnet_t *lookup_subnet_mac(mac_t * address) { - subnet_t subnet, *p; - cp(); - subnet.type = SUBNET_MAC; - memcpy(&subnet.net.mac.address, address, sizeof(mac_t)); - subnet.owner = NULL; - - p = (subnet_t *)avl_search(subnet_tree, &subnet); - cp(); - return p; + subnet_t subnet, *p; + + cp(); + + subnet.type = SUBNET_MAC; + memcpy(&subnet.net.mac.address, address, sizeof(mac_t)); + subnet.owner = NULL; + + p = (subnet_t *) avl_search(subnet_tree, &subnet); + + return p; } -subnet_t *lookup_subnet_ipv4(ipv4_t *address) +subnet_t *lookup_subnet_ipv4(ipv4_t * address) { - subnet_t subnet, *p; - cp(); - subnet.type = SUBNET_IPV4; - memcpy(&subnet.net.ipv4.address, address, sizeof(ipv4_t)); - subnet.net.ipv4.prefixlength = 32; - subnet.owner = NULL; - - do - { - /* Go find subnet */ - - p = (subnet_t *)avl_search_closest_smaller(subnet_tree, &subnet); - - /* Check if the found subnet REALLY matches */ - cp(); - if(p) - { - if(p->type != SUBNET_IPV4) - { - p = NULL; - break; - } - - if (!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength, sizeof(ipv4_t))) - break; - else - { - /* Otherwise, see if there is a bigger enclosing subnet */ - - subnet.net.ipv4.prefixlength = p->net.ipv4.prefixlength - 1; - maskcpy(&subnet.net.ipv4.address, &p->net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof(ipv4_t)); - } - } - } while (p); - cp(); - return p; + subnet_t subnet, *p; + + cp(); + + subnet.type = SUBNET_IPV4; + memcpy(&subnet.net.ipv4.address, address, sizeof(ipv4_t)); + subnet.net.ipv4.prefixlength = 32; + subnet.owner = NULL; + + do { + /* Go find subnet */ + + p = (subnet_t *) avl_search_closest_smaller(subnet_tree, &subnet); + + /* Check if the found subnet REALLY matches */ + + if(p) { + if(p->type != SUBNET_IPV4) { + p = NULL; + break; + } + + if(!maskcmp(address, &p->net.ipv4.address, p->net.ipv4.prefixlength, sizeof(ipv4_t))) + break; + else { + /* Otherwise, see if there is a bigger enclosing subnet */ + + subnet.net.ipv4.prefixlength = p->net.ipv4.prefixlength - 1; + maskcpy(&subnet.net.ipv4.address, &p->net.ipv4.address, subnet.net.ipv4.prefixlength, sizeof(ipv4_t)); + } + } + } while(p); + + return p; } -subnet_t *lookup_subnet_ipv6(ipv6_t *address) +subnet_t *lookup_subnet_ipv6(ipv6_t * address) { - subnet_t subnet, *p; - cp(); - subnet.type = SUBNET_IPV6; - memcpy(&subnet.net.ipv6.address, address, sizeof(ipv6_t)); - subnet.net.ipv6.prefixlength = 128; - subnet.owner = NULL; - - do - { - /* Go find subnet */ - - p = (subnet_t *)avl_search_closest_smaller(subnet_tree, &subnet); - - /* Check if the found subnet REALLY matches */ - - cp(); - if(p) - { - if(p->type != SUBNET_IPV6) - return NULL; - - if (!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength, sizeof(ipv6_t))) - break; - else - { - /* Otherwise, see if there is a bigger enclosing subnet */ - - subnet.net.ipv6.prefixlength = p->net.ipv6.prefixlength - 1; - maskcpy(&subnet.net.ipv6.address, &p->net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof(ipv6_t)); - } - } - } while (p); - cp(); - return p; + subnet_t subnet, *p; + + cp(); + + subnet.type = SUBNET_IPV6; + memcpy(&subnet.net.ipv6.address, address, sizeof(ipv6_t)); + subnet.net.ipv6.prefixlength = 128; + subnet.owner = NULL; + + do { + /* Go find subnet */ + + p = (subnet_t *) avl_search_closest_smaller(subnet_tree, &subnet); + + /* Check if the found subnet REALLY matches */ + + if(p) { + if(p->type != SUBNET_IPV6) + return NULL; + + if(!maskcmp(address, &p->net.ipv6.address, p->net.ipv6.prefixlength, sizeof(ipv6_t))) + break; + else { + /* Otherwise, see if there is a bigger enclosing subnet */ + + subnet.net.ipv6.prefixlength = p->net.ipv6.prefixlength - 1; + maskcpy(&subnet.net.ipv6.address, &p->net.ipv6.address, subnet.net.ipv6.prefixlength, sizeof(ipv6_t)); + } + } + } while(p); + + return p; } void dump_subnets(void) { - char *netstr; - subnet_t *subnet; - avl_node_t *node; - cp(); - syslog(LOG_DEBUG, _("Subnet list:")); - for(node = subnet_tree->head; node; node = node->next) - { - subnet = (subnet_t *)node->data; - netstr = net2str(subnet); - syslog(LOG_DEBUG, _(" %s owner %s"), netstr, subnet->owner->name); - free(netstr); - } - syslog(LOG_DEBUG, _("End of subnet list.")); - cp(); + char *netstr; + subnet_t *subnet; + avl_node_t *node; + + cp(); + + syslog(LOG_DEBUG, _("Subnet list:")); + + for(node = subnet_tree->head; node; node = node->next) { + subnet = (subnet_t *) node->data; + netstr = net2str(subnet); + syslog(LOG_DEBUG, _(" %s owner %s"), netstr, subnet->owner->name); + free(netstr); + } + + syslog(LOG_DEBUG, _("End of subnet list.")); } diff --git a/src/subnet.h b/src/subnet.h index 0ea2186..30d13ca 100644 --- a/src/subnet.h +++ b/src/subnet.h @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: subnet.h,v 1.1.2.19 2002/06/21 10:11:34 guus Exp $ + $Id: subnet.h,v 1.1.2.20 2002/09/09 21:25:16 guus Exp $ */ #ifndef __TINC_SUBNET_H__ @@ -25,48 +25,43 @@ #include "net.h" -enum -{ - SUBNET_MAC = 0, - SUBNET_IPV4, - SUBNET_IPV6, - SUBNET_TYPES /* Guardian */ +enum { + SUBNET_MAC = 0, + SUBNET_IPV4, + SUBNET_IPV6, + SUBNET_TYPES /* Guardian */ }; -typedef struct subnet_mac_t -{ - mac_t address; - time_t lastseen; +typedef struct subnet_mac_t { + mac_t address; + time_t lastseen; } subnet_mac_t; -typedef struct subnet_ipv4_t -{ - ipv4_t address; - int prefixlength; +typedef struct subnet_ipv4_t { + ipv4_t address; + int prefixlength; } subnet_ipv4_t; -typedef struct subnet_ipv6_t -{ - ipv6_t address; - int prefixlength; +typedef struct subnet_ipv6_t { + ipv6_t address; + int prefixlength; } subnet_ipv6_t; #include "node.h" typedef struct subnet_t { - struct node_t *owner; /* the owner of this subnet */ - struct node_t *uplink; /* the uplink which we should send packets to for this subnet */ + struct node_t *owner; /* the owner of this subnet */ + struct node_t *uplink; /* the uplink which we should send packets to for this subnet */ - int type; /* subnet type (IPv4? IPv6? MAC? something even weirder?) */ + int type; /* subnet type (IPv4? IPv6? MAC? something even weirder?) */ - /* And now for the actual subnet: */ + /* And now for the actual subnet: */ - union net - { - subnet_mac_t mac; - subnet_ipv4_t ipv4; - subnet_ipv6_t ipv6; - } net; + union net { + subnet_mac_t mac; + subnet_ipv4_t ipv4; + subnet_ipv6_t ipv6; + } net; } subnet_t; extern subnet_t *new_subnet(void); @@ -85,4 +80,4 @@ extern subnet_t *lookup_subnet_ipv4(ipv4_t *); extern subnet_t *lookup_subnet_ipv6(ipv6_t *); extern void dump_subnets(void); -#endif /* __TINC_SUBNET_H__ */ +#endif /* __TINC_SUBNET_H__ */ diff --git a/src/tincd.c b/src/tincd.c index 6746c33..6bd92ec 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -17,7 +17,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - $Id: tincd.c,v 1.10.4.62 2002/09/09 19:40:12 guus Exp $ + $Id: tincd.c,v 1.10.4.63 2002/09/09 21:25:16 guus Exp $ */ #include "config.h" @@ -77,167 +77,178 @@ int bypass_security = 0; /* If nonzero, disable swapping for this process. */ int do_mlock = 0; -char *identname; /* program name for syslog */ -char *pidfilename; /* pid file location */ -char **g_argv; /* a copy of the cmdline arguments */ -char **environment; /* A pointer to the environment on - startup */ - -static struct option const long_options[] = -{ - { "config", required_argument, NULL, 'c' }, - { "kill", optional_argument, NULL, 'k' }, - { "net", required_argument, NULL, 'n' }, - { "help", no_argument, &show_help, 1 }, - { "version", no_argument, &show_version, 1 }, - { "no-detach", no_argument, &do_detach, 0 }, - { "generate-keys", optional_argument, NULL, 'K'}, - { "debug", optional_argument, NULL, 'd'}, - { "bypass-security", no_argument, &bypass_security, 1 }, - { "mlock", no_argument, &do_mlock, 1}, - { NULL, 0, NULL, 0 } +char *identname; /* program name for syslog */ +char *pidfilename; /* pid file location */ +char **g_argv; /* a copy of the cmdline arguments */ +char **environment; /* A pointer to the environment on + startup */ + +static struct option const long_options[] = { + {"config", required_argument, NULL, 'c'}, + {"kill", optional_argument, NULL, 'k'}, + {"net", required_argument, NULL, 'n'}, + {"help", no_argument, &show_help, 1}, + {"version", no_argument, &show_version, 1}, + {"no-detach", no_argument, &do_detach, 0}, + {"generate-keys", optional_argument, NULL, 'K'}, + {"debug", optional_argument, NULL, 'd'}, + {"bypass-security", no_argument, &bypass_security, 1}, + {"mlock", no_argument, &do_mlock, 1}, + {NULL, 0, NULL, 0} }; -static void -usage(int status) +static void usage(int status) { - if(status != 0) - fprintf(stderr, _("Try `%s --help\' for more information.\n"), program_name); - else - { - printf(_("Usage: %s [option]...\n\n"), program_name); - printf(_(" -c, --config=DIR Read configuration options from DIR.\n" - " -D, --no-detach Don't fork and detach.\n" - " -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n" - " -k, --kill[=SIGNAL] Attempt to kill a running tincd and exit.\n" - " -n, --net=NETNAME Connect to net NETNAME.\n" - " -K, --generate-keys[=BITS] Generate public/private RSA keypair.\n" - " -L, --mlock Lock tinc into main memory.\n" - " --help Display this help and exit.\n" - " --version Output version information and exit.\n\n")); - printf(_("Report bugs to tinc@nl.linux.org.\n")); - } - exit(status); + if(status != 0) + fprintf(stderr, _("Try `%s --help\' for more information.\n"), + program_name); + else { + printf(_("Usage: %s [option]...\n\n"), program_name); + printf(_ + (" -c, --config=DIR Read configuration options from DIR.\n" + " -D, --no-detach Don't fork and detach.\n" + " -d, --debug[=LEVEL] Increase debug level or set it to LEVEL.\n" + " -k, --kill[=SIGNAL] Attempt to kill a running tincd and exit.\n" + " -n, --net=NETNAME Connect to net NETNAME.\n" + " -K, --generate-keys[=BITS] Generate public/private RSA keypair.\n" + " -L, --mlock Lock tinc into main memory.\n" + " --help Display this help and exit.\n" + " --version Output version information and exit.\n\n")); + printf(_("Report bugs to tinc@nl.linux.org.\n")); + } + + exit(status); } -void -parse_options(int argc, char **argv, char **envp) +void parse_options(int argc, char **argv, char **envp) { - int r; - int option_index = 0; - - while((r = getopt_long(argc, argv, "c:DLd::k::n:K::", long_options, &option_index)) != EOF) - { - switch(r) - { - case 0: /* long option */ - break; - case 'c': /* config file */ - confbase = xmalloc(strlen(optarg)+1); - strcpy(confbase, optarg); - break; - case 'D': /* no detach */ - do_detach = 0; - break; - case 'L': /* no detach */ - do_mlock = 1; - break; - case 'd': /* inc debug level */ - if(optarg) - debug_lvl = atoi(optarg); - else - debug_lvl++; - break; - case 'k': /* kill old tincds */ - if(optarg) - { - if(!strcasecmp(optarg, "HUP")) - kill_tincd = SIGHUP; - else if(!strcasecmp(optarg, "TERM")) - kill_tincd = SIGTERM; - else if(!strcasecmp(optarg, "KILL")) - kill_tincd = SIGKILL; - else if(!strcasecmp(optarg, "USR1")) - kill_tincd = SIGUSR1; - else if(!strcasecmp(optarg, "USR2")) - kill_tincd = SIGUSR2; - else if(!strcasecmp(optarg, "WINCH")) - kill_tincd = SIGWINCH; - else if(!strcasecmp(optarg, "INT")) - kill_tincd = SIGINT; - else if(!strcasecmp(optarg, "ALRM")) - kill_tincd = SIGALRM; - else - { - kill_tincd = atoi(optarg); - if(!kill_tincd) - { - fprintf(stderr, _("Invalid argument `%s'; SIGNAL must be a number or one of HUP, TERM, KILL, USR1, USR2, WINCH, INT or ALRM.\n"), optarg); - usage(1); - } - } - } - else - kill_tincd = SIGTERM; - break; - case 'n': /* net name given */ - netname = xmalloc(strlen(optarg)+1); - strcpy(netname, optarg); - break; - case 'K': /* generate public/private keypair */ - if(optarg) - { - generate_keys = atoi(optarg); - if(generate_keys < 512) - { - fprintf(stderr, _("Invalid argument `%s'; BITS must be a number equal to or greater than 512.\n"), - optarg); - usage(1); - } - generate_keys &= ~7; /* Round it to bytes */ - } - else - generate_keys = 1024; - break; - case '?': - usage(1); - default: - break; - } - } + int r; + int option_index = 0; + + while((r = getopt_long(argc, argv, "c:DLd::k::n:K::", long_options, &option_index)) != EOF) { + switch (r) { + case 0: /* long option */ + break; + + case 'c': /* config file */ + confbase = xmalloc(strlen(optarg) + 1); + strcpy(confbase, optarg); + break; + + case 'D': /* no detach */ + do_detach = 0; + break; + + case 'L': /* no detach */ + do_mlock = 1; + break; + + case 'd': /* inc debug level */ + if(optarg) + debug_lvl = atoi(optarg); + else + debug_lvl++; + break; + + case 'k': /* kill old tincds */ + if(optarg) { + if(!strcasecmp(optarg, "HUP")) + kill_tincd = SIGHUP; + else if(!strcasecmp(optarg, "TERM")) + kill_tincd = SIGTERM; + else if(!strcasecmp(optarg, "KILL")) + kill_tincd = SIGKILL; + else if(!strcasecmp(optarg, "USR1")) + kill_tincd = SIGUSR1; + else if(!strcasecmp(optarg, "USR2")) + kill_tincd = SIGUSR2; + else if(!strcasecmp(optarg, "WINCH")) + kill_tincd = SIGWINCH; + else if(!strcasecmp(optarg, "INT")) + kill_tincd = SIGINT; + else if(!strcasecmp(optarg, "ALRM")) + kill_tincd = SIGALRM; + else { + kill_tincd = atoi(optarg); + + if(!kill_tincd) { + fprintf(stderr, + _ + ("Invalid argument `%s'; SIGNAL must be a number or one of HUP, TERM, KILL, USR1, USR2, WINCH, INT or ALRM.\n"), + optarg); + usage(1); + } + } + } else + kill_tincd = SIGTERM; + break; + + case 'n': /* net name given */ + netname = xmalloc(strlen(optarg) + 1); + strcpy(netname, optarg); + break; + + case 'K': /* generate public/private keypair */ + if(optarg) { + generate_keys = atoi(optarg); + + if(generate_keys < 512) { + fprintf(stderr, + _ + ("Invalid argument `%s'; BITS must be a number equal to or greater than 512.\n"), + optarg); + usage(1); + } + + generate_keys &= ~7; /* Round it to bytes */ + } else + generate_keys = 1024; + break; + + case '?': + usage(1); + + default: + break; + } + } } /* This function prettyprints the key generation process */ void indicator(int a, int b, void *p) { - switch(a) - { - case 0: - fprintf(stderr, "."); - break; - case 1: - fprintf(stderr, "+"); - break; - case 2: - fprintf(stderr, "-"); - break; - case 3: - switch(b) - { - case 0: - fprintf(stderr, " p\n"); - break; - case 1: - fprintf(stderr, " q\n"); - break; - default: - fprintf(stderr, "?"); - } - break; - default: - fprintf(stderr, "?"); - } + switch (a) { + case 0: + fprintf(stderr, "."); + break; + + case 1: + fprintf(stderr, "+"); + break; + + case 2: + fprintf(stderr, "-"); + break; + + case 3: + switch (b) { + case 0: + fprintf(stderr, " p\n"); + break; + + case 1: + fprintf(stderr, " q\n"); + break; + + default: + fprintf(stderr, "?"); + } + break; + + default: + fprintf(stderr, "?"); + } } /* @@ -246,55 +257,53 @@ void indicator(int a, int b, void *p) */ int keygen(int bits) { - RSA *rsa_key; - FILE *f; - char *name = NULL; - char *filename; - - fprintf(stderr, _("Generating %d bits keys:\n"), bits); - rsa_key = RSA_generate_key(bits, 0xFFFF, indicator, NULL); - - if(!rsa_key) - { - fprintf(stderr, _("Error during key generation!\n")); - return -1; - } - else - fprintf(stderr, _("Done.\n")); - - get_config_string(lookup_config(config_tree, "Name"), &name); - - if(name) - asprintf(&filename, "%s/hosts/%s", confbase, name); - else - asprintf(&filename, "%s/rsa_key.pub", confbase); - - f = ask_and_safe_open(filename, _("public RSA key"), "a"); - - if(!f) - return -1; - - if(ftell(f)) - fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n")); - - PEM_write_RSAPublicKey(f, rsa_key); - fclose(f); - free(filename); - - asprintf(&filename, "%s/rsa_key.priv", confbase); - f = ask_and_safe_open(filename, _("private RSA key"), "a"); - - if(!f) - return -1; - - if(ftell(f)) - fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n")); - - PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL); - fclose(f); - free(filename); - - return 0; + RSA *rsa_key; + FILE *f; + char *name = NULL; + char *filename; + + fprintf(stderr, _("Generating %d bits keys:\n"), bits); + rsa_key = RSA_generate_key(bits, 0xFFFF, indicator, NULL); + + if(!rsa_key) { + fprintf(stderr, _("Error during key generation!\n")); + return -1; + } else + fprintf(stderr, _("Done.\n")); + + get_config_string(lookup_config(config_tree, "Name"), &name); + + if(name) + asprintf(&filename, "%s/hosts/%s", confbase, name); + else + asprintf(&filename, "%s/rsa_key.pub", confbase); + + f = ask_and_safe_open(filename, _("public RSA key"), "a"); + + if(!f) + return -1; + + if(ftell(f)) + fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n")); + + PEM_write_RSAPublicKey(f, rsa_key); + fclose(f); + free(filename); + + asprintf(&filename, "%s/rsa_key.priv", confbase); + f = ask_and_safe_open(filename, _("private RSA key"), "a"); + + if(!f) + return -1; + + if(ftell(f)) + fprintf(stderr, _("Appending key to existing contents.\nMake sure only one key is stored in the file.\n")); + + PEM_write_RSAPrivateKey(f, rsa_key, NULL, NULL, 0, NULL, NULL); + fclose(f); + free(filename); + + return 0; } /* @@ -302,126 +311,119 @@ int keygen(int bits) */ void make_names(void) { - if(netname) - { - if(!pidfilename) - asprintf(&pidfilename, LOCALSTATEDIR "/run/tinc.%s.pid", netname); - if(!confbase) - asprintf(&confbase, "%s/tinc/%s", CONFDIR, netname); - else - syslog(LOG_INFO, _("Both netname and configuration directory given, using the latter...")); - if(!identname) - asprintf(&identname, "tinc.%s", netname); - } - else - { - if(!pidfilename) - pidfilename = LOCALSTATEDIR "/run/tinc.pid"; - if(!confbase) - asprintf(&confbase, "%s/tinc", CONFDIR); - if(!identname) - identname = "tinc"; - } + if(netname) { + if(!pidfilename) + asprintf(&pidfilename, LOCALSTATEDIR "/run/tinc.%s.pid", netname); + + if(!confbase) + asprintf(&confbase, "%s/tinc/%s", CONFDIR, netname); + else + syslog(LOG_INFO, _("Both netname and configuration directory given, using the latter...")); + + if(!identname) + asprintf(&identname, "tinc.%s", netname); + } else { + if(!pidfilename) + pidfilename = LOCALSTATEDIR "/run/tinc.pid"; + + if(!confbase) + asprintf(&confbase, "%s/tinc", CONFDIR); + + if(!identname) + identname = "tinc"; + } } -int -main(int argc, char **argv, char **envp) +int main(int argc, char **argv, char **envp) { - program_name = argv[0]; + program_name = argv[0]; - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); - environment = envp; - parse_options(argc, argv, envp); + environment = envp; + parse_options(argc, argv, envp); - if(show_version) - { - printf(_("%s version %s (built %s %s, protocol %d)\n"), PACKAGE, VERSION, __DATE__, __TIME__, PROT_CURRENT); - printf(_("Copyright (C) 1998-2002 Ivo Timmermans, Guus Sliepen and others.\n" - "See the AUTHORS file for a complete list.\n\n" - "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" - "and you are welcome to redistribute it under certain conditions;\n" - "see the file COPYING for details.\n")); + if(show_version) { + printf(_("%s version %s (built %s %s, protocol %d)\n"), PACKAGE, + VERSION, __DATE__, __TIME__, PROT_CURRENT); + printf(_("Copyright (C) 1998-2002 Ivo Timmermans, Guus Sliepen and others.\n" + "See the AUTHORS file for a complete list.\n\n" + "tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n" + "and you are welcome to redistribute it under certain conditions;\n" + "see the file COPYING for details.\n")); - return 0; - } + return 0; + } - if(show_help) - usage(0); + if(show_help) + usage(0); #ifndef LOG_PERROR - openlog("tinc", LOG_CONS, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */ + openlog("tinc", LOG_CONS, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */ #else - openlog("tinc", LOG_PERROR, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */ + openlog("tinc", LOG_PERROR, LOG_DAEMON); /* Catch all syslog() calls issued before detaching */ #endif - /* Lock all pages into memory if requested */ - - if(do_mlock) + /* Lock all pages into memory if requested */ + + if(do_mlock) #ifdef HAVE_MLOCKALL - if(mlockall(MCL_CURRENT | MCL_FUTURE)) - { - syslog(LOG_ERR, _("System call `%s' failed: %s"), "mlockall", strerror(errno)); + if(mlockall(MCL_CURRENT | MCL_FUTURE)) { + syslog(LOG_ERR, _("System call `%s' failed: %s"), "mlockall", + strerror(errno)); #else - { - syslog(LOG_ERR, _("mlockall() not supported on this platform!")); + { + syslog(LOG_ERR, _("mlockall() not supported on this platform!")); #endif - return -1; - } - - g_argv = argv; + return -1; + } + + g_argv = argv; + + make_names(); + init_configuration(&config_tree); - make_names(); - init_configuration(&config_tree); + /* Slllluuuuuuurrrrp! */ - /* Slllluuuuuuurrrrp! */ - cp(); - RAND_load_file("/dev/urandom", 1024); + RAND_load_file("/dev/urandom", 1024); #ifdef HAVE_SSLEAY_ADD_ALL_ALGORITHMS - SSLeay_add_all_algorithms(); + SSLeay_add_all_algorithms(); #else - OpenSSL_add_all_algorithms(); + OpenSSL_add_all_algorithms(); #endif - cp(); - if(generate_keys) - { - read_server_config(); - exit(keygen(generate_keys)); - } - - if(kill_tincd) - exit(kill_other(kill_tincd)); - - if(read_server_config()) - exit(1); - cp(); - if(detach()) - exit(0); - cp(); - for(;;) - { - if(!setup_network_connections()) - { - main_loop(); - cleanup_and_exit(1); - } - - syslog(LOG_ERR, _("Unrecoverable error")); - cp_trace(); - - if(do_detach) - { - syslog(LOG_NOTICE, _("Restarting in %d seconds!"), maxtimeout); - sleep(maxtimeout); - } - else - { - syslog(LOG_ERR, _("Not restarting.")); - exit(1); - } - } + if(generate_keys) { + read_server_config(); + exit(keygen(generate_keys)); + } + + if(kill_tincd) + exit(kill_other(kill_tincd)); + + if(read_server_config()) + exit(1); + + if(detach()) + exit(0); + + for(;;) { + if(!setup_network_connections()) { + main_loop(); + cleanup_and_exit(1); + } + + syslog(LOG_ERR, _("Unrecoverable error")); + cp_trace(); + + if(do_detach) { + syslog(LOG_NOTICE, _("Restarting in %d seconds!"), maxtimeout); + sleep(maxtimeout); + } else { + syslog(LOG_ERR, _("Not restarting.")); + exit(1); + } + } } -- 2.25.1