Moving files, first attempt at gcrypt compatibility, more interface
abstraction
This commit is contained in:
		
							parent
							
								
									b0a676988a
								
							
						
					
					
						commit
						04d33be4bd
					
				
					 69 changed files with 10498 additions and 536 deletions
				
			
		
							
								
								
									
										14
									
								
								acconfig.h
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								acconfig.h
									
										
									
									
									
								
							|  | @ -75,3 +75,17 @@ | |||
| 
 | ||||
| /* Define to enable use of old SSLeay_add_all_algorithms() function */ | ||||
| #undef HAVE_SSLEAY_ADD_ALL_ALGORITHMS | ||||
| 
 | ||||
| /* Define to 1 if you want to include GCRYPT support */ | ||||
| #undef USE_GCRYPT | ||||
| 
 | ||||
| /* Define to 1 if you want to include OpenSSL support */ | ||||
| #undef USE_OPENSSL | ||||
| 
 | ||||
| #if defined(USE_GCRYPT) && defined(USE_OPENSSL) | ||||
| #  error You can only define one of USE_GCRYPT and USE_OPENSSL | ||||
| #endif | ||||
| 
 | ||||
| #if !defined(USE_GCRYPT) && !defined(USE_OPENSSL) | ||||
| #  error You must define exactly one of USE_GCRYPT and USE_OPENSSL | ||||
| #endif | ||||
|  |  | |||
							
								
								
									
										51
									
								
								configure.in
									
										
									
									
									
								
							
							
						
						
									
										51
									
								
								configure.in
									
										
									
									
									
								
							|  | @ -1,6 +1,6 @@ | |||
| dnl Process this file with autoconf to produce a configure script. | ||||
| 
 | ||||
| dnl $Id: configure.in,v 1.18 2002/04/11 20:17:33 zarq Exp $ | ||||
| dnl $Id: configure.in,v 1.19 2002/04/28 12:46:25 zarq Exp $ | ||||
| 
 | ||||
| AC_INIT(src/tincd.c) | ||||
| AM_INIT_AUTOMAKE(tinc, 1.0-cvs) | ||||
|  | @ -97,8 +97,53 @@ AC_CACHE_SAVE | |||
| 
 | ||||
| dnl These are defined in files in m4/ | ||||
| tinc_TUNTAP | ||||
| tinc_OPENSSL | ||||
| tinc_ZLIB | ||||
| 
 | ||||
| 	use_gcrypt=0 | ||||
| 	use_openssl=0 | ||||
| 
 | ||||
| 	AC_ARG_WITH(gcrypt, | ||||
| 	[  --with-gcrypt           Use GCRYPT for all cryptographic functions], | ||||
| 	[ | ||||
| 	  if test "x$withval" = "xyes" ; then | ||||
| 	    use_gcrypt=1 | ||||
| 	  else | ||||
| 	    use_gcrypt=0 | ||||
| 	  fi | ||||
| 	], | ||||
| 	[use_gcrypt=0]) | ||||
| 
 | ||||
| 	AC_ARG_WITH(openssl, | ||||
| 	[  --with-openssl          Use OpenSSL for all cryptographic functions], | ||||
| 	[ | ||||
| 	  if test "x$withval" = "xyes" ; then | ||||
| 	    use_openssl=1 | ||||
| 	  else | ||||
| 	    use_openssl=0 | ||||
| 	  fi | ||||
| 	], | ||||
| 	[use_openssl=0]) | ||||
| 
 | ||||
| 	if test \( $use_gcrypt -eq 0 -a $use_openssl -eq 0 \) \ | ||||
| 	     -o \( $use_gcrypt -eq 1 -a $use_openssl -eq 1 \) ; then | ||||
| 	  cat << EOM | ||||
| Error: You must select exactly one of GCRYPT or OpenSSL. | ||||
| EOM | ||||
| 	  echo use_openssl=$use_openssl, use_gcrypt=$use_gcrypt | ||||
| 	  exit 1 | ||||
| 	fi | ||||
| 
 | ||||
| 	if test $use_gcrypt -eq 1 ; then | ||||
| 	  AC_MSG_RESULT([Selecting GCRYPT for crypto]) | ||||
| 	  tinc_GCRYPT | ||||
| 	  AC_DEFINE(USE_GCRYPT) | ||||
| 	fi | ||||
| 	if test $use_openssl -eq 1 ; then | ||||
| 	  AC_MSG_RESULT([Selecting OpenSSL for crypto]) | ||||
| 	  tinc_OPENSSL | ||||
| 	  AC_DEFINE(USE_OPENSSL) | ||||
| 	fi | ||||
| 
 | ||||
| 	tinc_ZLIB | ||||
| 
 | ||||
| dnl Check if support for jumbograms is requested  | ||||
| AC_ARG_ENABLE(jumbograms, | ||||
|  |  | |||
|  | @ -1,15 +1,17 @@ | |||
| ## Process this file with automake to produce Makefile.in | ||||
| # $Id: Makefile.am,v 1.6 2002/04/13 11:23:19 zarq Exp $ | ||||
| # $Id: Makefile.am,v 1.7 2002/04/28 12:46:25 zarq Exp $ | ||||
| 
 | ||||
| noinst_LIBRARIES = libtinc.a | ||||
| 
 | ||||
| INCLUDES = @INCLUDES@ -I. -I$(top_builddir) -I$(top_srcdir)/intl | ||||
| 
 | ||||
| libtinc_a_SOURCES = xmalloc.c pidfile.c utils.c getopt.c getopt1.c list.c avl_tree.c dropin.c | ||||
| libtinc_a_SOURCES = xmalloc.c pidfile.c utils.c getopt.c getopt1.c	\ | ||||
| 	list.c avl_tree.c hooks.c dropin.c edge.c conf.c netutl.c logging.c connection.c subnet.c node.c | ||||
| 
 | ||||
| libtinc_a_LIBADD = @LIBOBJS@ @ALLOCA@ | ||||
| libtinc_a_DEPENDENCIES = $(libvpn_a_LIBADD) | ||||
| 
 | ||||
| noinst_HEADERS = xalloc.h pidfile.h utils.h getopt.h list.h avl_tree.h dropin.h | ||||
| noinst_HEADERS = xalloc.h pidfile.h utils.h getopt.h list.h avl_tree.h	\ | ||||
| 	hooks.h dropin.h edge.h net.h conf.h netutl.h logging.h connection.h subnet.h node.h | ||||
| 
 | ||||
| EXTRA_DIST = README | ||||
|  |  | |||
							
								
								
									
										269
									
								
								lib/conf.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										269
									
								
								lib/conf.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,269 @@ | |||
| /*
 | ||||
|     conf.c -- configuration storage & retrieval code | ||||
|     Copyright (C) 1998 Robert van der Meulen | ||||
|                   1998-2002 Ivo Timmermans <ivo@o2w.nl> | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 		  2000 Cris van Pelt <tribbel@arise.dhs.org> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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.1 2002/04/28 12:46:25 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <ctype.h> | ||||
| #include <errno.h> | ||||
| #include <netdb.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <sys/stat.h> | ||||
| #include <sys/types.h> | ||||
| #include <unistd.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include <xalloc.h> | ||||
| #include <utils.h> /* for cp */ | ||||
| #include <avl_tree.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| #include "netutl.h" /* for str2address */ | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| avl_tree_t *config_tree; | ||||
| 
 | ||||
| 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 result; | ||||
| 
 | ||||
|   result = strcasecmp(a->variable, b->variable); | ||||
| 
 | ||||
|   if(result) | ||||
|     return result; | ||||
| 
 | ||||
|   result = a->line - b->line; | ||||
| 
 | ||||
|   if(result) | ||||
|     return result; | ||||
|   else | ||||
|     return strcmp(a->file, b->file); | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
| 
 | ||||
| void exit_configuration(avl_tree_t **config_tree) | ||||
| { | ||||
| cp | ||||
|   avl_delete_tree(*config_tree); | ||||
|   *config_tree = NULL; | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| config_t *new_config(void) | ||||
| { | ||||
|   config_t *cfg; | ||||
| cp | ||||
|   cfg = (config_t *)xmalloc_and_zero(sizeof(*cfg)); | ||||
| 
 | ||||
|   return 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 | ||||
| } | ||||
| 
 | ||||
| void config_add(avl_tree_t *config_tree, config_t *cfg) | ||||
| { | ||||
| cp | ||||
|   avl_insert(config_tree, cfg); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| config_t *lookup_config(avl_tree_t *config_tree, char *variable) | ||||
| { | ||||
|   config_t cfg, *found; | ||||
| cp | ||||
|   cfg.variable = variable; | ||||
|   cfg.file = ""; | ||||
|   cfg.line = 0; | ||||
| 
 | ||||
|   found = avl_search_closest_greater(config_tree, &cfg); | ||||
| 
 | ||||
|   if(!found) | ||||
|     return NULL; | ||||
| 
 | ||||
|   if(strcasecmp(found->variable, variable)) | ||||
|     return NULL; | ||||
| 
 | ||||
|   return found; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| int get_config_int(config_t *cfg, int *result) | ||||
| { | ||||
| cp | ||||
|   if(!cfg) | ||||
|     return 0; | ||||
| 
 | ||||
|   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; | ||||
| } | ||||
| 
 | ||||
| int get_config_string(config_t *cfg, char **result) | ||||
| { | ||||
| cp | ||||
|   if(!cfg) | ||||
|     return 0; | ||||
| 
 | ||||
|   *result = xstrdup(cfg->value); | ||||
|   return 1; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| 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((char *)&subnet->net.ipv4.address, subnet->net.ipv4.prefixlength, sizeof(ipv4_t))) | ||||
|      || ((subnet->type == SUBNET_IPV6) && maskcheck((char *)&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; | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										65
									
								
								lib/conf.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								lib/conf.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,65 @@ | |||
| /*
 | ||||
|     conf.h -- header for conf.c | ||||
|     Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com> | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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.1 2002/04/28 12:46:25 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_CONF_H__ | ||||
| #define __TINC_CONF_H__ | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| #include <netdb.h> | ||||
| 
 | ||||
| #include <avl_tree.h> | ||||
| #include "net.h" | ||||
| #include "subnet.h" | ||||
| 
 | ||||
| typedef struct config_t { | ||||
|   char *variable; | ||||
|   char *value; | ||||
|   char *file; | ||||
|   int line; | ||||
| } config_t; | ||||
| 
 | ||||
| extern avl_tree_t *config_tree; | ||||
| 
 | ||||
| extern int pingtimeout; | ||||
| extern int maxtimeout; | ||||
| extern int bypass_security; | ||||
| extern char *confbase; | ||||
| extern char *netname; | ||||
| 
 | ||||
| extern void init_configuration(avl_tree_t **); | ||||
| extern void exit_configuration(avl_tree_t **); | ||||
| extern config_t *new_config(void); | ||||
| extern void free_config(config_t *); | ||||
| extern void config_add(avl_tree_t *, config_t *); | ||||
| extern config_t *lookup_config(avl_tree_t *, char *); | ||||
| extern config_t *lookup_config_next(avl_tree_t *, config_t *); | ||||
| extern int get_config_bool(config_t *, int *); | ||||
| 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. */ | ||||
| extern int get_config_subnet(config_t *, struct subnet_t **); | ||||
| 
 | ||||
| #endif /* __TINC_CONF_H__ */ | ||||
							
								
								
									
										126
									
								
								lib/connection.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								lib/connection.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,126 @@ | |||
| /*
 | ||||
|     connection.c -- connection list management | ||||
|     Copyright (C) 2000-2002 Guus Sliepen <guus@sliepen.warande.net>, | ||||
|                   2000-2002 Ivo Timmermans <itimmermans@bigfoot.com> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:25 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <sys/time.h> | ||||
| 
 | ||||
| #include <avl_tree.h> | ||||
| #include <list.h> | ||||
| 
 | ||||
| #include "net.h"	/* Don't ask. */ | ||||
| #include "netutl.h" | ||||
| #include "config.h" | ||||
| #include "conf.h" | ||||
| #include <utils.h> | ||||
| #include "subnet.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "xalloc.h" | ||||
| #include "system.h" | ||||
| 
 | ||||
| avl_tree_t *connection_tree;	/* Meta connections */ | ||||
| 
 | ||||
| int connection_compare(connection_t *a, connection_t *b) | ||||
| { | ||||
|   return a - b; | ||||
| } | ||||
| 
 | ||||
| void init_connections(void) | ||||
| { | ||||
| cp | ||||
|   connection_tree = avl_alloc_tree((avl_compare_t)connection_compare, NULL); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| void exit_connections(void) | ||||
| { | ||||
| cp | ||||
|   avl_delete_tree(connection_tree); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| connection_t *new_connection(void) | ||||
| { | ||||
|   connection_t *c; | ||||
| cp | ||||
|   c = (connection_t *)xmalloc_and_zero(sizeof(connection_t)); | ||||
| 
 | ||||
|   if(!c) | ||||
|     return NULL; | ||||
| 
 | ||||
|   gettimeofday(&c->start, NULL); | ||||
| cp | ||||
|   return 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 | ||||
| } | ||||
| 
 | ||||
| void connection_add(connection_t *c) | ||||
| { | ||||
| cp | ||||
|   avl_insert(connection_tree, c); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| void connection_del(connection_t *c) | ||||
| { | ||||
| cp | ||||
|   avl_delete(connection_tree, c); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
							
								
								
									
										141
									
								
								lib/connection.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								lib/connection.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,141 @@ | |||
| /*
 | ||||
|     connection.h -- header for connection.c | ||||
|     Copyright (C) 2000-2002 Guus Sliepen <guus@sliepen.warande.net>, | ||||
|                   2000-2002 Ivo Timmermans <itimmermans@bigfoot.com> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:25 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_CONNECTION_H__ | ||||
| #define __TINC_CONNECTION_H__ | ||||
| 
 | ||||
| #include <sys/time.h> | ||||
| 
 | ||||
| #include <avl_tree.h> | ||||
| #include <list.h> | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
| # ifdef HAVE_OPENSSL_EVP_H | ||||
| #  include <openssl/evp.h> | ||||
| # else | ||||
| #  include <evp.h> | ||||
| # endif | ||||
| 
 | ||||
| # ifdef HAVE_OPENSSL_RSA_H | ||||
| #  include <openssl/rsa.h> | ||||
| # else | ||||
| #  include <rsa.h> | ||||
| # endif | ||||
| #endif /* USE_OPENSSL */ | ||||
| 
 | ||||
| #ifdef USE_GCRYPT | ||||
| # include <gcrypt.h> | ||||
| #endif | ||||
| 
 | ||||
| #include "net.h" | ||||
| #include "conf.h" | ||||
| 
 | ||||
| #include "node.h" | ||||
| #include "edge.h" | ||||
| 
 | ||||
| #define OPTION_INDIRECT		0x0001 | ||||
| #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; | ||||
| } 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 */ | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   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 */ | ||||
|   const EVP_MD *indigest; | ||||
|   const EVP_MD *outdigest; | ||||
| #endif | ||||
| 
 | ||||
| #ifdef USE_GCRYPT | ||||
|   GCRY_SEXP rsa_key; | ||||
|   GCRY_CIPHER_HD incipher; | ||||
|   GCRY_CIPHER_HD outcipher; | ||||
|   GCRY_CIPHER_HD inctx; | ||||
|   GCRY_CIPHER_HD outctx; | ||||
|   GCRY_MD_HD indigest; | ||||
|   GCRY_MD_HD outdigest; | ||||
|   /* FIXME */ | ||||
| #endif | ||||
|    | ||||
|   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 */ | ||||
|   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 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; | ||||
| 
 | ||||
| extern void init_connections(void); | ||||
| extern void exit_connections(void); | ||||
| extern connection_t *new_connection(void); | ||||
| extern void free_connection(connection_t *); | ||||
| extern void connection_add(connection_t *); | ||||
| extern void connection_del(connection_t *); | ||||
| extern void dump_connections(void); | ||||
| extern int read_connection_config(connection_t *); | ||||
| 
 | ||||
| #endif /* __TINC_CONNECTION_H__ */ | ||||
|  | @ -17,12 +17,13 @@ | |||
|     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.2 2002/04/09 15:26:00 zarq Exp $ | ||||
|     $Id: edge.c,v 1.1 2002/04/28 12:46:25 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <syslog.h> | ||||
| #include <string.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.2 2002/04/09 15:26:00 zarq Exp $ | ||||
|     $Id: edge.h,v 1.1 2002/04/28 12:46:25 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_EDGE_H__ | ||||
|  | @ -31,7 +31,7 @@ | |||
| 
 | ||||
| typedef struct halfconnection_t { | ||||
|   struct node_t *node;             /* node associated with this end of the connection */ | ||||
| //  sockaddr_t tcpaddress;           /* real (internet) ip on this end of the meta connection */
 | ||||
| /*  sockaddr_t tcpaddress; */          /* real (internet) ip on this end of the meta connection */ | ||||
|   sockaddr_t udpaddress;           /* real (internet) ip on this end of the vpn connection */ | ||||
| } halfconnection_t; | ||||
| 
 | ||||
|  | @ -43,6 +43,8 @@ typedef struct edge_t { | |||
|   int weight;                      /* weight of this edge */ | ||||
|    | ||||
|   struct connection_t *connection; /* connection associated with this edge, if available */ | ||||
| 
 | ||||
|   void *if_data;                   /* Interface data */ | ||||
| } edge_t; | ||||
| 
 | ||||
| extern avl_tree_t *edge_tree;    /* Tree with all known edges (replaces active_tree) */ | ||||
|  | @ -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: logging.c,v 1.5 2002/04/13 18:01:58 zarq Exp $ | ||||
|     $Id: logging.c,v 1.1 2002/04/28 12:46:25 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.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: logging.h,v 1.7 2002/04/13 11:00:41 zarq Exp $ | ||||
|     $Id: logging.h,v 1.1 2002/04/28 12:46:25 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_LOGGING_H__ | ||||
|  | @ -67,6 +67,8 @@ extern void tinc_syslog(int, char *, ...); | |||
| #define LOG_NOTICE      5       /* normal but significant condition */ | ||||
| #define LOG_INFO        6       /* informational */ | ||||
| #define LOG_DEBUG       7       /* debug-level messages */ | ||||
| #else | ||||
| # warning dont include syslog! | ||||
| #endif | ||||
| 
 | ||||
| #endif /* __TINC_LOGGING_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.11 2002/04/09 15:26:00 zarq Exp $ | ||||
|     $Id: net.h,v 1.1 2002/04/28 12:46:25 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_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: netutl.c,v 1.15 2002/04/13 11:07:12 zarq Exp $ | ||||
|     $Id: netutl.c,v 1.1 2002/04/28 12:46:25 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.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.4 2002/04/09 15:26:00 zarq Exp $ | ||||
|     $Id: netutl.h,v 1.1 2002/04/28 12:46:25 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_NETUTL_H__ | ||||
							
								
								
									
										188
									
								
								lib/node.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								lib/node.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,188 @@ | |||
| /*
 | ||||
|     node.c -- node tree management | ||||
|     Copyright (C) 2001-2002 Guus Sliepen <guus@sliepen.warande.net>, | ||||
|                   2001-2002 Ivo Timmermans <itimmermans@bigfoot.com> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:25 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include <avl_tree.h> | ||||
| #include "node.h" | ||||
| #include "netutl.h" | ||||
| #include "net.h" | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| #include <hooks.h> | ||||
| 
 | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #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 */ | ||||
| 
 | ||||
| node_t *myself; | ||||
| 
 | ||||
| int node_compare(node_t *a, node_t *b) | ||||
| { | ||||
|   return strcmp(a->name, b->name); | ||||
| } | ||||
| 
 | ||||
| int node_udp_compare(node_t *a, node_t *b) | ||||
| { | ||||
|   int result; | ||||
| cp | ||||
|   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 | ||||
| } | ||||
| 
 | ||||
| void exit_nodes(void) | ||||
| { | ||||
| cp | ||||
|   avl_delete_tree(node_tree); | ||||
|   avl_delete_tree(node_udp_tree); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
| 
 | ||||
| void node_add(node_t *n) | ||||
| { | ||||
| cp | ||||
|   avl_insert(node_tree, n); | ||||
|   avl_insert(node_udp_tree, n); | ||||
| 
 | ||||
|   run_hooks("node-add", n); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| 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->subnet_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); | ||||
| 
 | ||||
|   run_hooks("node-del", n); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| node_t *lookup_node(char *name) | ||||
| { | ||||
|   node_t n; | ||||
| cp | ||||
|   n.name = name; | ||||
|   return avl_search(node_tree, &n); | ||||
| } | ||||
| 
 | ||||
| node_t *lookup_node_udp(sockaddr_t *sa) | ||||
| { | ||||
|   node_t n; | ||||
| cp | ||||
|   n.address = *sa; | ||||
|   n.name = NULL; | ||||
| 
 | ||||
|   return avl_search(node_udp_tree, &n); | ||||
| } | ||||
| 
 | ||||
| void dump_nodes(void) | ||||
| { | ||||
|   avl_node_t *node; | ||||
|   node_t *n; | ||||
| cp | ||||
|   log(0, TLOG_DEBUG, | ||||
|       _("Nodes:")); | ||||
| 
 | ||||
|   for(node = node_tree->head; node; node = node->next) | ||||
|     { | ||||
|       n = (node_t *)node->data; | ||||
| #ifdef USE_OPENSSL | ||||
|       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:"-"); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|       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?-1:0, n->digest?-1:0, n->maclength, n->compression, n->options, | ||||
|              n->status, n->nexthop?n->nexthop->name:"-", n->via?n->via->name:"-"); | ||||
| #endif | ||||
|     } | ||||
|      | ||||
|   syslog(LOG_DEBUG, _("End of nodes.")); | ||||
| cp | ||||
| } | ||||
|  | @ -17,12 +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.2 2002/04/09 15:26:00 zarq Exp $ | ||||
|     $Id: node.h,v 1.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_NODE_H__ | ||||
| #define __TINC_NODE_H__ | ||||
| 
 | ||||
| #include <gcrypt.h> | ||||
| 
 | ||||
| #include <avl_tree.h> | ||||
| 
 | ||||
| #include "subnet.h" | ||||
|  | @ -47,11 +49,23 @@ typedef struct node_t { | |||
| 
 | ||||
|   struct node_status_t status; | ||||
| 
 | ||||
|   const EVP_CIPHER *cipher;        /* Cipher type for UDP packets */  | ||||
| #ifdef USE_OPENSSL | ||||
|   const EVP_CIPHER *cipher;        /* Cipher type for UDP packets */ | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|   GCRY_CIPHER_HD cipher;           /* Cipher type for UDP packets */ | ||||
| #endif | ||||
|    | ||||
|   char *key;                       /* Cipher key and iv */ | ||||
|   int keylength;                   /* Cipher key and iv length*/ | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   const EVP_MD *digest;            /* Digest type for MAC */ | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|   GCRY_MD_HD digest;               /* Digest type for MAC */ | ||||
| #endif | ||||
|    | ||||
|   int maclength;                   /* Length of MAC */ | ||||
| 
 | ||||
|   int compression;                 /* Compressionlevel, 0 = no compression */ | ||||
|  | @ -69,6 +83,8 @@ typedef struct node_t { | |||
| 
 | ||||
|   unsigned int sent_seqno;         /* Sequence number last sent to this node */ | ||||
|   unsigned int received_seqno;     /* Sequence number last received from this node */ | ||||
| 
 | ||||
|   void *data;                      /* Interface details */ | ||||
| } node_t; | ||||
| 
 | ||||
| extern struct node_t *myself; | ||||
|  | @ -17,19 +17,19 @@ | |||
|     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.2 2002/04/09 15:26:01 zarq Exp $ | ||||
|     $Id: subnet.c,v 1.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include <syslog.h> | ||||
| #include <string.h> | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <netdb.h> | ||||
| #include <netinet/in.h> | ||||
| 
 | ||||
| #include <hooks.h> | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| #include <avl_tree.h> | ||||
|  | @ -39,6 +39,7 @@ | |||
| #include "node.h" | ||||
| #include "subnet.h" | ||||
| #include "netutl.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
|  | @ -158,6 +159,8 @@ cp | |||
|   avl_insert(subnet_tree, subnet); | ||||
| cp | ||||
|   avl_insert(n->subnet_tree, subnet); | ||||
| 
 | ||||
|   run_hooks("subnet-add", subnet); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
|  | @ -167,6 +170,8 @@ cp | |||
|   avl_delete(n->subnet_tree, subnet); | ||||
| cp | ||||
|   avl_delete(subnet_tree, subnet); | ||||
| 
 | ||||
|   run_hooks("subnet-del", subnet); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
|  | @ -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.2 2002/04/09 15:26:01 zarq Exp $ | ||||
|     $Id: subnet.h,v 1.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_SUBNET_H__ | ||||
|  | @ -67,6 +67,8 @@ typedef struct subnet_t { | |||
|       subnet_ipv4_t ipv4; | ||||
|       subnet_ipv6_t ipv6; | ||||
|     } net; | ||||
| 
 | ||||
|   void *data;                           /* Interface details */ | ||||
| } subnet_t; | ||||
| 
 | ||||
| extern subnet_t *new_subnet(void); | ||||
|  | @ -46,4 +46,6 @@ AC_DEFUN(tinc_OPENSSL, | |||
|       [AC_MSG_ERROR("OpenSSL depends on libdl.")] | ||||
|     ) | ||||
|   ) | ||||
| 
 | ||||
|   found_openssl=1 | ||||
| ]) | ||||
|  |  | |||
|  | @ -31,3 +31,4 @@ src/freebsd/device.c | |||
| src/solaris/device.c | ||||
| src/netbsd/device.c | ||||
| src/openbsd/device.c | ||||
| src/pokey/pokey.translatables | ||||
|  |  | |||
							
								
								
									
										320
									
								
								po/nl.po
									
										
									
									
									
								
							
							
						
						
									
										320
									
								
								po/nl.po
									
										
									
									
									
								
							|  | @ -5,7 +5,7 @@ | |||
| msgid "" | ||||
| msgstr "" | ||||
| "Project-Id-Version: tinc 1.0-cvs\n" | ||||
| "POT-Creation-Date: 2002-04-09 13:41+0200\n" | ||||
| "POT-Creation-Date: 2002-04-14 21:41+0200\n" | ||||
| "PO-Revision-Date: 2002-03-27 16:59+0100\n" | ||||
| "Last-Translator: Guus Sliepen <guus@sliepen.warande.net>\n" | ||||
| "Language-Team: Dutch <vertaling@nl.linux.org>\n" | ||||
|  | @ -13,35 +13,35 @@ msgstr "" | |||
| "Content-Type: text/plain; charset=iso-8859-1\n" | ||||
| "Content-Transfer-Encoding: 8bit\n" | ||||
| 
 | ||||
| #: src/conf.c:173 | ||||
| #: src/conf.c:171 | ||||
| #, c-format | ||||
| msgid "\"yes\" or \"no\" expected for configuration variable %s in %s line %d" | ||||
| msgstr "" | ||||
| "\"ja\" of \"nee\" verwacht voor configuratievariabele %s in %s regel %d" | ||||
| 
 | ||||
| #: src/conf.c:188 | ||||
| #: src/conf.c:186 | ||||
| #, c-format | ||||
| msgid "Integer expected for configuration variable %s in %s line %d" | ||||
| msgstr "Geheel getal verwacht voor configuratievariabele %s in %s regel %d" | ||||
| 
 | ||||
| #: src/conf.c:218 | ||||
| #: src/conf.c:216 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Hostname or IP address expected for configuration variable %s in %s line %d" | ||||
| msgstr "" | ||||
| "Hostnaam of IP adres verwacht voor configuratievariabele %s in %s regel %d" | ||||
| 
 | ||||
| #: src/conf.c:235 | ||||
| #: src/conf.c:233 | ||||
| #, c-format | ||||
| msgid "Port number expected for configuration variable %s in %s line %d" | ||||
| msgstr "Poortnummer verwacht voor configuratievariabele %s in %s regel %d" | ||||
| 
 | ||||
| #: src/conf.c:251 | ||||
| #: src/conf.c:249 | ||||
| #, c-format | ||||
| msgid "Subnet expected for configuration variable %s in %s line %d" | ||||
| msgstr "Subnet verwacht voor configuratievariabele %s in %s regel %d" | ||||
| 
 | ||||
| #: src/conf.c:261 | ||||
| #: src/conf.c:259 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Network address and prefix length do not match for configuration variable %s " | ||||
|  | @ -50,71 +50,71 @@ msgstr "" | |||
| "Netwerk adres en prefix lengte komen niet overeen bij configuratievariabele %" | ||||
| "s in %s regel %d" | ||||
| 
 | ||||
| #: src/conf.c:369 | ||||
| #: src/conf.c:367 | ||||
| #, c-format | ||||
| msgid "Cannot open config file %s: %s" | ||||
| msgstr "Kan configuratie bestand %s niet openen: %s" | ||||
| 
 | ||||
| #: src/conf.c:405 | ||||
| #: src/conf.c:403 | ||||
| #, c-format | ||||
| msgid "No value for variable `%s' on line %d while reading config file %s" | ||||
| msgstr "" | ||||
| "Geen waarde voor variabele `%s' op regel %d tijdens het lezen van " | ||||
| "configuratie bestand %s" | ||||
| 
 | ||||
| #: src/conf.c:438 | ||||
| #: src/conf.c:436 | ||||
| #, c-format | ||||
| msgid "Failed to read `%s': %s" | ||||
| msgstr "Lezen van `%s' mislukte: %s" | ||||
| 
 | ||||
| #: src/conf.c:465 | ||||
| #: src/conf.c:463 | ||||
| #, c-format | ||||
| msgid "`%s' is not an absolute path" | ||||
| msgstr "`%s' is geen absoluut pad" | ||||
| 
 | ||||
| #: src/conf.c:481 src/conf.c:513 | ||||
| #: src/conf.c:479 src/conf.c:511 | ||||
| #, c-format | ||||
| msgid "Couldn't stat `%s': %s" | ||||
| msgstr "Kon `%s' niet statten: %s" | ||||
| 
 | ||||
| #: src/conf.c:487 src/conf.c:522 | ||||
| #: src/conf.c:485 src/conf.c:520 | ||||
| #, c-format | ||||
| msgid "`%s' is owned by UID %d instead of %d" | ||||
| msgstr "`%s' is eigendom van UID %d in plaats van %d" | ||||
| 
 | ||||
| #: src/conf.c:494 src/conf.c:529 | ||||
| #: src/conf.c:492 src/conf.c:527 | ||||
| #, c-format | ||||
| msgid "Warning: `%s' is a symlink" | ||||
| msgstr "Waarschuwing: `%s' is een symbolische link" | ||||
| 
 | ||||
| #: src/conf.c:499 src/conf.c:534 | ||||
| #: src/conf.c:497 src/conf.c:532 | ||||
| #, c-format | ||||
| msgid "Unable to read symbolic link `%s': %s" | ||||
| msgstr "Kan symbolische link `%s' niet lezen: %s" | ||||
| 
 | ||||
| #. Accessible by others | ||||
| #: src/conf.c:545 | ||||
| #: src/conf.c:543 | ||||
| #, c-format | ||||
| msgid "`%s' has unsecure permissions" | ||||
| msgstr "`%s' heeft onveilige permissies" | ||||
| 
 | ||||
| #. Ask for a file and/or directory name. | ||||
| #: src/conf.c:570 | ||||
| #: src/conf.c:568 | ||||
| #, c-format | ||||
| msgid "Please enter a file to save %s to [%s]: " | ||||
| msgstr "Geef een bestand om de %s naar de schrijven [%s]: " | ||||
| 
 | ||||
| #: src/conf.c:576 | ||||
| #: src/conf.c:574 | ||||
| #, c-format | ||||
| msgid "Error while reading stdin: %s\n" | ||||
| msgstr "Fout tijdens lezen van standaardinvoer: %s\n" | ||||
| 
 | ||||
| #: src/conf.c:602 | ||||
| #: src/conf.c:600 | ||||
| #, c-format | ||||
| msgid "Error opening file `%s': %s\n" | ||||
| msgstr "Fout bij het openen van het bestand `%s': %s\n" | ||||
| 
 | ||||
| #: src/conf.c:612 | ||||
| #: src/conf.c:610 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "The file `%s' (or any of the leading directories) has unsafe permissions.\n" | ||||
|  | @ -260,8 +260,8 @@ msgstr "Instellen prioriteit uitgaand pakket op %d" | |||
| 
 | ||||
| #. SO_PRIORITY doesn't seem to work | ||||
| #: src/net_packet.c:290 src/net_setup.c:450 src/net_socket.c:98 | ||||
| #: src/net_socket.c:144 src/net_socket.c:171 src/process.c:273 | ||||
| #: src/process.c:310 | ||||
| #: src/net_socket.c:144 src/net_socket.c:171 src/process.c:278 | ||||
| #: src/process.c:315 | ||||
| #, c-format | ||||
| msgid "System call `%s' failed: %s" | ||||
| msgstr "Systeemaanroep `%s' mislukte: %s" | ||||
|  | @ -499,27 +499,27 @@ msgstr "Verbinding van %s" | |||
| msgid "Invalid name for outgoing connection in %s line %d" | ||||
| msgstr "Ongeldige naam voor uitgaande verbinding in %s regel %d" | ||||
| 
 | ||||
| #: src/netutl.c:65 src/netutl.c:88 | ||||
| #: src/netutl.c:66 src/netutl.c:89 | ||||
| #, c-format | ||||
| msgid "Error looking up %s port %s: %s\n" | ||||
| msgstr "Fout bij het opzoeken van %s poort %s: %s\n" | ||||
| 
 | ||||
| #: src/netutl.c:109 | ||||
| #: src/netutl.c:110 | ||||
| #, c-format | ||||
| msgid "Error while translating addresses: %s" | ||||
| msgstr "Fout tijdens vertalen adressen: %s" | ||||
| 
 | ||||
| #: src/netutl.c:134 | ||||
| #: src/netutl.c:135 | ||||
| #, c-format | ||||
| msgid "Error while looking up hostname: %s" | ||||
| msgstr "Fout bij het opzoeken van hostnaam: %s" | ||||
| 
 | ||||
| #: src/netutl.c:137 | ||||
| #: src/netutl.c:138 | ||||
| #, c-format | ||||
| msgid "%s port %s" | ||||
| msgstr "%s poort %s" | ||||
| 
 | ||||
| #: src/netutl.c:166 | ||||
| #: src/netutl.c:167 | ||||
| #, c-format | ||||
| msgid "sockaddrcmp() was called with unknown address family %d, exitting!" | ||||
| msgstr "" | ||||
|  | @ -909,127 +909,127 @@ msgstr "" | |||
| "en je bent welkom om het te distribueren onder bepaalde voorwaarden;\n" | ||||
| "zie het bestand COPYING voor details.\n" | ||||
| 
 | ||||
| #: src/tincd.c:386 | ||||
| #: src/tincd.c:382 | ||||
| msgid "Unrecoverable error" | ||||
| msgstr "Onherstelbare fout" | ||||
| 
 | ||||
| #: src/tincd.c:391 | ||||
| #: src/tincd.c:387 | ||||
| #, c-format | ||||
| msgid "Restarting in %d seconds!" | ||||
| msgstr "Herstart in %d seconden!" | ||||
| 
 | ||||
| #: src/process.c:373 src/tincd.c:396 | ||||
| #: src/process.c:378 src/tincd.c:392 | ||||
| msgid "Not restarting." | ||||
| msgstr "Geen herstart." | ||||
| 
 | ||||
| #: src/process.c:69 | ||||
| #: src/process.c:71 | ||||
| #, c-format | ||||
| msgid "Memory exhausted (couldn't allocate %d bytes), exitting." | ||||
| msgstr "Geheugen uitgeput (kon geen %d bytes reserveren), beëindigen." | ||||
| 
 | ||||
| #: src/process.c:100 | ||||
| #: src/process.c:103 | ||||
| msgid "Terminating" | ||||
| msgstr "Beëindigen" | ||||
| 
 | ||||
| #: src/process.c:116 | ||||
| #: src/process.c:119 | ||||
| #, c-format | ||||
| msgid "A tincd is already running for net `%s' with pid %d.\n" | ||||
| msgstr "Een tincd draait al voor net `%s' met pid %d.\n" | ||||
| 
 | ||||
| #: src/process.c:119 | ||||
| #: src/process.c:122 | ||||
| #, c-format | ||||
| msgid "A tincd is already running with pid %d.\n" | ||||
| msgstr "Een tincd draait al met pid %d.\n" | ||||
| 
 | ||||
| #: src/process.c:140 | ||||
| #: src/process.c:143 | ||||
| #, c-format | ||||
| msgid "No other tincd is running for net `%s'.\n" | ||||
| msgstr "Geen andere tincd draait voor net `%s'.\n" | ||||
| 
 | ||||
| #: src/process.c:142 | ||||
| #: src/process.c:145 | ||||
| msgid "No other tincd is running.\n" | ||||
| msgstr "Geen andere tincd draait.\n" | ||||
| 
 | ||||
| #: src/process.c:151 | ||||
| #: src/process.c:154 | ||||
| #, c-format | ||||
| msgid "The tincd for net `%s' is no longer running. " | ||||
| msgstr "De tincd voor net `%s' draait niet meer. " | ||||
| 
 | ||||
| #: src/process.c:153 | ||||
| #: src/process.c:156 | ||||
| msgid "The tincd is no longer running. " | ||||
| msgstr "De tincd draait niet meer. " | ||||
| 
 | ||||
| #: src/process.c:155 | ||||
| #: src/process.c:158 | ||||
| msgid "Removing stale lock file.\n" | ||||
| msgstr "Verwijdering oud vergrendelingsbestand.\n" | ||||
| 
 | ||||
| #: src/process.c:183 | ||||
| #: src/process.c:186 | ||||
| #, c-format | ||||
| msgid "Couldn't detach from terminal: %s" | ||||
| msgstr "Kon niet ontkoppelen van terminal: %s" | ||||
| 
 | ||||
| #: src/process.c:196 | ||||
| #: src/process.c:201 | ||||
| #, c-format | ||||
| msgid "tincd %s (%s %s) starting, debug level %d" | ||||
| msgstr "tincd %s (%s %s) start, debug niveau %d" | ||||
| 
 | ||||
| #: src/process.c:199 | ||||
| #: src/process.c:204 | ||||
| #, c-format | ||||
| msgid "tincd %s starting" | ||||
| msgstr "tincd %s wordt gestart" | ||||
| 
 | ||||
| #: src/process.c:280 | ||||
| #: src/process.c:285 | ||||
| #, c-format | ||||
| msgid "Executing script %s" | ||||
| msgstr "Uitvoeren script %s" | ||||
| 
 | ||||
| #: src/process.c:290 | ||||
| #: src/process.c:295 | ||||
| #, c-format | ||||
| msgid "Process %d (%s) exited with non-zero status %d" | ||||
| msgstr "Proces %d (%s) beëindigde met status %d" | ||||
| 
 | ||||
| #: src/process.c:298 | ||||
| #: src/process.c:303 | ||||
| #, c-format | ||||
| msgid "Process %d (%s) was killed by signal %d (%s)" | ||||
| msgstr "Proces %d (%s) was gestopt door signaal %d (%s)" | ||||
| 
 | ||||
| #: src/process.c:304 | ||||
| #: src/process.c:309 | ||||
| #, c-format | ||||
| msgid "Process %d (%s) terminated abnormally" | ||||
| msgstr "Proces %d (%s) abnormaal beëindigd" | ||||
| 
 | ||||
| #: src/process.c:329 | ||||
| #: src/process.c:334 | ||||
| msgid "Got TERM signal" | ||||
| msgstr "Kreeg TERM signaal" | ||||
| 
 | ||||
| #: src/process.c:338 | ||||
| #: src/process.c:343 | ||||
| msgid "Got QUIT signal" | ||||
| msgstr "Kreeg QUIT signaal" | ||||
| 
 | ||||
| #: src/process.c:345 | ||||
| #: src/process.c:350 | ||||
| #, c-format | ||||
| msgid "Got another fatal signal %d (%s): not restarting." | ||||
| msgstr "Kreeg nog een fataal signaal %s (%s): geen herstart." | ||||
| 
 | ||||
| #: src/process.c:354 | ||||
| #: src/process.c:359 | ||||
| #, c-format | ||||
| msgid "Got fatal signal %d (%s)" | ||||
| msgstr "Kreeg fataal signaal %d (%s)" | ||||
| 
 | ||||
| #: src/process.c:359 | ||||
| #: src/process.c:364 | ||||
| msgid "Trying to re-execute in 5 seconds..." | ||||
| msgstr "Poging tot herstarten over 5 seconden..." | ||||
| 
 | ||||
| #: src/process.c:382 | ||||
| #: src/process.c:387 | ||||
| msgid "Got HUP signal" | ||||
| msgstr "Kreeg HUP signaal" | ||||
| 
 | ||||
| #: src/process.c:391 | ||||
| #: src/process.c:396 | ||||
| #, c-format | ||||
| msgid "Reverting to old debug level (%d)" | ||||
| msgstr "Herstellen van oud debug niveau (%d)" | ||||
| 
 | ||||
| #: src/process.c:398 | ||||
| #: src/process.c:403 | ||||
| #, c-format | ||||
| msgid "" | ||||
| "Temporarily setting debug level to 5.  Kill me with SIGINT again to go back " | ||||
|  | @ -1038,21 +1038,21 @@ msgstr "" | |||
| "Tijdelijk instellen debug niveau op 5. Zend nog een SIGINT signaal om niveau " | ||||
| "%d te herstellen." | ||||
| 
 | ||||
| #: src/process.c:409 | ||||
| #: src/process.c:414 | ||||
| msgid "Got ALRM signal" | ||||
| msgstr "Kreeg ALRM signaal" | ||||
| 
 | ||||
| #: src/process.c:438 | ||||
| #: src/process.c:443 | ||||
| #, c-format | ||||
| msgid "Got unexpected signal %d (%s)" | ||||
| msgstr "Kreeg onverwacht signaal %d (%s)" | ||||
| 
 | ||||
| #: src/process.c:447 | ||||
| #: src/process.c:452 | ||||
| #, c-format | ||||
| msgid "Ignored signal %d (%s)" | ||||
| msgstr "Signaal %d (%s) genegeerd" | ||||
| 
 | ||||
| #: src/process.c:504 | ||||
| #: src/process.c:509 | ||||
| #, c-format | ||||
| msgid "Installing signal handler for signal %d (%s) failed: %s\n" | ||||
| msgstr "Installeren van signaal afhandelaar voor signaal %d (%s) faalde: %s\n" | ||||
|  | @ -1116,11 +1116,11 @@ msgstr "Kan pakket niet routeren: ARP verzoek voor onbekend adres %d.%d.%d.%d" | |||
| msgid "Cannot route packet: unknown type %hx" | ||||
| msgstr "Kan pakket niet routeren: onbekend type %hx" | ||||
| 
 | ||||
| #: src/node.c:161 | ||||
| #: src/node.c:160 | ||||
| msgid "Nodes:" | ||||
| msgstr "Nodes:" | ||||
| 
 | ||||
| #: src/node.c:166 | ||||
| #: src/node.c:165 | ||||
| #, c-format | ||||
| msgid "" | ||||
| " %s at %s cipher %d digest %d maclength %d compression %d options %lx status " | ||||
|  | @ -1129,7 +1129,7 @@ msgstr "" | |||
| " %s op %s cipher %d digest %d maclengte %d compressie %d opties %lx status %" | ||||
| "04x nexthop %s via %s" | ||||
| 
 | ||||
| #: src/node.c:171 | ||||
| #: src/node.c:170 | ||||
| msgid "End of nodes." | ||||
| msgstr "Einde van nodes." | ||||
| 
 | ||||
|  | @ -1284,5 +1284,203 @@ msgstr "Onbekende adresfamilie tijdens lezen pakket van %s %s" | |||
| msgid "Unknown address family %d while writing packet to %s %s" | ||||
| msgstr "Onbekende adresfamilie tijdens schrijven pakket naar %s %s" | ||||
| 
 | ||||
| #. | ||||
| #. * Vertaalbare teksten bestand gegenereerd door Glade. | ||||
| #. * Voeg dit bestand toe aan uw project's bestand POTFILES.in. | ||||
| #. * Compileer dit NIET als onderdeel van uw applicatie. | ||||
| #. | ||||
| #: src/pokey/pokey.translatables:7 | ||||
| msgid "window1" | ||||
| msgstr "" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:8 | ||||
| msgid "_Network" | ||||
| msgstr "_Netwerk" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:9 | ||||
| msgid "_New network" | ||||
| msgstr "_Nieuw netwerk" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:10 | ||||
| msgid "label1" | ||||
| msgstr "" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:11 | ||||
| msgid "Information about host" | ||||
| msgstr "Informatie over computer" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:12 src/pokey/pokey.translatables:30 | ||||
| msgid "Name" | ||||
| msgstr "Naam" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:13 src/pokey/pokey.translatables:31 | ||||
| msgid "Hostname" | ||||
| msgstr "Hostnaam" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:14 | ||||
| msgid "Port" | ||||
| msgstr "Poort" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:15 | ||||
| msgid "Version" | ||||
| msgstr "Versie" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:16 | ||||
| msgid "Status" | ||||
| msgstr "Status" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:17 | ||||
| msgid "Only TCP packets" | ||||
| msgstr "Alleen TCP pakketten" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:18 | ||||
| msgid "Send data indirectly" | ||||
| msgstr "Stuur data indirect" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:19 | ||||
| msgid "Active" | ||||
| msgstr "Actief" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:20 | ||||
| msgid "Valid key" | ||||
| msgstr "Geldige sleutel" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:21 | ||||
| msgid "Waiting for key" | ||||
| msgstr "Wachten op sleutel" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:22 | ||||
| msgid "Visited" | ||||
| msgstr "Bezocht" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:23 | ||||
| msgid "Reachable" | ||||
| msgstr "Bereikbaar" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:24 | ||||
| msgid "Indirect" | ||||
| msgstr "Indirect" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:25 | ||||
| msgid "Visible" | ||||
| msgstr "Zichtbaar" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:26 | ||||
| msgid "Force Key Regeneration" | ||||
| msgstr "Forceer Nieuwe Sleutel" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:27 | ||||
| msgid "Host Info" | ||||
| msgstr "Host Informatie" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:28 | ||||
| msgid "label5" | ||||
| msgstr "" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:29 | ||||
| msgid "Information about connection" | ||||
| msgstr "Informatie over verbinding" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:32 | ||||
| msgid "Protocol version" | ||||
| msgstr "Protocolversie" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:33 | ||||
| msgid "Active since" | ||||
| msgstr "Actief sinds" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:34 | ||||
| msgid "Options" | ||||
| msgstr "Opties" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:35 | ||||
| msgid "label13" | ||||
| msgstr "" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:36 | ||||
| msgid "Force Disconnect" | ||||
| msgstr "Forceer Ontkoppeling" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:37 | ||||
| msgid "Force Reconnect" | ||||
| msgstr "Forceer Opnieuw Verbinden" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:38 | ||||
| msgid "Force Connect" | ||||
| msgstr "Forceer Verbinding" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:39 | ||||
| msgid "Connections" | ||||
| msgstr "Verbindingen" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:40 | ||||
| msgid "label4" | ||||
| msgstr "" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:41 | ||||
| msgid "Clear" | ||||
| msgstr "Leegmaken" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:42 | ||||
| msgid "Follow" | ||||
| msgstr "Volgen" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:43 | ||||
| msgid "Keep drawing" | ||||
| msgstr "Blijf tekenen" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:44 | ||||
| msgid "Shuffle" | ||||
| msgstr "Willekeurig" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:45 | ||||
| msgid "Zoom" | ||||
| msgstr "Zoomen" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:46 | ||||
| #, c-format | ||||
| msgid "-50%" | ||||
| msgstr "-50%" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:47 | ||||
| #, c-format | ||||
| msgid "-25%" | ||||
| msgstr "-25%" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:48 | ||||
| #, c-format | ||||
| msgid "-10%" | ||||
| msgstr "-10%" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:49 | ||||
| msgid "Default" | ||||
| msgstr "Standaard" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:50 | ||||
| #, c-format | ||||
| msgid "+10%" | ||||
| msgstr "+10%" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:51 | ||||
| #, c-format | ||||
| msgid "+25%" | ||||
| msgstr "+25%" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:52 | ||||
| #, c-format | ||||
| msgid "+50%" | ||||
| msgstr "+50%" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:53 | ||||
| msgid "Copyright 1998-2002" | ||||
| msgstr "Copyright 1998-2002" | ||||
| 
 | ||||
| #: src/pokey/pokey.translatables:54 | ||||
| msgid "" | ||||
| "tinc comes with ABSOLUTELY NO WARRANTY.  This is free software, and you are " | ||||
| "welcome to distribute it under certain conditions; see the file COPYING for " | ||||
| "details." | ||||
| msgstr "tinc wordt gedistribueerd ZONDER ENIGE GARANTIE.  Dit is vrije programmatuur, en je bent welkom om het te distribueren onder bepaalde voorwaarden; zie het bestand COPYING voor details." | ||||
| 
 | ||||
| #~ msgid "Invalid public/private keypair!" | ||||
| #~ msgstr "Ongeldig publiek/privé sleutelpaar!" | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| ## Produce this file with automake to get Makefile.in | ||||
| # $Id: Makefile.am,v 1.9 2002/04/13 11:23:46 zarq Exp $ | ||||
| # $Id: Makefile.am,v 1.10 2002/04/28 12:46:26 zarq Exp $ | ||||
| 
 | ||||
| SUBDIRS = pokey | ||||
| 
 | ||||
|  | @ -7,19 +7,19 @@ sbin_PROGRAMS = tincd | |||
| 
 | ||||
| EXTRA_DIST = linux/device.c freebsd/device.c openbsd/device.c solaris/device.c | ||||
| 
 | ||||
| tincd_SOURCES = conf.c connection.c device.c edge.c event.c graph.c logging.c meta.c net.c net_packet.c net_setup.c	\ | ||||
| 	net_socket.c netutl.c node.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c	\ | ||||
| 	protocol_key.c protocol_subnet.c route.c subnet.c tincd.c | ||||
| tincd_SOURCES = read_conf.c device.c event.c graph.c meta.c net_packet.c net_setup.c	\ | ||||
| 	net_socket.c process.c protocol.c protocol_auth.c protocol_edge.c protocol_misc.c	\ | ||||
| 	protocol_key.c protocol_subnet.c route.c tincd.c net.c | ||||
| 
 | ||||
| INCLUDES = @INCLUDES@ -I$(top_builddir) -I$(top_srcdir)/lib -I$(top_srcdir)/intl | ||||
| 
 | ||||
| noinst_HEADERS = conf.h connection.h device.h edge.h event.h graph.h logging.h meta.h net.h netutl.h node.h process.h	\ | ||||
| 	protocol.h route.h subnet.h | ||||
| noinst_HEADERS = read_conf.h  device.h event.h graph.h  meta.h process.h	\ | ||||
| 	protocol.h route.h  | ||||
| 
 | ||||
| LIBS = @LIBS@ @INTLLIBS@ | ||||
| 
 | ||||
| tincd_LDADD = \ | ||||
| 	$(top_builddir)/lib/libtinc.a | ||||
| 	$(top_builddir)/lib/libtinc.a -lgcrypt | ||||
| 
 | ||||
| localedir = $(datadir)/locale | ||||
| 
 | ||||
|  |  | |||
|  | @ -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.3 2002/04/13 11:07:12 zarq Exp $ | ||||
|     $Id: graph.c,v 1.4 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| /* We need to generate two trees from the graph:
 | ||||
|  | @ -47,7 +47,7 @@ | |||
| #include "config.h" | ||||
| 
 | ||||
| #include <stdio.h> | ||||
| #include "config.h" | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #if defined(HAVE_FREEBSD) || defined(HAVE_OPENBSD) | ||||
|  #include <sys/param.h> | ||||
|  |  | |||
							
								
								
									
										12
									
								
								src/meta.c
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								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.3 2002/04/13 11:07:12 zarq Exp $ | ||||
|     $Id: meta.c,v 1.4 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
|  | @ -51,7 +51,12 @@ cp | |||
| 
 | ||||
|   if(c->status.encryptout) | ||||
|     { | ||||
| #ifdef USE_OPENSSL | ||||
|       EVP_EncryptUpdate(c->outctx, outbuf, &outlen, buffer, length); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|       outlen = gcry_cipher_encrypt(c->outctx, outbuf, sizeof(outbuf), buffer, length); | ||||
| #endif | ||||
|       bufp = outbuf; | ||||
|       length = outlen; | ||||
|     } | ||||
|  | @ -140,7 +145,12 @@ cp | |||
| 
 | ||||
|       if(c->status.decryptin && !decrypted) | ||||
|         { | ||||
| #ifdef USE_OPENSSL | ||||
|           EVP_DecryptUpdate(c->inctx, inbuf, &lenin, c->buffer + oldlen, lenin); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
| 	  lenin = gcry_cipher_decrypt(c->inctx, inbuf, sizeof(inbuf), c->buffer + oldlen, lenin); | ||||
| #endif | ||||
|           memcpy(c->buffer + oldlen, inbuf, lenin); | ||||
|           decrypted = 1; | ||||
|         } | ||||
|  |  | |||
|  | @ -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.38 2002/04/13 11:07:12 zarq Exp $ | ||||
|     $Id: net.c,v 1.39 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
|  | @ -396,7 +396,9 @@ cp | |||
|               if(debug_lvl >= DEBUG_STATUS) | ||||
|                 syslog(LOG_INFO, _("Regenerating symmetric key")); | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|               RAND_pseudo_bytes(myself->key, myself->keylength); | ||||
| #endif | ||||
|               send_key_changed(myself->connection, myself); | ||||
|               keyexpires = now + keylifetime; | ||||
|             } | ||||
|  |  | |||
|  | @ -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.3 2002/04/13 11:07:12 zarq Exp $ | ||||
|     $Id: net_packet.c,v 1.4 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
|  | @ -92,15 +92,29 @@ void receive_udppacket(node_t *n, vpn_packet_t *inpkt) | |||
|   vpn_packet_t *outpkt = pkt[0]; | ||||
|   int outlen, outpad; | ||||
|   long int complen = MTU + 12; | ||||
|    | ||||
| #ifdef USE_OPENSSL | ||||
|   EVP_CIPHER_CTX ctx; | ||||
|   char hmac[EVP_MAX_MD_SIZE]; | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|   char *hmac; | ||||
| #endif | ||||
|    | ||||
| cp | ||||
|   /* Check the message authentication code */ | ||||
| 
 | ||||
|   if(myself->digest && myself->maclength) | ||||
|     { | ||||
|       inpkt->len -= myself->maclength; | ||||
| #ifdef USE_OPENSSL | ||||
|       HMAC(myself->digest, myself->key, myself->keylength, (char *)&inpkt->seqno, inpkt->len, hmac, NULL); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|       hmac = xmalloc(gcry_md_get_algo_dlen(0));  /* myself->digest type */ | ||||
|       gcry_md_hash_buffer(0, hmac, (char *)&inpkt->seqno, inpkt->len); | ||||
|       /* FIXME */ | ||||
| #endif | ||||
|       if(memcmp(hmac, (char *)&inpkt->seqno + inpkt->len, myself->maclength)) | ||||
|         { | ||||
|           if(debug_lvl >= DEBUG_TRAFFIC) | ||||
|  | @ -115,9 +129,14 @@ cp | |||
|   { | ||||
|     outpkt = pkt[nextpkt++]; | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|     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); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|     /* FIXME */ | ||||
| #endif | ||||
| 
 | ||||
|     outpkt->len = outlen + outpad; | ||||
|     inpkt = outpkt; | ||||
|  | @ -190,11 +209,15 @@ void send_udppacket(node_t *n, vpn_packet_t *inpkt) | |||
|   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; | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   EVP_CIPHER_CTX ctx; | ||||
| #endif | ||||
|    | ||||
| cp | ||||
|   /* Make sure we have a valid key */ | ||||
| 
 | ||||
|  | @ -253,9 +276,18 @@ cp | |||
|   { | ||||
|     outpkt = pkt[nextpkt++]; | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|     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); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|     gcry_cipher_ctl(n->cipher, GCRYCTL_SET_IV, n->key + n->keylength, n->keylength); | ||||
|     gcry_cipher_ctl(n->cipher, GCRYCTL_SET_KEY, n->key, n->keylength); | ||||
|     outlen = inpkt->len; | ||||
|     gcry_cipher_encrypt(n->cipher, (char *)&outpkt->seqno, outlen, (char *)&inpkt->seqno, inpkt->len); | ||||
|     /* FIXME */ | ||||
| #endif | ||||
| 
 | ||||
|     outpkt->len = outlen + outpad; | ||||
|     inpkt = outpkt; | ||||
|  | @ -265,7 +297,18 @@ cp | |||
| 
 | ||||
|   if(n->digest && n->maclength) | ||||
|     { | ||||
| #ifdef USE_OPENSSL | ||||
|       HMAC(n->digest, n->key, n->keylength, (char *)&inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len, &outlen); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|       char *hmac; | ||||
|       outlen = gcry_md_get_algo_dlen(0); | ||||
|       hmac = xmalloc(outlen);  /* myself->digest type */ | ||||
|       gcry_md_ctl(n->digest, GCRYCTL_SET_KEY, n->key, n->keylength); | ||||
|       gcry_md_hash_buffer(0, hmac, (char *)&inpkt->seqno, inpkt->len); | ||||
|       memcpy((char *)&inpkt->seqno, hmac, outlen); | ||||
|       /* FIXME */ | ||||
| #endif | ||||
|       inpkt->len += n->maclength; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										123
									
								
								src/net_setup.c
									
										
									
									
									
								
							
							
						
						
									
										123
									
								
								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.3 2002/04/13 11:07:12 zarq Exp $ | ||||
|     $Id: net_setup.c,v 1.4 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
|  | @ -44,9 +44,15 @@ | |||
| #include <sys/socket.h> | ||||
| #include <net/if.h> | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
| #include <openssl/pem.h> | ||||
| #include <openssl/rsa.h> | ||||
| #include <openssl/rand.h> | ||||
| #endif | ||||
| 
 | ||||
| #ifdef USE_GCRYPT | ||||
| #include <gcrypt.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
|  | @ -74,23 +80,39 @@ char *myport; | |||
| 
 | ||||
| int read_rsa_public_key(connection_t *c) | ||||
| { | ||||
|   char *key; | ||||
| #ifdef USE_OPENSSL | ||||
|   FILE *fp; | ||||
|   char *fname; | ||||
|   char *key; | ||||
| cp | ||||
|   if(!c->rsa_key) | ||||
|     c->rsa_key = RSA_new(); | ||||
| 
 | ||||
| #endif | ||||
| cp | ||||
|    | ||||
|   /* First, check for simple PublicKey statement */ | ||||
| 
 | ||||
|   if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &key)) | ||||
|     { | ||||
| #ifdef USE_OPENSSL | ||||
|       BN_hex2bn(&c->rsa_key->n, key); | ||||
|       BN_hex2bn(&c->rsa_key->e, "FFFF"); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|       int rc = gcry_sexp_build(&c->rsa_key, NULL, "(public-key(rsa(n%s)(e%s)))", | ||||
| 			       key, "FFFF"); | ||||
|       if(!rc) | ||||
| 	{ | ||||
| 	  syslog(LOG_ERR, _("gcry_sexp_build error: %d (%s)"), | ||||
| 		 rc, gcry_strerror(-1)); | ||||
| 	  return -1; | ||||
| 	} | ||||
| #endif | ||||
|       free(key); | ||||
|       return 0; | ||||
|     } | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   /* Else, check for PublicKeyFile statement and read it */ | ||||
| 
 | ||||
|   if(get_config_string(lookup_config(c->config_tree, "PublicKeyFile"), &fname)) | ||||
|  | @ -140,22 +162,44 @@ cp | |||
|       syslog(LOG_ERR, _("No public key for %s specified!"), c->name); | ||||
|       return -1; | ||||
|     } | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|   syslog(LOG_ERR, _("Only PublicKey statements are supported when using gcrypt for now.")); | ||||
|   return -1; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| int read_rsa_private_key(void) | ||||
| { | ||||
| #ifdef USE_OPENSSL | ||||
|   FILE *fp; | ||||
|   char *fname, *key; | ||||
|   char *fname; | ||||
| #endif | ||||
|   char *key; | ||||
| cp | ||||
|   if(get_config_string(lookup_config(config_tree, "PrivateKey"), &key)) | ||||
|     { | ||||
| #ifdef USE_OPENSSL | ||||
|       myself->connection->rsa_key = RSA_new(); | ||||
|       BN_hex2bn(&myself->connection->rsa_key->d, key); | ||||
|       BN_hex2bn(&myself->connection->rsa_key->e, "FFFF"); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|       int rc = gcry_sexp_build(&myself->connection->rsa_key, NULL, | ||||
| 			       "(public-key(rsa(n%s)(e%s)))", | ||||
| 			       key, "FFFF"); | ||||
|       if(!rc) | ||||
| 	{ | ||||
| 	  syslog(LOG_ERR, _("gcry_sexp_build error: %d (%s)"), | ||||
| 		 rc, gcry_strerror(-1)); | ||||
| 	  return -1; | ||||
| 	} | ||||
| #endif | ||||
|       free(key); | ||||
|       return 0; | ||||
|     } | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   if(!get_config_string(lookup_config(config_tree, "PrivateKeyFile"), &fname)) | ||||
|     asprintf(&fname, "%s/rsa_key.priv", confbase); | ||||
| 
 | ||||
|  | @ -182,6 +226,11 @@ cp | |||
| 
 | ||||
|   free(fname); | ||||
|   return -1; | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|   syslog(LOG_ERR, _("Only PrivateKey statements are supported when using gcrypt for now.")); | ||||
|   return -1; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  | @ -338,11 +387,23 @@ cp | |||
|     { | ||||
|       if(!strcasecmp(cipher, "none")) | ||||
|         { | ||||
| #ifdef USE_OPENSSL | ||||
|           myself->cipher = NULL; | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
| 	  myself->cipher = gcry_cipher_open(GCRY_CIPHER_NONE, GCRY_CIPHER_MODE_NONE, 0); | ||||
| #endif | ||||
|         } | ||||
|       else | ||||
|         { | ||||
| #ifdef USE_OPENSSL | ||||
|           if(!(myself->cipher = EVP_get_cipherbyname(cipher))) | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
| 	  /* FIXME */ | ||||
| 	  myself->cipher = gcry_cipher_open(GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC, 0); | ||||
| 	  if(0) | ||||
| #endif | ||||
|             { | ||||
|               syslog(LOG_ERR, _("Unrecognized cipher type!")); | ||||
|               return -1; | ||||
|  | @ -350,17 +411,42 @@ cp | |||
|         } | ||||
|     } | ||||
|   else | ||||
|     myself->cipher = EVP_bf_cbc(); | ||||
|     { | ||||
| #ifdef USE_OPENSSL | ||||
|       myself->cipher = EVP_bf_cbc(); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|       myself->cipher = gcry_cipher_open(GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_CBC, 0); | ||||
| #endif | ||||
|     } | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   if(myself->cipher) | ||||
|     myself->keylength = myself->cipher->key_len + myself->cipher->iv_len; | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|   if(myself->cipher) | ||||
|     myself->keylength = 16;  /* FIXME */ | ||||
| #endif | ||||
|   else | ||||
|     myself->keylength = 1; | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   myself->connection->outcipher = EVP_bf_ofb(); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|   /* FIXME: CHANGE this to something like aes - but openssl
 | ||||
|      compatibility mode for now */ | ||||
|   myself->connection->outcipher = gcry_cipher_open(GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_MODE_OFB, 0); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   myself->key = (char *)xmalloc(myself->keylength); | ||||
|   RAND_pseudo_bytes(myself->key, myself->keylength); | ||||
| #endif | ||||
| #ifdef USE_GCYRPT | ||||
|   myself->key = gcry_random_bytes(myself->keylength, GCRY_WEAK_RANDOM); | ||||
| #endif | ||||
| 
 | ||||
|   if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime)) | ||||
|     keylifetime = 3600; | ||||
|  | @ -373,11 +459,22 @@ cp | |||
|     { | ||||
|       if(!strcasecmp(digest, "none")) | ||||
|         { | ||||
| #ifdef USE_OPENSSL | ||||
|           myself->digest = NULL; | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
| 	  myself->digest = gcry_md_open(GCRY_MD_NONE, GCRY_MD_FLAG_HMAC); | ||||
| #endif | ||||
|         } | ||||
|       else | ||||
|         { | ||||
| #ifdef USE_OPENSSL | ||||
|           if(!(myself->digest = EVP_get_digestbyname(digest))) | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
| 	  /* FIXME */ | ||||
| 	  if(!(myself->digest = gcry_md_open(GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC))) | ||||
| #endif | ||||
|             { | ||||
|               syslog(LOG_ERR, _("Unrecognized digest type!")); | ||||
|               return -1; | ||||
|  | @ -385,14 +482,25 @@ cp | |||
|         } | ||||
|     } | ||||
|   else | ||||
| #ifdef USE_OPENSSL | ||||
|     myself->digest = EVP_sha1(); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|     myself->digest = gcry_md_open(GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   myself->connection->outdigest = EVP_sha1(); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|   myself->connection->outdigest = gcry_md_open(GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC); | ||||
| #endif | ||||
| 
 | ||||
|   if(get_config_int(lookup_config(myself->connection->config_tree, "MACLength"), &myself->maclength)) | ||||
|     { | ||||
|       if(myself->digest) | ||||
|         { | ||||
| #ifdef USE_OPENSSL | ||||
|           if(myself->maclength > myself->digest->md_size) | ||||
|             { | ||||
|               syslog(LOG_ERR, _("MAC length exceeds size of digest!")); | ||||
|  | @ -403,6 +511,11 @@ cp | |||
|               syslog(LOG_ERR, _("Bogus MAC length!")); | ||||
|               return -1; | ||||
|             } | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
| 	  /* FIXME */ | ||||
| 	  myself->maclength = 12; | ||||
| #endif | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|  |  | |||
|  | @ -1,18 +1,18 @@ | |||
| ## Produce this file with automake to get Makefile.in | ||||
| # $Id: Makefile.am,v 1.1 2002/04/13 11:24:25 zarq Exp $ | ||||
| # $Id: Makefile.am,v 1.2 2002/04/28 12:46:26 zarq Exp $ | ||||
| 
 | ||||
| sbin_PROGRAMS = pokey | ||||
| 
 | ||||
| pokey_SOURCES = conf.c connection.c edge.c event.c graph.c	\ | ||||
| 	interface.c meta.c net.c net_packet.c net_setup.c net_socket.c netutl.c	\ | ||||
| 	node.c process.c protocol.c protocol_auth.c protocol_edge.c	\ | ||||
| pokey_SOURCES = event.c graph.c	\ | ||||
| 	interface.c logging.c meta.c net.c net_packet.c net_setup.c net_socket.c netutl.c	\ | ||||
| 	 process.c protocol.c protocol_auth.c protocol_edge.c	\ | ||||
| 	protocol_misc.c protocol_key.c protocol_subnet.c route.c	\ | ||||
| 	subnet.c pokey.c | ||||
| 	 pokey.c | ||||
| 
 | ||||
| INCLUDES = @INCLUDES@ -I$(top_builddir) -I$(top_srcdir)/lib -I$(top_srcdir)/intl -I$(top_srcdir)/src -I/usr/include/gtk-1.2 -I/usr/include/glib-1.2 -I/usr/lib/glib/include -I/usr/include/libglade-1.0 -I/usr/include/gnome-1.0 -I/usr/include/gnome-xml -I/usr/include/libglade-1.0 -I/usr/include/gnome-1.0 -DNEED_GNOMESUPPORT_H -I/usr/lib/gnome-libs/include -I/usr/include/glib-1.2 -I/usr/lib/glib/include -I/usr/include/orbit-1.0 -I/usr/include/gtk-1.2 -I/usr/X11R6/include | ||||
| 
 | ||||
| noinst_HEADERS = conf.h connection.h device.h edge.h event.h graph.h meta.h net.h netutl.h node.h process.h	\ | ||||
| 	protocol.h route.h subnet.h | ||||
| noinst_HEADERS =  device.h event.h graph.h meta.h net.h netutl.h  process.h	\ | ||||
| 	protocol.h route.h  | ||||
| 
 | ||||
| LIBS = @LIBS@ @INTLLIBS@ | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										45
									
								
								src/pokey/array.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/pokey/array.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| #include "myalloc.h" | ||||
| #include "array.h" | ||||
| 
 | ||||
| void *array_add(array_t *array, void *element) | ||||
| { | ||||
|   if(!array) | ||||
|     return NULL; | ||||
| 
 | ||||
|   if(array->allocated == 0) | ||||
|     { | ||||
|       array->allocated = 4; | ||||
|       array->data = xcalloc(array->allocated, sizeof(void*)); | ||||
|       array->elements = 0; | ||||
|     } | ||||
| 
 | ||||
|   if(array->elements >= array->allocated - 1) | ||||
|     { | ||||
|       int newalloc; | ||||
| 
 | ||||
|       newalloc = array->allocated << 1; | ||||
|       array->data = xrealloc(array->data, newalloc * sizeof(void*)); | ||||
|       array->allocated = newalloc; | ||||
|     } | ||||
| 
 | ||||
|   array->data[array->elements] = element; | ||||
|   array->elements++; | ||||
|   return element; | ||||
| } | ||||
| 
 | ||||
| array_t *array_create(void) | ||||
| { | ||||
|   array_t *r; | ||||
| 
 | ||||
|   r = xcalloc(1, sizeof(*r)); | ||||
|   return r; | ||||
| } | ||||
| 
 | ||||
| void array_free(array_t *array) | ||||
| { | ||||
|   free(array->data); | ||||
|   free(array); | ||||
| } | ||||
							
								
								
									
										18
									
								
								src/pokey/array.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/pokey/array.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| #ifndef __ARRAY_H__ | ||||
| #define __ARRAY_H__ | ||||
| 
 | ||||
| typedef struct array_t { | ||||
|   void **data; | ||||
|   int allocated; | ||||
|   int elements; | ||||
| } array_t; | ||||
| 
 | ||||
| #define array_get_ptr(array)  ((array)->data) | ||||
| #define array_get_nelts(array)  ((array)->elements) | ||||
| #define array_get_element(array, index)  ((array)->data[(index)]) | ||||
| 
 | ||||
| void *array_add(array_t *array, void *element); | ||||
| array_t *array_create(void); | ||||
| void array_free(array_t *array); | ||||
| 
 | ||||
| #endif /* __ARRAY_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.9 2002/04/13 10:04:46 zarq Exp $ | ||||
|     $Id: conf.h,v 1.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_CONF_H__ | ||||
|  | @ -40,6 +40,7 @@ typedef struct config_t { | |||
| 
 | ||||
| extern avl_tree_t *config_tree; | ||||
| 
 | ||||
| extern int debug_lvl; | ||||
| extern int pingtimeout; | ||||
| extern int maxtimeout; | ||||
| extern int bypass_security; | ||||
|  | @ -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.2 2002/04/09 15:26:00 zarq Exp $ | ||||
|     $Id: connection.h,v 1.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_CONNECTION_H__ | ||||
|  | @ -99,7 +99,6 @@ typedef struct connection_t { | |||
| 
 | ||||
|   char buffer[MAXBUFSIZE];         /* metadata input buffer */ | ||||
|   int buflen;                      /* bytes read into buffer */ | ||||
|   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 */ | ||||
							
								
								
									
										36
									
								
								src/pokey/device.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/pokey/device.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| /*
 | ||||
|     net.h -- generic header for device.c | ||||
|     Copyright (C) 2001-2002 Ivo Timmermans <zarq@iname.com> | ||||
|                   2001-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_DEVICE_H__ | ||||
| #define __TINC_DEVICE_H__ | ||||
| 
 | ||||
| extern int device_fd; | ||||
| extern char *device; | ||||
| extern char *interface; | ||||
| 
 | ||||
| extern int setup_device(void); | ||||
| extern void close_device(void); | ||||
| extern int read_packet(vpn_packet_t *); | ||||
| extern int write_packet(vpn_packet_t *); | ||||
| extern void dump_device_stats(void); | ||||
| 
 | ||||
| #endif /* __TINC_DEVICE_H__ */ | ||||
							
								
								
									
										110
									
								
								src/pokey/event.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/pokey/event.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,110 @@ | |||
| /*
 | ||||
|     event.c -- event queue | ||||
|     Copyright (C) 2002 Guus Sliepen <guus@sliepen.warande.net>, | ||||
|                   2002 Ivo Timmermans <itimmermans@bigfoot.com> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <xalloc.h> | ||||
| #include <string.h> | ||||
| #include <utils.h> | ||||
| #include <avl_tree.h> | ||||
| #include <time.h> | ||||
| 
 | ||||
| #include "event.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| avl_tree_t *event_tree; | ||||
| extern time_t now; | ||||
| 
 | ||||
| int id; | ||||
| 
 | ||||
| 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;  | ||||
| } | ||||
| 
 | ||||
| void init_events(void) | ||||
| { | ||||
| cp | ||||
|   event_tree = avl_alloc_tree((avl_compare_t)event_compare, NULL); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| void exit_events(void) | ||||
| { | ||||
| cp | ||||
|   avl_delete_tree(event_tree); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| event_t *new_event(void) | ||||
| { | ||||
|   event_t *event; | ||||
| cp | ||||
|   event = (event_t *)xmalloc_and_zero(sizeof(*event)); | ||||
| cp | ||||
|   return event; | ||||
| } | ||||
| 
 | ||||
| void free_event(event_t *event) | ||||
| { | ||||
| cp | ||||
|   free(event); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| void event_add(event_t *event) | ||||
| { | ||||
| cp | ||||
|   event->id = ++id; | ||||
|   avl_insert(event_tree, event); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| void event_del(event_t *event) | ||||
| { | ||||
| cp | ||||
|   avl_delete(event_tree, event); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
							
								
								
									
										48
									
								
								src/pokey/event.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/pokey/event.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | |||
| /*
 | ||||
|     event.h -- header for event.c | ||||
|     Copyright (C) 2002 Guus Sliepen <guus@sliepen.warande.net>, | ||||
|                   2002 Ivo Timmermans <itimmermans@bigfoot.com> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_EVENT_H__ | ||||
| #define __TINC_EVENT_H__ | ||||
| 
 | ||||
| #include <time.h> | ||||
| #include <avl_tree.h> | ||||
| 
 | ||||
| avl_tree_t *event_tree; | ||||
| 
 | ||||
| typedef void (*event_handler_t)(void *); | ||||
| 
 | ||||
| typedef struct { | ||||
|   time_t time; | ||||
|   int id; | ||||
|   event_handler_t handler; | ||||
|   void *data; | ||||
| } event_t; | ||||
| 
 | ||||
| extern void init_events(void); | ||||
| extern void exit_events(void); | ||||
| extern event_t *new_event(void); | ||||
| extern void free_event(event_t *); | ||||
| extern void event_add(event_t *); | ||||
| extern void event_del(event_t *); | ||||
| extern event_t *get_expired_event(void); | ||||
| 
 | ||||
| #endif /* __TINC_EVENT_H__ */ | ||||
							
								
								
									
										283
									
								
								src/pokey/graph.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										283
									
								
								src/pokey/graph.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,283 @@ | |||
| /*
 | ||||
|     graph.c -- graph algorithms | ||||
|     Copyright (C) 2001-2002 Guus Sliepen <guus@sliepen.warande.net>, | ||||
|                   2001-2002 Ivo Timmermans <itimmermans@bigfoot.com> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| /* We need to generate two trees from the graph:
 | ||||
| 
 | ||||
|    1. A minimum spanning tree for broadcasts, | ||||
|    2. A single-source shortest path tree for unicasts. | ||||
| 
 | ||||
|    Actually, the first one alone would suffice but would make unicast packets | ||||
|    take longer routes than necessary. | ||||
| 
 | ||||
|    For the MST algorithm we can choose from Prim's or Kruskal's. I personally | ||||
|    favour Kruskal's, because we make an extra AVL tree of edges sorted on | ||||
|    weights (metric). That tree only has to be updated when an edge is added or | ||||
|    removed, and during the MST algorithm we just have go linearly through that | ||||
|    tree, adding safe edges until #edges = #nodes - 1. The implementation here | ||||
|    however is not so fast, because I tried to avoid having to make a forest and | ||||
|    merge trees. | ||||
| 
 | ||||
|    For the SSSP algorithm Dijkstra's seems to be a nice choice. Currently a | ||||
|    simple breadth-first search is presented here. | ||||
| 
 | ||||
|    The SSSP algorithm will also be used to determine whether nodes are directly, | ||||
|    indirectly or not reachable from the source. It will also set the correct | ||||
|    destination address and port of a node if possible. | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| #include <string.h> | ||||
| #if defined(HAVE_FREEBSD) || defined(HAVE_OPENBSD) | ||||
|  #include <sys/param.h> | ||||
| #endif | ||||
| #include <netinet/in.h> | ||||
| 
 | ||||
| #include <avl_tree.h> | ||||
| #include <hooks.h> | ||||
| #include <utils.h> | ||||
| 
 | ||||
| #include "interface.h" | ||||
| #include "netutl.h" | ||||
| #include "node.h" | ||||
| #include "edge.h" | ||||
| #include "connection.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| /* Implementation of Kruskal's algorithm.
 | ||||
|    Running time: O(EN) | ||||
|    Please note that sorting on weight is already done by add_edge(). | ||||
| */ | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
|   log(DEBUG_SCARY_THINGS, TLOG_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.node->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->from.node->status.visited == e->to.node->status.visited) | ||||
|         { | ||||
|           skipped = 1; | ||||
|           continue; | ||||
|         } | ||||
| 
 | ||||
|       e->from.node->status.visited = 1; | ||||
|       e->to.node->status.visited = 1; | ||||
|       if(e->connection) | ||||
|         e->connection->status.mst = 1; | ||||
| 
 | ||||
|       safe_edges++; | ||||
| 
 | ||||
|       if(debug_lvl >= DEBUG_SCARY_THINGS) | ||||
| 	syslog(LOG_DEBUG, " Adding edge %s - %s weight %d", e->from.node->name, e->to.node->name, e->weight); | ||||
| 
 | ||||
|       if(skipped) | ||||
|         { | ||||
|           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.
 | ||||
|    Running time: O(E) | ||||
| */ | ||||
| 
 | ||||
| void sssp_bfs(void) | ||||
| { | ||||
|   avl_node_t *node, *from, *next, *to; | ||||
|   edge_t *e; | ||||
|   node_t *n; | ||||
|   halfconnection_t to_hc, from_hc; | ||||
|   avl_tree_t *todo_tree; | ||||
|   int indirect; | ||||
| 
 | ||||
|   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->from.node == n)                              /* "from_hc" is the halfconnection with .node == from */ | ||||
|                 to_hc = e->to, from_hc = e->from; | ||||
|               else | ||||
|                 to_hc = e->from, from_hc = e->to; | ||||
| 
 | ||||
|               /* Situation:
 | ||||
| 
 | ||||
| 	        	  / | ||||
| 	        	 / | ||||
| 		 ------(n)from_hc-----to_hc | ||||
|                 	 \ | ||||
|                 	  \ | ||||
| 
 | ||||
|                  n->address is set to the to_hc.udpaddress of the edge left of n. | ||||
| 		 We are currently examining the edge right of n: | ||||
| 
 | ||||
|                  - If from_hc.udpaddress != n->address, then to_hc.node 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 to_hc.node, update | ||||
| 		   to_hc.node 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, &from_hc.udpaddress)); | ||||
| 
 | ||||
|               if(to_hc.node->status.visited && (!to_hc.node->status.indirect || indirect)) | ||||
| 	        continue; | ||||
| 
 | ||||
|               to_hc.node->status.visited = 1; | ||||
|               to_hc.node->status.indirect = indirect; | ||||
|               to_hc.node->nexthop = (n->nexthop == myself) ? to_hc.node : n->nexthop; | ||||
|               to_hc.node->via = indirect ? n->via : to_hc.node; | ||||
| 	      to_hc.node->options = e->options; | ||||
|               if(sockaddrcmp(&to_hc.node->address, &to_hc.udpaddress)) | ||||
| 	      { | ||||
|                 node = avl_unlink(node_udp_tree, to_hc.node); | ||||
|                 to_hc.node->address = to_hc.udpaddress; | ||||
| 		if(to_hc.node->hostname) | ||||
| 		  free(to_hc.node->hostname); | ||||
| 		to_hc.node->hostname = sockaddr2hostname(&to_hc.udpaddress); | ||||
|                 avl_insert_node(node_udp_tree, node); | ||||
| 	      } | ||||
|               node = avl_alloc_node(); | ||||
|               node->data = to_hc.node; | ||||
|               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) | ||||
|       { | ||||
|         if(!n->status.reachable) | ||||
| 	{ | ||||
|           if(debug_lvl >= DEBUG_TRAFFIC) | ||||
|             syslog(LOG_ERR, _("Node %s (%s) became reachable"), n->name, n->hostname); | ||||
|           n->status.reachable = 1; | ||||
| 	  run_hooks("node-visible", n); | ||||
| 	} | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|         if(n->status.reachable) | ||||
| 	{ | ||||
|           if(debug_lvl >= DEBUG_TRAFFIC) | ||||
|             syslog(LOG_DEBUG, _("Node %s (%s) became unreachable"), n->name, n->hostname); | ||||
|           n->status.reachable = 0; | ||||
| 	  n->status.validkey = 0; | ||||
| 	  n->status.waitingforkey = 0; | ||||
| 	  n->sent_seqno = 0; | ||||
|           run_hooks("node-invisible", n); | ||||
| 	} | ||||
|       } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void graph(void) | ||||
| { | ||||
|   mst_kruskal(); | ||||
|   sssp_bfs(); | ||||
| } | ||||
							
								
								
									
										30
									
								
								src/pokey/graph.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/pokey/graph.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| /*
 | ||||
|     graph.h -- header for graph.c | ||||
|     Copyright (C) 2001-2002 Guus Sliepen <guus@sliepen.warande.net>, | ||||
|                   2001-2002 Ivo Timmermans <itimmermans@bigfoot.com> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| 
 | ||||
|     $Id: graph.h,v 1.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_GRAPH_H__ | ||||
| #define __TINC_GRAPH_H__ | ||||
| 
 | ||||
| extern void graph(void); | ||||
| extern void mst_kruskal(void); | ||||
| extern void sssp_bfs(void); | ||||
| 
 | ||||
| #endif /* __TINC_GRAPH_H__ */ | ||||
|  | @ -1,9 +1,35 @@ | |||
| /*
 | ||||
|     interface.c -- GTK+/GNOME interface functions | ||||
|     Copyright (C) 2002 Guus Sliepen <guus@sliepen.warande.net>, | ||||
|                   2002 Ivo Timmermans <ivo@o2w.nl> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| 
 | ||||
|     $Id: interface.c,v 1.4 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <stdarg.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <sys/time.h> | ||||
| 
 | ||||
| #define log mathlog | ||||
| #include <math.h> | ||||
| #undef log | ||||
| 
 | ||||
| #include <gtk/gtk.h> | ||||
| #include <glade/glade.h> | ||||
|  | @ -14,10 +40,12 @@ | |||
| #include <libgnomeui/gnome-canvas-util.h> | ||||
| 
 | ||||
| #include "node.h" | ||||
| #include "connection.h" | ||||
| #include "edge.h" | ||||
| #include "interface.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include <hooks.h> | ||||
| #include <xalloc.h> | ||||
| 
 | ||||
| #include "system.h" | ||||
|  | @ -56,7 +84,7 @@ static int inited = 0; | |||
| static int number_of_nodes = 0; | ||||
| 
 | ||||
| static GtkWidget *nodetree; | ||||
| static GtkCTreeNode *subnets_ctn, *hosts_ctn, *conns_ctn; | ||||
| static GtkCTreeNode *hosts_ctn; | ||||
| 
 | ||||
| static GnomeCanvasGroup *edge_group = NULL; | ||||
| 
 | ||||
|  | @ -65,28 +93,34 @@ static int canvas_height; | |||
| 
 | ||||
| static GtkWidget *canvas = NULL; | ||||
| 
 | ||||
| static int log_inited = 0; | ||||
| static int follow_log = 1; | ||||
| 
 | ||||
| static int keep_drawing = 1; | ||||
| 
 | ||||
| static GtkCList *connlist = NULL; | ||||
| 
 | ||||
| static double canvas_zoom = 1.00; | ||||
| 
 | ||||
| void if_node_add(const char *hooktype, va_list ap); | ||||
| void if_node_del(const char *hooktype, va_list ap); | ||||
| void if_subnet_add(const char *hooktype, va_list ap); | ||||
| void if_subnet_del(const char *hooktype, va_list ap); | ||||
| void if_edge_add(const char *hooktype, va_list ap); | ||||
| void if_edge_del(const char *hooktype, va_list ap); | ||||
| void if_node_visible(const char *hooktype, va_list ap); | ||||
| void if_node_invisible(const char *hooktype, va_list ap); | ||||
| 
 | ||||
| GtkWidget *create_canvas(void) | ||||
| { | ||||
|   GtkWidget *w; | ||||
| 
 | ||||
|   gtk_widget_push_visual(gdk_rgb_get_visual()); | ||||
|   gtk_widget_push_colormap(gdk_rgb_get_cmap()); | ||||
|    | ||||
|   canvas = gnome_canvas_new_aa(); | ||||
|    | ||||
|   gtk_widget_pop_visual(); | ||||
|   gtk_widget_pop_colormap(); | ||||
|    | ||||
|   gnome_canvas_set_scroll_region(GNOME_CANVAS(canvas), -00.0, -00.0, 700, 500); | ||||
|    | ||||
|   w = glade_xml_get_widget(xml, "scrolledwindow3"); | ||||
|   if(!w) | ||||
|   canvas = glade_xml_get_widget(xml, "canvas1"); | ||||
|   if(!canvas) | ||||
|     { | ||||
|       fprintf(stderr, "Could not find widget `scrolledwindow3'\n"); | ||||
|       fprintf(stderr, "Could not find widget `canvas1'\n"); | ||||
|       return NULL; | ||||
|     } | ||||
|   gtk_container_add(GTK_CONTAINER(w), canvas); | ||||
|   gtk_widget_show_all(w); | ||||
|    | ||||
|   gnome_canvas_set_scroll_region(GNOME_CANVAS(canvas), -00.0, -00.0, 700, 500); | ||||
| 
 | ||||
|   canvas_width = 300.0; | ||||
|   canvas_height = 500.0; | ||||
|  | @ -103,7 +137,6 @@ void log_gtk(int level, int priority, char *fmt, va_list ap) | |||
|   char *p; | ||||
|   struct tm *tm; | ||||
|   time_t t; | ||||
|   static int inited = 0; | ||||
| 
 | ||||
|   if(!xml) | ||||
|     return; | ||||
|  | @ -141,56 +174,383 @@ void log_gtk(int level, int priority, char *fmt, va_list ap) | |||
|    | ||||
|   gtk_text_freeze(GTK_TEXT(w)); | ||||
| 
 | ||||
|   if(inited) | ||||
|   if(log_inited) | ||||
|     gtk_text_insert(GTK_TEXT(w), NULL, NULL, NULL, "\n", 1); | ||||
| 
 | ||||
|   gtk_text_insert(GTK_TEXT(w), NULL, &timecolor, NULL, buffer2, strlen(buffer2)); | ||||
|   gtk_text_insert(GTK_TEXT(w), NULL, NULL, NULL, buffer1, len); | ||||
|   gtk_text_thaw(GTK_TEXT(w)); | ||||
| 
 | ||||
|   inited = 1; | ||||
|   log_inited = 1; | ||||
|   if(follow_log) | ||||
| /*     gtk_text_set_point(GTK_TEXT(w), -1); */ | ||||
|     gtk_editable_set_position(GTK_EDITABLE(w), gtk_text_get_length(GTK_TEXT(w))); | ||||
| } | ||||
| 
 | ||||
| void if_hostinfoclosebutton_clicked(GtkWidget *w, gpointer data) | ||||
| { | ||||
|   gtk_widget_destroy(GTK_WIDGET(data)); | ||||
| } | ||||
| 
 | ||||
| void update_hostinfo_dialog(GladeXML *x, node_t *n) | ||||
| { | ||||
|   GtkWidget *w; | ||||
|   char s[100]; | ||||
|   avl_node_t *avlnode; | ||||
|   char *l[1]; | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoNameEntry"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoNameEntry"); return; } | ||||
|   gtk_entry_set_text(GTK_ENTRY(w), n->name); | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoHostnameEntry"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoHostnameEntry"); return; } | ||||
|   gtk_entry_set_text(GTK_ENTRY(w), n->hostname); | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoPortEntry"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoPortEntry"); return; } | ||||
| /*   snprintf(s, sizeof(s)-1, "%hd", "0"); */ | ||||
|   gtk_entry_set_text(GTK_ENTRY(w), "port"); | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoVersionEntry"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoVersionEntry"); return; } | ||||
|   gtk_entry_set_text(GTK_ENTRY(w), n->name); | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoStatusEntry"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoStatusEntry"); return; } | ||||
| /*   snprintf(s, sizeof(s)-1, "%x", n->status); */ | ||||
|   gtk_entry_set_text(GTK_ENTRY(w), "0"); | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoActiveCheckbutton"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoActiveCheckbutton"); return; } | ||||
|   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.active); | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoValidkeyCheckbutton"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoValidkeyCheckbutton"); return; } | ||||
|   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.validkey); | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoWaitingforkeyCheckbutton"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoWaitingforkeyCheckbutton"); return; } | ||||
|   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.waitingforkey); | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoVisitedCheckbutton"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoVisitedCheckbutton"); return; } | ||||
|   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.visited); | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoReachableCheckbutton"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoReachableCheckbutton"); return; } | ||||
|   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.reachable); | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoIndirectCheckbutton"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoIndirectCheckbutton"); return; } | ||||
|   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.indirect); | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoVisibleCheckbutton"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoVisibleCheckbutton"); return; } | ||||
| /*   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), n->status.visible); */ | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoTCPOnlyCheckbutton"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoTCPOnlyCheckbutton"); return; } | ||||
|   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), (n->options & OPTION_TCPONLY) != 0); | ||||
| 
 | ||||
|   w = glade_xml_get_widget(x, "HostInfoIndirectdataCheckbutton"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoIndirectdataCheckbutton"); return; } | ||||
|   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), (n->options & OPTION_INDIRECT) != 0); | ||||
| 
 | ||||
| /*   w = glade_xml_get_widget(x, "HostInfoWindow"); */ | ||||
| /*   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostInfoWindow"); return; } */ | ||||
| /*   glade_xml_signal_connect_data(x, "on_HostInfoCloseButton_clicked", if_hostinfoclosebutton_clicked, (gpointer)w); */ | ||||
|   w = glade_xml_get_widget(x, "HostConnectionsCList"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "HostConnectionsCList"); return; } | ||||
|   for(avlnode = n->edge_tree->head; avlnode; avlnode = avlnode->next) | ||||
|     { | ||||
|       if(((edge_t*)(avlnode->data))->to.node == n) | ||||
| 	l[0] = ((edge_t*)(avlnode->data))->from.node->name; | ||||
|       else | ||||
| 	l[0] = ((edge_t*)(avlnode->data))->to.node->name; | ||||
|       gtk_clist_append(GTK_CLIST(w), l); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void on_settings1_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   GtkWidget *w; | ||||
|   GladeXML *x; | ||||
|    | ||||
|   x = glade_xml_new(INTERFACE_FILE, "PropertyBox"); | ||||
|   if(x == NULL) | ||||
|     { | ||||
|       log(0, TLOG_ERROR, | ||||
| 	  _("Could not find widget `%s'"), | ||||
| 	  "PropertyBox"); | ||||
|       return; | ||||
|     } | ||||
|    | ||||
|   w = glade_xml_get_widget(x, "PropertyBox"); | ||||
|   if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "PropertyBox"); return; } | ||||
|   glade_xml_signal_autoconnect(x); | ||||
| } | ||||
| 
 | ||||
| void on_logcontext_clear_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   GtkWidget *l = glade_xml_get_widget(xml, "Messages"); | ||||
|   if(!l) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "Messages"); return; } | ||||
|   gtk_editable_delete_text(GTK_EDITABLE(l), 0, -1); /* Delete from 0 to end of buffer */ | ||||
|   log_inited = 0; | ||||
| } | ||||
| 
 | ||||
| void on_logcontext_follow_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   follow_log = !follow_log; | ||||
| } | ||||
| 
 | ||||
| void on_messages_button_press_event(GtkWidget *w, GdkEventButton *event, gpointer data) | ||||
| { | ||||
|   GladeXML *x; | ||||
|   GtkWidget *menu; | ||||
|    | ||||
|   if (event->button == 3) | ||||
|     { | ||||
|       x = glade_xml_new(INTERFACE_FILE, "LogContextMenu"); | ||||
|       if(x == NULL) | ||||
| 	{ | ||||
| 	  log(0, TLOG_ERROR, | ||||
| 	      _("Could not find widget `%s'"), | ||||
| 	      "LogContextMenu"); | ||||
| 	  return; | ||||
| 	} | ||||
| 
 | ||||
|       menu = glade_xml_get_widget(x, "LogContextMenu"); | ||||
|       if(!menu) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "LogContextMenu"); return; } | ||||
|        | ||||
|       glade_xml_signal_connect_data(x, "on_logcontext_clear_activate", on_logcontext_clear_activate, (gpointer)x); | ||||
|       glade_xml_signal_connect_data(x, "on_logcontext_follow_activate", on_logcontext_follow_activate, (gpointer)x); | ||||
|       w = glade_xml_get_widget(x, "LogContextFollow"); | ||||
|       if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "LogContextFollow"); return; } | ||||
|       GTK_CHECK_MENU_ITEM(w)->active = follow_log; | ||||
|       gnome_popup_menu_do_popup_modal(menu, NULL, NULL, event, NULL); | ||||
|       gtk_widget_destroy(menu); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void on_canvascontext_shuffle_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   avl_node_t *avlnode; | ||||
|   double newx, newy; | ||||
|    | ||||
|   for(avlnode = node_tree->head; avlnode; avlnode = avlnode->next) | ||||
|     { | ||||
|       newx = ((double)random()) / ((double)RAND_MAX) * 500.0; | ||||
|       newy = ((double)random()) / ((double)RAND_MAX) * 300.0; | ||||
|       ((struct if_node_data*)((node_t *)(avlnode->data))->data)->x = newx; | ||||
|       ((struct if_node_data*)((node_t *)(avlnode->data))->data)->y = newy; | ||||
| 
 | ||||
|       if(!((struct if_node_data*)((node_t*)(avlnode->data)))->visible) | ||||
| 	continue; | ||||
|        | ||||
|       x[((struct if_node_data*)((node_t*)(avlnode->data))->data)->id] = newx; | ||||
|       y[((struct if_node_data*)((node_t*)(avlnode->data))->data)->id] = newy; | ||||
|     } | ||||
|   inited = 0; | ||||
|   build_graph = 1; | ||||
| } | ||||
| 
 | ||||
| void on_canvascontext_keep_drawing_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   keep_drawing = !keep_drawing; | ||||
| } | ||||
| 
 | ||||
| void on_canvascontext_minus50_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   canvas_zoom *= 0.50; | ||||
|   gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), canvas_zoom); | ||||
| } | ||||
| 
 | ||||
| void on_canvascontext_minus25_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   canvas_zoom *= 0.75; | ||||
|   gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), canvas_zoom); | ||||
| } | ||||
| 
 | ||||
| void on_canvascontext_minus10_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   canvas_zoom *= 0.90; | ||||
|   gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), canvas_zoom); | ||||
| } | ||||
| 
 | ||||
| void on_canvascontext_default_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   canvas_zoom = 1.00; | ||||
|   gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), 1.00); | ||||
| } | ||||
| 
 | ||||
| void on_canvascontext_plus10_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   canvas_zoom *= 1.10; | ||||
|   gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), canvas_zoom); | ||||
| } | ||||
| 
 | ||||
| void on_canvascontext_plus25_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   canvas_zoom *= 1.25; | ||||
|   gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), canvas_zoom); | ||||
| } | ||||
| 
 | ||||
| void on_canvascontext_plus50_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   canvas_zoom *= 1.50; | ||||
|   gnome_canvas_set_pixels_per_unit(GNOME_CANVAS(canvas), canvas_zoom); | ||||
| } | ||||
| 
 | ||||
| void on_canvas_button_press_event(GtkWidget *w, GdkEventButton *event, gpointer data) | ||||
| { | ||||
|   GladeXML *x; | ||||
|   GtkWidget *menu; | ||||
|    | ||||
|   if (event->button == 3) | ||||
|     { | ||||
|       x = glade_xml_new(INTERFACE_FILE, "CanvasContextMenu"); | ||||
|       if(x == NULL) | ||||
| 	{ | ||||
| 	  log(0, TLOG_ERROR, | ||||
| 	      _("Could not find widget `%s'"), | ||||
| 	      "CanvasContextMenu"); | ||||
| 	  return; | ||||
| 	} | ||||
| 
 | ||||
|       menu = glade_xml_get_widget(x, "CanvasContextMenu"); | ||||
|       if(!menu) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "CanvasContextMenu"); return; } | ||||
|        | ||||
|       glade_xml_signal_autoconnect(x); | ||||
|       glade_xml_signal_connect_data(x, "on_canvascontext_shuffle_activate", on_canvascontext_shuffle_activate, (gpointer)x); | ||||
|       glade_xml_signal_connect_data(x, "on_canvascontext_keep_drawing_activate", on_canvascontext_keep_drawing_activate, (gpointer)x); | ||||
|       w = glade_xml_get_widget(x, "CanvasContextKeepDrawing"); | ||||
|       if(!w) { log(0, TLOG_ERROR, _("Couldn't find widget `%s'"), "CanvasContextKeepDrawing"); return; } | ||||
|       GTK_CHECK_MENU_ITEM(w)->active = keep_drawing; | ||||
|       gnome_popup_menu_do_popup_modal(menu, NULL, NULL, event, NULL); | ||||
|       gtk_widget_destroy(menu); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void on_nodetree_button_press_event(GtkWidget *w, GdkEventButton *event, gpointer data) | ||||
| { | ||||
|   GtkCTreeNode *node; | ||||
|   int row, col; | ||||
|   gpointer lt; | ||||
|   GladeXML *x; | ||||
|    | ||||
|   gtk_clist_get_selection_info(GTK_CLIST(w), event->x, event->y, | ||||
|                                &row, &col); | ||||
| 
 | ||||
|   node = gtk_ctree_node_nth(GTK_CTREE(w), row); | ||||
|   if(node == NULL) | ||||
|     return; | ||||
|   lt = gtk_ctree_node_get_row_data(GTK_CTREE(w), node); | ||||
|   if(event->type == GDK_2BUTTON_PRESS && event->button == 1) | ||||
|     { | ||||
|       /* Double left click on an item */ | ||||
|       if(lt == NULL) | ||||
|         /* this is only a branch, double click wil (un)expand. */ | ||||
|         return; | ||||
| 
 | ||||
|       if(GTK_CTREE_ROW(node)->parent == hosts_ctn) | ||||
| 	{ | ||||
| 	  x = ((struct if_node_data*)(((node_t*)lt)->data))->hi_xml = glade_xml_new(INTERFACE_FILE, "HostInfoWindow"); | ||||
| 	  if(x == NULL) | ||||
| 	    { | ||||
| 	      log(0, TLOG_ERROR, | ||||
| 		  _("Could not find widget `%s'"), | ||||
| 		  "HostInfoWindow"); | ||||
| 	      return; | ||||
| 	    } | ||||
| 	  glade_xml_signal_autoconnect(x); | ||||
| 	  update_hostinfo_dialog(x, (node_t*)lt); | ||||
| 	} | ||||
|       else | ||||
| 	{ | ||||
| 	  log(0, TLOG_ERROR, | ||||
| 	      "WHERE did you click?!"); | ||||
| 	} | ||||
|       /* so now we have access to all the data we want. */ | ||||
| /*       gldap_show_details(lt); */ | ||||
|       return; | ||||
|     } | ||||
| /*   else */ | ||||
| /*     if (event->button == 3) */ | ||||
| /*       { */ | ||||
| /*         GtkWidget *temp_menu; */ | ||||
| /*         temp_menu = gnome_popup_menu_new(data); */ | ||||
| /*         gnome_popup_menu_do_popup_modal(temp_menu, NULL, NULL, event, NULL); */ | ||||
| /*         gtk_widget_destroy(temp_menu); */ | ||||
| /*       } */ | ||||
| } | ||||
| 
 | ||||
| void on_exit1_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   close_network_connections(); | ||||
|   gtk_exit(0); | ||||
| } | ||||
| 
 | ||||
| void on_info1_activate(GtkMenuItem *mi, gpointer data) | ||||
| { | ||||
|   GladeXML *x; | ||||
|   x = glade_xml_new(INTERFACE_FILE, "AboutWindow"); | ||||
|   if(x == NULL) | ||||
|     { | ||||
|       log(0, TLOG_ERROR, | ||||
| 	  _("Could not find widget `%s'"), | ||||
| 	  "AboutWindow"); | ||||
|       return; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int init_interface(void) | ||||
| { | ||||
|   char *l[1]; | ||||
| 
 | ||||
|   glade_gnome_init(); | ||||
| 
 | ||||
|   xml = glade_xml_new("pokey.glade", "AppWindow"); | ||||
| 
 | ||||
|   if(!xml) | ||||
|     return -1; | ||||
|     { | ||||
|       log(0, TLOG_ERROR, | ||||
| 	  _("Something bad happened while creating the interface.\n")); | ||||
|       return -1; | ||||
|     } | ||||
| 
 | ||||
|   nodetree = glade_xml_get_widget(xml, "NodeTree"); | ||||
|   if(!nodetree) | ||||
|     { | ||||
|       fprintf(stderr, _("Could not find widget `NodeTree'\n")); | ||||
|       log(0, TLOG_ERROR, | ||||
| 	  _("Could not find widget `%s'"), | ||||
| 	  "NodeTree"); | ||||
|       return -1; | ||||
|     } | ||||
| 
 | ||||
|   gtk_clist_freeze(GTK_CLIST(nodetree)); | ||||
| 
 | ||||
|   l[0] = _("Hosts"); | ||||
|   hosts_ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree), | ||||
| 			      NULL, NULL, l, 1, | ||||
| 			      NULL, NULL, NULL, NULL, | ||||
| 			      FALSE, TRUE); | ||||
|   l[0] = _("Subnets"); | ||||
|   subnets_ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree), | ||||
| 			      NULL, NULL, l, 1, | ||||
| 			      NULL, NULL, NULL, NULL, | ||||
| 			      FALSE, TRUE); | ||||
|   l[0] = _("Connections"); | ||||
|   conns_ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree), | ||||
| 			      NULL, NULL, l, 1, | ||||
| 			      NULL, NULL, NULL, NULL, | ||||
| 			      FALSE, TRUE); | ||||
|    | ||||
|   gtk_clist_thaw(GTK_CLIST(nodetree)); | ||||
| 
 | ||||
|   create_canvas(); | ||||
| 
 | ||||
|   gtk_signal_connect(GTK_OBJECT(nodetree), "button_press_event", if_nodetree_button_press_event, NULL); | ||||
|   glade_xml_signal_autoconnect(xml); | ||||
| 
 | ||||
|   log_add_hook(log_gtk); | ||||
|   log_del_hook(log_default); | ||||
| 
 | ||||
|   add_hook("node-add", if_node_add); | ||||
|   add_hook("node-del", if_node_del); | ||||
|   add_hook("subnet-add", if_subnet_add); | ||||
|   add_hook("subnet-del", if_subnet_del); | ||||
|   add_hook("edge-add", if_edge_add); | ||||
|   add_hook("edge-del", if_edge_del); | ||||
|   add_hook("node-visible", if_node_visible); | ||||
|   add_hook("node-invisible", if_node_invisible); | ||||
|    | ||||
|   return 0; | ||||
| } | ||||
|  | @ -241,10 +601,10 @@ static gint item_event(GnomeCanvasItem *item, GdkEvent *event, gpointer data) | |||
|       gnome_canvas_item_ungrab(item, event->button.time); | ||||
|       dragging = FALSE; | ||||
|       n = (node_t *)gtk_object_get_user_data(GTK_OBJECT(item)); | ||||
|       n->x = item_x; | ||||
|       n->y = item_y; | ||||
|       x[n->id] = item_x; | ||||
|       y[n->id] = item_y; | ||||
|       ((struct if_node_data*)(n->data))->x = item_x; | ||||
|       ((struct if_node_data*)(n->data))->y = item_y; | ||||
|       x[((struct if_node_data*)(n->data))->id] = item_x; | ||||
|       y[((struct if_node_data*)(n->data))->id] = item_y; | ||||
|       build_graph = 1; | ||||
|       break; | ||||
| 
 | ||||
|  | @ -270,7 +630,7 @@ void if_node_create(node_t *n) | |||
| 			"y1", -08.0, | ||||
| 			"x2", 30.0, | ||||
| 			"y2", 08.0, | ||||
| 			"fill_color_rgba", 0x5f9ea0ff, | ||||
| 			"fill_color_rgba", 0x5f9ea080, | ||||
| 			"outline_color", "black", | ||||
| 			"width_pixels", 0, | ||||
| 			NULL); | ||||
|  | @ -285,47 +645,48 @@ void if_node_create(node_t *n) | |||
| 			"font", "-*-verdana-medium-r-*-*-10-*-*-*-*-*-iso8859-1", | ||||
| 			NULL); | ||||
|    | ||||
|   n->item = GNOME_CANVAS_ITEM(group); | ||||
|   n->x = n->y = 0.0; | ||||
|   ((struct if_node_data*)(n->data))->item = GNOME_CANVAS_ITEM(group); | ||||
|   ((struct if_node_data*)(n->data))->x = ((struct if_node_data*)(n->data))->y = 0.0; | ||||
|   gtk_object_set_user_data(GTK_OBJECT(group), (gpointer)n); | ||||
|    | ||||
|   gtk_signal_connect(GTK_OBJECT(n->item), "event", (GtkSignalFunc) item_event, NULL); | ||||
|   gtk_signal_connect(GTK_OBJECT(((struct if_node_data*)(n->data))->item), "event", (GtkSignalFunc) item_event, NULL); | ||||
| 
 | ||||
|   gnome_canvas_item_hide(GNOME_CANVAS_ITEM(n->item)); | ||||
|   gnome_canvas_item_hide(GNOME_CANVAS_ITEM(((struct if_node_data*)(n->data))->item)); | ||||
| } | ||||
| 
 | ||||
| void if_node_visible(node_t *n) | ||||
| void if_node_visible(const char *hooktype, va_list ap) | ||||
| { | ||||
|   int i; | ||||
|   avl_node_t *avlnode; | ||||
|   double newx, newy; | ||||
|   node_t *n = va_arg(ap, node_t*); | ||||
|    | ||||
|   if(!n->item) | ||||
|   if(!((struct if_node_data*)(n->data))->item) | ||||
|     return; | ||||
| 
 | ||||
|   if(n->status.visible) | ||||
|   if(((struct if_node_data*)(n->data))->visible) | ||||
|     /* This node is already shown */ | ||||
|     return; | ||||
| 
 | ||||
|   n->status.visible = 1; | ||||
|   ((struct if_node_data*)(n->data))->visible = 1; | ||||
| 
 | ||||
|   newx = 250.0 + 200.0 * sin(number_of_nodes / 10.0 * M_PI); | ||||
|   newy = 150.0 - 100.0 * cos(number_of_nodes / 10.0 * M_PI); | ||||
|   gnome_canvas_item_move(GNOME_CANVAS_ITEM(n->item), newx - n->x, newy - n->y); | ||||
|   n->x = newx; | ||||
|   n->y = newy; | ||||
|   gnome_canvas_item_move(GNOME_CANVAS_ITEM(((struct if_node_data*)(n->data))->item), newx - ((struct if_node_data*)(n->data))->x, newy - ((struct if_node_data*)(n->data))->y); | ||||
|   ((struct if_node_data*)(n->data))->x = newx; | ||||
|   ((struct if_node_data*)(n->data))->y = newy; | ||||
|    | ||||
|   for(i = 0, avlnode = node_tree->head; avlnode; avlnode = avlnode->next, i++) | ||||
|     { | ||||
|       if(!((node_t*)(avlnode->data))->status.visible) | ||||
|       if(!((struct if_node_data*)(((node_t*)(avlnode->data))->data))->visible) | ||||
| 	continue; | ||||
|        | ||||
|       nodes[i] = (node_t *)(avlnode->data); | ||||
|       nodes[i]->id = i; | ||||
|       ((struct if_node_data*)(nodes[i]->data))->id = i; | ||||
|     } | ||||
|   number_of_nodes = i; | ||||
| 
 | ||||
|   gnome_canvas_item_show(GNOME_CANVAS_ITEM(n->item)); | ||||
|   gnome_canvas_item_show(GNOME_CANVAS_ITEM(((struct if_node_data*)(n->data))->item)); | ||||
|   gnome_canvas_update_now(GNOME_CANVAS(canvas)); | ||||
| 
 | ||||
|   /* (Re)start calculations */ | ||||
|  | @ -333,31 +694,32 @@ void if_node_visible(node_t *n) | |||
|   build_graph = 1; | ||||
| } | ||||
| 
 | ||||
| void if_node_invisible(node_t *n) | ||||
| void if_node_invisible(const char *hooktype, va_list ap) | ||||
| { | ||||
|   int i; | ||||
|   avl_node_t *avlnode; | ||||
|   node_t *n = va_arg(ap, node_t*); | ||||
|    | ||||
|   if(!n->item) | ||||
|   if(!((struct if_node_data*)(n->data))->item) | ||||
|     return; | ||||
| 
 | ||||
|   if(!n->status.visible) | ||||
|   if(!((struct if_node_data*)(n->data))->visible) | ||||
|     /* This node is already invisible */ | ||||
|     return; | ||||
| 
 | ||||
|   n->status.visible = 0; | ||||
|   ((struct if_node_data*)(n->data))->visible = 0; | ||||
| 
 | ||||
|   for(i = 0, avlnode = node_tree->head; avlnode; avlnode = avlnode->next, i++) | ||||
|     { | ||||
|       if(!((node_t*)(avlnode->data))->status.visible) | ||||
|       if(!((struct if_node_data*)((node_t*)(avlnode->data))->data)->visible) | ||||
| 	continue; | ||||
|        | ||||
|       nodes[i] = (node_t *)(avlnode->data); | ||||
|       nodes[i]->id = i; | ||||
|       ((struct if_node_data*)(nodes[i]->data))->id = i; | ||||
|     } | ||||
|   number_of_nodes = i; | ||||
|    | ||||
|   gnome_canvas_item_hide(GNOME_CANVAS_ITEM(n->item)); | ||||
|   gnome_canvas_item_hide(GNOME_CANVAS_ITEM(((struct if_node_data*)(n->data))->item)); | ||||
|   gnome_canvas_update_now(GNOME_CANVAS(canvas)); | ||||
| 
 | ||||
|   /* (Re)start calculations */ | ||||
|  | @ -365,57 +727,89 @@ void if_node_invisible(node_t *n) | |||
|   build_graph = 1; | ||||
| } | ||||
| 
 | ||||
| GtkCTreeNode *if_node_add(node_t *n) | ||||
| void if_node_add(const char *hooktype, va_list ap) | ||||
| { | ||||
|   node_t *n = va_arg(ap, node_t*); | ||||
|   char *l[1]; | ||||
|   GtkCTreeNode *ctn; | ||||
|   struct if_node_data *nd; | ||||
| 
 | ||||
|   if(!xml) | ||||
|     return NULL; | ||||
|     return; | ||||
| 
 | ||||
|   nd = xmalloc(sizeof(*nd)); | ||||
|   l[0] = n->name; | ||||
|   gtk_clist_freeze(GTK_CLIST(nodetree)); | ||||
|   n->host_ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree), | ||||
| 				      hosts_ctn, NULL, l, 1, | ||||
| 				      NULL, NULL, NULL, NULL, | ||||
| 				      FALSE, FALSE); | ||||
|   nd->ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree), | ||||
| 				  hosts_ctn, NULL, l, 1, | ||||
| 				  NULL, NULL, NULL, NULL, | ||||
| 				  FALSE, FALSE); | ||||
|   gtk_clist_thaw(GTK_CLIST(nodetree)); | ||||
|   gtk_ctree_node_set_row_data(GTK_CTREE(nodetree), nd->ctn, n); | ||||
| 
 | ||||
|   n->data = (void*)nd; | ||||
| 
 | ||||
|   if_node_create(n); | ||||
|   if_node_visible(n); | ||||
| 
 | ||||
|   return ctn; | ||||
|   if_node_visible(hooktype, ap); | ||||
| } | ||||
| 
 | ||||
| void if_node_del(node_t *n) | ||||
| void if_node_del(const char *hooktype, va_list ap) | ||||
| { | ||||
|   gtk_clist_freeze(GTK_CLIST(nodetree)); | ||||
|   if(n->host_ctn) | ||||
|     gtk_ctree_remove_node(GTK_CTREE(nodetree), n->host_ctn); | ||||
|   if(n->conn_ctn) | ||||
|     gtk_ctree_remove_node(GTK_CTREE(nodetree), n->conn_ctn); | ||||
|   if(n->subnet_ctn) | ||||
|     gtk_ctree_remove_node(GTK_CTREE(nodetree), n->subnet_ctn); | ||||
|   gtk_clist_thaw(GTK_CLIST(nodetree)); | ||||
|   node_t *n = va_arg(ap, node_t*); | ||||
|   struct if_node_data *nd; | ||||
| 
 | ||||
|   if_node_invisible(n); | ||||
|   nd = (struct if_node_data*)(n->data); | ||||
|   if(nd &&nd->ctn) | ||||
|     { | ||||
|       gtk_clist_freeze(GTK_CLIST(nodetree)); | ||||
|       gtk_ctree_remove_node(GTK_CTREE(nodetree), nd->ctn); | ||||
|       gtk_clist_thaw(GTK_CLIST(nodetree)); | ||||
|     } | ||||
| 
 | ||||
|   if_node_invisible(hooktype, ap); | ||||
| 
 | ||||
|   free(nd); | ||||
|   n->data = NULL; | ||||
| } | ||||
| 
 | ||||
| void if_subnet_add(subnet_t *subnet) | ||||
| void if_subnet_add(const char *hooktype, va_list ap) | ||||
| { | ||||
|   char *l[1]; | ||||
|    | ||||
|   subnet_t *subnet = va_arg(ap, subnet_t*); | ||||
|   struct if_subnet_data *sd; | ||||
|   GtkCTreeNode *parent; | ||||
| 
 | ||||
|   sd = xmalloc(sizeof(*sd)); | ||||
|   l[0] = net2str(subnet); | ||||
|   parent = subnet->owner->data ? | ||||
|     ((struct if_subnet_data*)(subnet->owner->data))->ctn | ||||
|       : NULL; | ||||
| 
 | ||||
|   gtk_clist_freeze(GTK_CLIST(nodetree)); | ||||
|   gtk_ctree_insert_node(GTK_CTREE(nodetree), | ||||
| 			subnets_ctn, NULL, l, 1, | ||||
| 			NULL, NULL, NULL, NULL, | ||||
| 			TRUE, FALSE); | ||||
|   sd->ctn = gtk_ctree_insert_node(GTK_CTREE(nodetree), | ||||
| 				  parent, NULL, l, 1, | ||||
| 				  NULL, NULL, NULL, NULL, | ||||
| 				  TRUE, FALSE); | ||||
|   gtk_clist_thaw(GTK_CLIST(nodetree)); | ||||
|   gtk_ctree_node_set_row_data(GTK_CTREE(nodetree), sd->ctn, subnet); | ||||
| 
 | ||||
|   subnet->data = (void*)sd; | ||||
| } | ||||
| 
 | ||||
| void if_subnet_del(subnet_t *subnet) | ||||
| void if_subnet_del(const char *hooktype, va_list ap) | ||||
| { | ||||
|   subnet_t *subnet = va_arg(ap, subnet_t*); | ||||
|   struct if_subnet_data *sd; | ||||
| 
 | ||||
|   sd = (struct if_subnet_data*)(subnet->data); | ||||
|   if(sd && sd->ctn) | ||||
|     { | ||||
|       gtk_clist_freeze(GTK_CLIST(nodetree)); | ||||
|       gtk_ctree_remove_node(GTK_CTREE(nodetree), sd->ctn); | ||||
|       gtk_clist_thaw(GTK_CLIST(nodetree)); | ||||
|     } | ||||
|    | ||||
|   free(sd); | ||||
|   subnet->data = NULL; | ||||
| } | ||||
| 
 | ||||
| void redraw_edges(void) | ||||
|  | @ -424,6 +818,7 @@ void redraw_edges(void) | |||
|   GnomeCanvasPoints *points; | ||||
|   avl_node_t *avlnode; | ||||
|   edge_t *e; | ||||
|   struct if_node_data *fd, *td; | ||||
| 
 | ||||
|   if(edge_group) | ||||
|     gtk_object_destroy(GTK_OBJECT(edge_group)); | ||||
|  | @ -438,22 +833,24 @@ void redraw_edges(void) | |||
|   for(avlnode = edge_tree->head; avlnode; avlnode = avlnode->next) | ||||
|     { | ||||
|       e = (edge_t *)avlnode->data; | ||||
|       fd = (struct if_node_data*)(e->from.node->data); | ||||
|       td = (struct if_node_data*)(e->to.node->data); | ||||
| 
 | ||||
|       if(!e->from.node->status.visible || | ||||
| 	 !e->to.node->status.visible) | ||||
| 	/* We shouldn't draw this line */ | ||||
| 	continue; | ||||
| /*       if(!e->from.node->status.visible || */ | ||||
| /* 	 !e->to.node->status.visible) */ | ||||
| /* 	/\* We shouldn't draw this line *\/ */ | ||||
| /* 	continue; */ | ||||
|        | ||||
|       points = gnome_canvas_points_new(2); | ||||
|        | ||||
|       points->coords[0] = e->from.node->x; | ||||
|       points->coords[1] = e->from.node->y; | ||||
|       points->coords[2] = e->to.node->x; | ||||
|       points->coords[3] = e->to.node->y; | ||||
|       points->coords[0] = fd->x; | ||||
|       points->coords[1] = fd->y; | ||||
|       points->coords[2] = td->x; | ||||
|       points->coords[3] = td->y; | ||||
|       gnome_canvas_item_new(group, | ||||
| 			    gnome_canvas_line_get_type(), | ||||
| 			    "points", points, | ||||
| 			    "fill_color_rgba", 0xe080c0ff, | ||||
| 			    "fill_color_rgba", 0xe080c080, | ||||
| 			    "width_pixels", 2, | ||||
| 			    NULL); | ||||
|       gnome_canvas_points_unref(points); | ||||
|  | @ -464,7 +861,7 @@ void redraw_edges(void) | |||
|   edge_group = group; | ||||
| } | ||||
| 
 | ||||
| void if_edge_add(edge_t *e) | ||||
| void if_edge_add(const char *hooktype, va_list ap) | ||||
| { | ||||
|   redraw_edges(); | ||||
| 
 | ||||
|  | @ -472,7 +869,7 @@ void if_edge_add(edge_t *e) | |||
|   build_graph = 1; | ||||
| } | ||||
| 
 | ||||
| void if_edge_del(edge_t *e) | ||||
| void if_edge_del(const char *hooktype, va_list ap) | ||||
| { | ||||
|   redraw_edges(); | ||||
| 
 | ||||
|  | @ -484,11 +881,11 @@ void if_move_node(node_t *n, double dx, double dy) | |||
| { | ||||
|   double newx, newy; | ||||
|    | ||||
|   newx = n->x + dx; | ||||
|   newy = n->y + dy; | ||||
|   gnome_canvas_item_move(GNOME_CANVAS_ITEM(n->item), newx - n->x, newy - n->y); | ||||
|   n->x = newx; | ||||
|   n->y = newy; | ||||
|   newx = ((struct if_node_data*)(n->data))->x + dx; | ||||
|   newy = ((struct if_node_data*)(n->data))->y + dy; | ||||
|   gnome_canvas_item_move(GNOME_CANVAS_ITEM(((struct if_node_data*)(n->data))->item), newx - ((struct if_node_data*)(n->data))->x, newy - ((struct if_node_data*)(n->data))->y); | ||||
|   ((struct if_node_data*)(n->data))->x = newx; | ||||
|   ((struct if_node_data*)(n->data))->y = newy; | ||||
| } | ||||
| 
 | ||||
| #define X_MARGIN 50.0 | ||||
|  | @ -505,17 +902,17 @@ void set_zooming(void) | |||
|   minx = miny = maxx = maxy = 0.0; | ||||
|   for(i = 0; i < number_of_nodes; i++) | ||||
|     { | ||||
|       if(nodes[i]->x < minx) | ||||
| 	minx = nodes[i]->x; | ||||
|       if(((struct if_node_data*)(nodes[i]->data))->x < minx) | ||||
| 	minx = ((struct if_node_data*)(nodes[i]->data))->x; | ||||
|       else | ||||
| 	if(nodes[i]->x > maxx) | ||||
| 	  maxx = nodes[i]->x; | ||||
| 	if(((struct if_node_data*)(nodes[i]->data))->x > maxx) | ||||
| 	  maxx = ((struct if_node_data*)(nodes[i]->data))->x; | ||||
| 
 | ||||
|       if(nodes[i]->y < miny) | ||||
| 	miny = nodes[i]->y; | ||||
|       if(((struct if_node_data*)(nodes[i]->data))->y < miny) | ||||
| 	miny = ((struct if_node_data*)(nodes[i]->data))->y; | ||||
|       else | ||||
| 	if(nodes[i]->y > maxy) | ||||
| 	  maxy = nodes[i]->y; | ||||
| 	if(((struct if_node_data*)(nodes[i]->data))->y > maxy) | ||||
| 	  maxy = ((struct if_node_data*)(nodes[i]->data))->y; | ||||
|     } | ||||
| 
 | ||||
|   if(minx > ominx - X_MARGIN_BUFFER && ominx > minx) | ||||
|  | @ -595,15 +992,18 @@ void if_build_graph(void) | |||
| { | ||||
|   int i, j, p, max_i; | ||||
|   double delta_m, max_delta_m; | ||||
|   double dx, dy, s, L, max_d, old_x, old_y; | ||||
|   double dx, dy, s, L, min_d, old_x, old_y; | ||||
|   edge_t *e; | ||||
| 
 | ||||
|   if(!keep_drawing) | ||||
|     return; | ||||
|    | ||||
|   if(!inited) | ||||
|     { | ||||
|       for(i = 0; i < number_of_nodes; i++) | ||||
| 	{ | ||||
| 	  x[i] = nodes[i]->x; | ||||
| 	  y[i] = nodes[i]->y; | ||||
| 	  x[i] = ((struct if_node_data*)(nodes[i]->data))->x; | ||||
| 	  y[i] = ((struct if_node_data*)(nodes[i]->data))->y; | ||||
| 	} | ||||
| 
 | ||||
|       /* Initialize Floyd */ | ||||
|  | @ -645,19 +1045,19 @@ void if_build_graph(void) | |||
| 	    } | ||||
| 	} | ||||
| 
 | ||||
|       max_d = 0.0; | ||||
|       min_d = 0.0; | ||||
|       for(i = 0; i < number_of_nodes; i++) | ||||
| 	for(j = i + 1; j < number_of_nodes; j++) | ||||
| 	  if(d[i][j] > max_d && d[i][j] < INFINITY) | ||||
| 	    max_d = d[i][j]; | ||||
| 	  if(d[i][j] < min_d && d[i][j] > 0) | ||||
| 	    min_d = d[i][j]; | ||||
| 
 | ||||
|       L = 300.0 / log(max_d); | ||||
|       L = 5.0 / sqrt(min_d + 1.0); | ||||
| 
 | ||||
|       for(i = 0; i < number_of_nodes; i++) | ||||
| 	{ | ||||
| 	  for(j = i + 1; j < number_of_nodes; j++) | ||||
| 	    { | ||||
| 	      d[i][j] = d[j][i] = log(d[i][j]+1.0); | ||||
| 	      d[i][j] = d[j][i] = sqrt(d[i][j]+1.0); | ||||
| 	      l[i][j] = l[j][i] = L * d[i][j]; | ||||
| 	      k[i][j] = k[j][i] = K / (d[i][j] * d[i][j]); | ||||
| 	    } | ||||
|  | @ -679,7 +1079,10 @@ void if_build_graph(void) | |||
|     } | ||||
| 
 | ||||
|   if(max_delta_m <= epsilon) | ||||
|     build_graph = 0; | ||||
|     { | ||||
|       fprintf(stderr, "Graph building is done; max_delta_m = %f\n", max_delta_m); | ||||
|       build_graph = 0; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       int iter = 0, maxiter = 20; | ||||
|  |  | |||
|  | @ -17,17 +17,21 @@ | |||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| 
 | ||||
|     $Id: interface.h,v 1.1 2002/04/11 14:23:56 zarq Exp $ | ||||
|     $Id: interface.h,v 1.2 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_INTERFACE_H__ | ||||
| #define __TINC_INTERFACE_H__ | ||||
| 
 | ||||
| #include <gtk/gtk.h> | ||||
| #include <glade/glade.h> | ||||
| #include <libgnomeui/gnome-canvas.h> | ||||
| 
 | ||||
| #include "node.h" | ||||
| #include "edge.h" | ||||
| 
 | ||||
| #define INTERFACE_FILE "pokey.glade" | ||||
| 
 | ||||
| typedef struct graph_t { | ||||
|   struct graph_t *attractors[20]; | ||||
|   struct graph_t *repellors[20]; | ||||
|  | @ -36,20 +40,23 @@ typedef struct graph_t { | |||
|   node_t *node; | ||||
| } graph_t; | ||||
| 
 | ||||
| struct if_subnet_data { | ||||
|   GnomeCanvasItem *item;           /* The gnome canvas item associated with the line */ | ||||
|   GtkCTreeNode *ctn; | ||||
| }; | ||||
| 
 | ||||
| struct if_node_data { | ||||
|   double x, y; | ||||
|   int visible; | ||||
|   int id; | ||||
|   GnomeCanvasItem *item; | ||||
|   GtkCTreeNode *ctn; | ||||
|   GladeXML *hi_xml; | ||||
| }; | ||||
| 
 | ||||
| extern int build_graph; | ||||
| 
 | ||||
| void log_message(int, const char *, ...); | ||||
| GtkCTreeNode *if_node_add(node_t *); | ||||
| void if_node_del(node_t *); | ||||
| void if_subnet_add(subnet_t *); | ||||
| void if_subnet_del(subnet_t *); | ||||
| void if_edge_add(edge_t *); | ||||
| void if_edge_del(edge_t *); | ||||
| 
 | ||||
| void if_build_graph(void); | ||||
| void if_graph_add_node(node_t *); | ||||
| void if_graph_add_edge(edge_t *); | ||||
| 
 | ||||
| int init_interface(void); | ||||
| 
 | ||||
| #endif /* __TINC_INTERFACE_H__ */ | ||||
|  |  | |||
							
								
								
									
										103
									
								
								src/pokey/logging.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								src/pokey/logging.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,103 @@ | |||
| /*
 | ||||
|     logging.c -- log messages to e.g. syslog | ||||
|     Copyright (C) 2001-2002 Guus Sliepen <guus@sliepen.warande.net>, | ||||
|                   2001-2002 Ivo Timmermans <itimmermans@bigfoot.com> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| 
 | ||||
|     $Id: logging.c,v 1.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <assert.h> | ||||
| #include <stdarg.h> | ||||
| #include <stdio.h> | ||||
| #include <syslog.h> | ||||
| 
 | ||||
| #include <avl_tree.h> | ||||
| 
 | ||||
| #include "logging.h" | ||||
| 
 | ||||
| avl_tree_t *log_hooks_tree = NULL; | ||||
| 
 | ||||
| int debug_lvl = 0; | ||||
| 
 | ||||
| int log_compare(const void *a, const void *b) | ||||
| { | ||||
|   if(a < b) | ||||
|     return -1; | ||||
|   if(a > b) | ||||
|     return 1; | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| void log(int level, int priority, char *fmt, ...) | ||||
| { | ||||
|   avl_node_t *avlnode; | ||||
|   va_list args; | ||||
| 
 | ||||
|   va_start(args, fmt); | ||||
|   for(avlnode = log_hooks_tree->head; avlnode; avlnode = avlnode->next) | ||||
|     { | ||||
|       assert(avlnode->data); | ||||
|       ((log_function_t*)(avlnode->data))(level, priority, fmt, args); | ||||
|     } | ||||
|   va_end(args); | ||||
| } | ||||
| 
 | ||||
| void log_add_hook(log_function_t *fn) | ||||
| { | ||||
|   if(!log_hooks_tree) | ||||
|     log_hooks_tree = avl_alloc_tree(log_compare, NULL); | ||||
| 
 | ||||
|   avl_insert(log_hooks_tree, (void*)fn); | ||||
| } | ||||
| 
 | ||||
| void log_del_hook(log_function_t *fn) | ||||
| { | ||||
|   avl_delete(log_hooks_tree, (void*)fn); | ||||
| } | ||||
| 
 | ||||
| void log_default(int level, int priority, char *fmt, va_list ap) | ||||
| { | ||||
|   if(debug_lvl >= level) | ||||
|     vfprintf(stderr, fmt, ap); | ||||
| } | ||||
| 
 | ||||
| void log_syslog(int level, int priority, char *fmt, va_list ap) | ||||
| { | ||||
|   const int priorities[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_ERR, LOG_CRIT }; | ||||
| 
 | ||||
|   if(debug_lvl >= level) | ||||
|     vsyslog(priorities[priority], fmt, ap); | ||||
| } | ||||
| 
 | ||||
| void tinc_syslog(int priority, char *fmt, ...) | ||||
| { | ||||
|   /* Mapping syslog prio -> tinc prio */ | ||||
|   const int priorities[] = { TLOG_CRITICAL, TLOG_CRITICAL, TLOG_CRITICAL, TLOG_ERROR, | ||||
| 			       TLOG_NOTICE, TLOG_NOTICE, TLOG_INFO, TLOG_DEBUG }; | ||||
|   avl_node_t *avlnode; | ||||
|   va_list args; | ||||
| 
 | ||||
|   va_start(args, fmt); | ||||
|   for(avlnode = log_hooks_tree->head; avlnode; avlnode = avlnode->next) | ||||
|     { | ||||
|       assert(avlnode->data); | ||||
|       ((log_function_t*)(avlnode->data))(0, priorities[priority], fmt, args); | ||||
|     } | ||||
|   va_end(args); | ||||
| } | ||||
							
								
								
									
										190
									
								
								src/pokey/meta.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								src/pokey/meta.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,190 @@ | |||
| /*
 | ||||
|     meta.c -- handle the meta communication | ||||
|     Copyright (C) 2000-2002 Guus Sliepen <guus@sliepen.warande.net>, | ||||
|                   2000-2002 Ivo Timmermans <itimmermans@bigfoot.com> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| #include <utils.h> | ||||
| #include <avl_tree.h> | ||||
| 
 | ||||
| #include <errno.h> | ||||
| #include <unistd.h> | ||||
| #include <string.h> | ||||
| /* This line must be below the rest for FreeBSD */ | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| 
 | ||||
| #include <openssl/evp.h> | ||||
| 
 | ||||
| #include "net.h" | ||||
| #include "connection.h" | ||||
| #include "interface.h" | ||||
| #include "system.h" | ||||
| #include "protocol.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| int send_meta(connection_t *c, char *buffer, int length) | ||||
| { | ||||
|   char *bufp; | ||||
|   int outlen; | ||||
|   char outbuf[MAXBUFSIZE]; | ||||
| cp | ||||
|   log(DEBUG_META, TLOG_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; | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|         } | ||||
| 
 | ||||
|       /* 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) | ||||
|         { | ||||
|           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; | ||||
| } | ||||
							
								
								
									
										32
									
								
								src/pokey/meta.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/pokey/meta.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | |||
| /*
 | ||||
|     meta.h -- header for meta.c | ||||
|     Copyright (C) 2000-2002 Guus Sliepen <guus@sliepen.warande.net>, | ||||
|                   2000-2002 Ivo Timmermans <itimmermans@bigfoot.com> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_META_H__ | ||||
| #define __TINC_META_H__ | ||||
| 
 | ||||
| #include "connection.h" | ||||
| 
 | ||||
| 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__ */ | ||||
							
								
								
									
										467
									
								
								src/pokey/net.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										467
									
								
								src/pokey/net.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,467 @@ | |||
| /*
 | ||||
|     net.c -- most of the network code | ||||
|     Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <netdb.h> | ||||
| #include <netinet/in.h> | ||||
| #ifdef HAVE_LINUX | ||||
|  #include <netinet/ip.h> | ||||
|  #include <netinet/tcp.h> | ||||
| #endif | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <signal.h> | ||||
| #include <sys/time.h> | ||||
| #include <sys/types.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/ioctl.h> | ||||
| /* SunOS really wants sys/socket.h BEFORE net/if.h,
 | ||||
|    and FreeBSD wants these lines below the rest. */ | ||||
| #include <arpa/inet.h> | ||||
| #include <sys/socket.h> | ||||
| #include <net/if.h> | ||||
| 
 | ||||
| #include <openssl/rand.h> | ||||
| 
 | ||||
| #include <gtk/gtk.h> | ||||
| 
 | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| #include <avl_tree.h> | ||||
| #include <list.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| #include "interface.h" | ||||
| #include "connection.h" | ||||
| #include "meta.h" | ||||
| #include "net.h" | ||||
| #include "netutl.h" | ||||
| #include "process.h" | ||||
| #include "protocol.h" | ||||
| #include "subnet.h" | ||||
| #include "graph.h" | ||||
| #include "process.h" | ||||
| #include "route.h" | ||||
| #include "device.h" | ||||
| #include "event.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| int do_prune = 0; | ||||
| int do_purge = 0; | ||||
| int sighup = 0; | ||||
| int sigalrm = 0; | ||||
| 
 | ||||
| time_t now = 0; | ||||
| 
 | ||||
| /*
 | ||||
|   put all file descriptors in an fd_set array | ||||
| */ | ||||
| void build_fdset(fd_set *fs) | ||||
| { | ||||
|   avl_node_t *node; | ||||
|   connection_t *c; | ||||
|   int i; | ||||
| cp | ||||
|   FD_ZERO(fs); | ||||
| 
 | ||||
|   for(node = connection_tree->head; node; node = node->next) | ||||
|     { | ||||
|       c = (connection_t *)node->data; | ||||
|       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); | ||||
|     } | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| /* Purge edges and subnets of unreachable nodes. Use carefully. */ | ||||
| 
 | ||||
| void purge(void) | ||||
| { | ||||
|   avl_node_t *nnode, *nnext, *enode, *enext, *snode, *snext, *cnode; | ||||
|   node_t *n; | ||||
|   edge_t *e; | ||||
|   subnet_t *s; | ||||
|   connection_t *c; | ||||
| cp | ||||
|   log(DEBUG_PROTOCOL, TLOG_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; | ||||
| 
 | ||||
|         for(cnode = connection_tree->head; cnode; cnode = cnode->next) | ||||
|         { | ||||
|           c = (connection_t *)cnode->data; | ||||
|           if(c->status.active) | ||||
|             send_del_subnet(c, s); | ||||
|         } | ||||
| 
 | ||||
|         subnet_del(n, s); | ||||
|       } | ||||
| 
 | ||||
|       for(enode = n->edge_tree->head; enode; enode = enext) | ||||
|       { | ||||
|         enext = enode->next; | ||||
|         e = (edge_t *)enode->data; | ||||
| 
 | ||||
|         for(cnode = connection_tree->head; cnode; cnode = cnode->next) | ||||
|         { | ||||
|           c = (connection_t *)cnode->data; | ||||
|           if(c->status.active) | ||||
|             send_del_edge(c, e); | ||||
|         } | ||||
| 
 | ||||
|         edge_del(e); | ||||
|       } | ||||
| 
 | ||||
|       node_del(n); | ||||
|     } | ||||
|   } | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   Terminate a connection: | ||||
|   - Close the socket | ||||
|   - Remove associated edge and tell other connections about it if report = 1 | ||||
|   - Check if we need to retry making an outgoing connection | ||||
|   - Deactivate the host | ||||
| */ | ||||
| void terminate_connection(connection_t *c, int report) | ||||
| { | ||||
|   avl_node_t *node; | ||||
|   connection_t *other; | ||||
| cp | ||||
|   if(c->status.remove) | ||||
|     return; | ||||
| 
 | ||||
|   if(debug_lvl >= DEBUG_CONNECTIONS) | ||||
|     syslog(LOG_NOTICE, _("Closing connection with %s (%s)"), | ||||
|            c->name, c->hostname); | ||||
| 
 | ||||
|   c->status.remove = 1; | ||||
| 
 | ||||
|   if(c->socket) | ||||
|     close(c->socket); | ||||
| 
 | ||||
|   if(c->edge) | ||||
|     { | ||||
|       if(report) | ||||
|         { | ||||
|           for(node = connection_tree->head; node; node = node->next) | ||||
|             { | ||||
|               other = (connection_t *)node->data; | ||||
|               if(other->status.active && other != c) | ||||
|                 send_del_edge(other, c->edge); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|       edge_del(c->edge); | ||||
| 
 | ||||
|       /* Run MST and SSSP algorithms */ | ||||
| 
 | ||||
|       graph(); | ||||
|     } | ||||
| 
 | ||||
|   /* Check if this was our outgoing connection */ | ||||
| 
 | ||||
|   if(c->outgoing) | ||||
|     { | ||||
|       retry_outgoing(c->outgoing); | ||||
|       c->outgoing = NULL; | ||||
|     } | ||||
| 
 | ||||
|   /* Deactivate */ | ||||
| 
 | ||||
|   c->status.active = 0; | ||||
|   if(c->node) | ||||
|     c->node->connection = NULL; | ||||
|   do_prune = 1; | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   Check if the other end is active. | ||||
|   If we have sent packets, but didn't receive any, | ||||
|   then possibly the other end is dead. We send a | ||||
|   PING request over the meta connection. If the other | ||||
|   end does not reply in time, we consider them dead | ||||
|   and close the connection. | ||||
| */ | ||||
| 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(debug_lvl >= DEBUG_CONNECTIONS) | ||||
|                 syslog(LOG_WARNING, _("Timeout from %s (%s) during authentication"), | ||||
|                        c->name, c->hostname); | ||||
|               terminate_connection(c, 0); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   check all connections to see if anything | ||||
|   happened on their sockets | ||||
| */ | ||||
| void check_network_activity(fd_set *f) | ||||
| { | ||||
|   connection_t *c; | ||||
|   avl_node_t *node; | ||||
|   int result, i; | ||||
|   int len = sizeof(result); | ||||
| cp | ||||
|   for(i = 0; i < listen_sockets; i++) | ||||
|     { | ||||
|       if(FD_ISSET(listen_socket[i].tcp, f)) | ||||
| 	handle_new_meta_connection(listen_socket[i].tcp); | ||||
|     } | ||||
| 
 | ||||
|   for(node = connection_tree->head; node; node = node->next) | ||||
|     { | ||||
|       c = (connection_t *)node->data; | ||||
| 
 | ||||
|       if(c->status.remove) | ||||
|         return; | ||||
| 
 | ||||
|       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); | ||||
|               return; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| void prune_connections(void) | ||||
| { | ||||
|   connection_t *c; | ||||
|   avl_node_t *node, *next; | ||||
| cp | ||||
|   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(); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   this is where it all happens... | ||||
| */ | ||||
| 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; */ | ||||
|       tv.tv_sec = 0; | ||||
|       tv.tv_usec = 50000; | ||||
| 
 | ||||
|       if(do_prune) | ||||
|         { | ||||
|           prune_connections(); | ||||
|           do_prune = 0; | ||||
|         } | ||||
| 
 | ||||
|       build_fdset(&fset); | ||||
| 
 | ||||
|       while(gtk_events_pending())  | ||||
| 	if(gtk_main_iteration() == FALSE) | ||||
| 	  return; | ||||
| 
 | ||||
|       if((r = select(FD_SETSIZE, &fset, NULL, NULL, &tv)) < 0) | ||||
|         { | ||||
|           if(errno != EINTR) /* because of a signal */ | ||||
|             { | ||||
|               syslog(LOG_ERR, _("Error while waiting for input: %s"), strerror(errno)); | ||||
|               return; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|       if(r > 0) | ||||
|         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(myself->connection, 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; | ||||
|         } | ||||
| 
 | ||||
|       if(build_graph) | ||||
| 	if_build_graph(); | ||||
|     } | ||||
| cp | ||||
| } | ||||
							
								
								
									
										153
									
								
								src/pokey/net.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								src/pokey/net.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,153 @@ | |||
| /*
 | ||||
|     net.h -- header for net.c | ||||
|     Copyright (C) 1998-2002 Ivo Timmermans <zarq@iname.com> | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_NET_H__ | ||||
| #define __TINC_NET_H__ | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| #include <netinet/in.h> | ||||
| #include <sys/time.h> | ||||
| 
 | ||||
| #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. */ | ||||
| #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. */ | ||||
| #endif | ||||
| 
 | ||||
| #define MAXSOCKETS 128 /* Overkill... */ | ||||
| 
 | ||||
| #define MAXQUEUELENGTH 8 | ||||
| 
 | ||||
| typedef struct mac_t | ||||
| { | ||||
|   unsigned char x[6]; | ||||
| } mac_t; | ||||
| 
 | ||||
| typedef struct ipv4_t | ||||
| { | ||||
|   unsigned char x[4]; | ||||
| } ipv4_t; | ||||
| 
 | ||||
| typedef struct ip_mask_t { | ||||
|   ipv4_t address; | ||||
|   ipv4_t mask; | ||||
| } ip_mask_t; | ||||
| 
 | ||||
| typedef struct ipv6_t | ||||
| { | ||||
|   unsigned short x[8]; | ||||
| } ipv6_t; | ||||
| 
 | ||||
| typedef unsigned short port_t; | ||||
| 
 | ||||
| typedef short length_t; | ||||
| 
 | ||||
| typedef union { | ||||
|   struct sockaddr sa; | ||||
|   struct sockaddr_in in; | ||||
|   struct sockaddr_in6 in6; | ||||
| } sockaddr_t; | ||||
| 
 | ||||
| #ifdef SA_LEN | ||||
| #define SALEN(s) SA_LEN(&s) | ||||
| #else | ||||
| #define SALEN(s) (s.sa_family==AF_INET?sizeof(struct sockaddr_in):sizeof(struct sockaddr_in6)) | ||||
| #endif | ||||
| 
 | ||||
| typedef struct vpn_packet_t { | ||||
|   length_t len;			/* the actual number of bytes in the `data' field */ | ||||
|   int priority;                 /* priority or TOS */ | ||||
|   unsigned int seqno;	        /* 32 bits sequence number (network byte order of course) */ | ||||
|   unsigned char data[MAXSIZE]; | ||||
| } vpn_packet_t; | ||||
| 
 | ||||
| typedef struct queue_element_t { | ||||
|   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; | ||||
| } packet_queue_t; | ||||
| 
 | ||||
| typedef struct outgoing_t { | ||||
|   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; | ||||
| } listen_socket_t; | ||||
| 
 | ||||
| extern int maxtimeout; | ||||
| extern int seconds_till_retry; | ||||
| 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 */ | ||||
| 
 | ||||
| extern listen_socket_t listen_socket[MAXSOCKETS]; | ||||
| extern int listen_sockets; | ||||
| extern int keyexpires; | ||||
| extern int keylifetime; | ||||
| extern int do_prune; | ||||
| extern int do_purge; | ||||
| extern char *myport; | ||||
| extern time_t now; | ||||
| 
 | ||||
| extern void retry_outgoing(outgoing_t *); | ||||
| extern void handle_incoming_vpn_data(int); | ||||
| extern void finish_connecting(connection_t *); | ||||
| extern void do_outgoing_connection(connection_t *); | ||||
| extern int handle_new_meta_connection(int); | ||||
| extern int setup_listen_socket(sockaddr_t *); | ||||
| extern int setup_vpn_in_socket(sockaddr_t *); | ||||
| extern void send_packet(struct node_t *, vpn_packet_t *); | ||||
| extern void receive_packet(struct node_t *, vpn_packet_t *); | ||||
| extern void receive_tcppacket(struct connection_t *, char *, int); | ||||
| extern void broadcast_packet(struct node_t *, vpn_packet_t *); | ||||
| extern int setup_network_connections(void); | ||||
| extern void setup_outgoing_connection(struct outgoing_t *); | ||||
| extern void try_outgoing_connections(void); | ||||
| extern void close_network_connections(void); | ||||
| extern void main_loop(void); | ||||
| 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__ */ | ||||
							
								
								
									
										429
									
								
								src/pokey/net_packet.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										429
									
								
								src/pokey/net_packet.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,429 @@ | |||
| /*
 | ||||
|     net_packet.c -- Handles in- and outgoing VPN packets | ||||
|     Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <netdb.h> | ||||
| #include <netinet/in.h> | ||||
| #ifdef HAVE_LINUX | ||||
|  #include <netinet/ip.h> | ||||
|  #include <netinet/tcp.h> | ||||
| #endif | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <signal.h> | ||||
| #include <sys/time.h> | ||||
| #include <sys/types.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/ioctl.h> | ||||
| /* SunOS really wants sys/socket.h BEFORE net/if.h,
 | ||||
|    and FreeBSD wants these lines below the rest. */ | ||||
| #include <arpa/inet.h> | ||||
| #include <sys/socket.h> | ||||
| #include <net/if.h> | ||||
| 
 | ||||
| #include <openssl/rand.h> | ||||
| #include <openssl/evp.h> | ||||
| #include <openssl/pem.h> | ||||
| #include <openssl/hmac.h> | ||||
| 
 | ||||
| #ifndef HAVE_RAND_PSEUDO_BYTES | ||||
| #define RAND_pseudo_bytes RAND_bytes | ||||
| #endif | ||||
| 
 | ||||
| #include <zlib.h> | ||||
| 
 | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| #include <avl_tree.h> | ||||
| #include <list.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| #include "connection.h" | ||||
| #include "meta.h" | ||||
| #include "net.h" | ||||
| #include "netutl.h" | ||||
| #include "process.h" | ||||
| #include "protocol.h" | ||||
| #include "subnet.h" | ||||
| #include "graph.h" | ||||
| #include "process.h" | ||||
| #include "route.h" | ||||
| #include "device.h" | ||||
| #include "event.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| int keylifetime = 0; | ||||
| int keyexpires = 0; | ||||
| 
 | ||||
| #define MAX_SEQNO 1073741824 | ||||
| 
 | ||||
| /* VPN packet I/O */ | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
| 
 | ||||
| void receive_tcppacket(connection_t *c, char *buffer, int len) | ||||
| { | ||||
|   vpn_packet_t outpkt; | ||||
| cp | ||||
|   outpkt.len = len; | ||||
|   memcpy(outpkt.data, buffer, len); | ||||
| 
 | ||||
|   receive_packet(c->node, &outpkt); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
| 
 | ||||
| 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 */ | ||||
| 
 | ||||
|   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); | ||||
| 
 | ||||
|       /* Since packet is on the stack of handle_tap_input(),
 | ||||
|          we have to make a copy of it first. */ | ||||
| 
 | ||||
|       copy = xmalloc(sizeof(vpn_packet_t)); | ||||
|       memcpy(copy, inpkt, sizeof(vpn_packet_t)); | ||||
| 
 | ||||
|       list_insert_tail(n->queue, copy); | ||||
| 
 | ||||
|       if(n->queue->count > MAXQUEUELENGTH) | ||||
|         list_delete_head(n->queue); | ||||
| 
 | ||||
|       if(!n->status.waitingforkey) | ||||
|         send_req_key(n->nexthop->connection, myself, n); | ||||
| 
 | ||||
|       n->status.waitingforkey = 1; | ||||
| 
 | ||||
|       return; | ||||
|     } | ||||
| 
 | ||||
|   origlen = inpkt->len; | ||||
|   origpriority = inpkt->priority; | ||||
| 
 | ||||
|   /* Compress the packet */ | ||||
| 
 | ||||
|   if(n->compression) | ||||
|   { | ||||
|     outpkt = pkt[nextpkt++]; | ||||
| 
 | ||||
|     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; | ||||
|   } | ||||
| 
 | ||||
|   /* Add sequence number */ | ||||
| 
 | ||||
|   inpkt->seqno = htonl(++(n->sent_seqno)); | ||||
|   inpkt->len += sizeof(inpkt->seqno); | ||||
| 
 | ||||
|   /* Encrypt the packet */ | ||||
| 
 | ||||
|   if(n->cipher) | ||||
|   { | ||||
|     outpkt = pkt[nextpkt++]; | ||||
| 
 | ||||
|     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); | ||||
| 
 | ||||
|     outpkt->len = outlen + outpad; | ||||
|     inpkt = outpkt; | ||||
|   } | ||||
| 
 | ||||
|   /* Add the message authentication code */ | ||||
| 
 | ||||
|   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)); | ||||
|     } | ||||
| #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 | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   send a packet to the given vpn ip. | ||||
| */ | ||||
| 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); | ||||
| } | ||||
| 
 | ||||
| /* Broadcast a packet using the minimum spanning tree */ | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|     } | ||||
| 
 | ||||
|   if((pkt.len = recvfrom(sock, (char *)&pkt.seqno, MAXSIZE, 0, &from.sa, &fromlen)) <= 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 | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										546
									
								
								src/pokey/net_setup.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										546
									
								
								src/pokey/net_setup.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,546 @@ | |||
| /*
 | ||||
|     net_setup.c -- Setup. | ||||
|     Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <netdb.h> | ||||
| #include <netinet/in.h> | ||||
| #ifdef HAVE_LINUX | ||||
|  #include <netinet/ip.h> | ||||
|  #include <netinet/tcp.h> | ||||
| #endif | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <signal.h> | ||||
| #include <sys/time.h> | ||||
| #include <sys/types.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/ioctl.h> | ||||
| /* SunOS really wants sys/socket.h BEFORE net/if.h,
 | ||||
|    and FreeBSD wants these lines below the rest. */ | ||||
| #include <arpa/inet.h> | ||||
| #include <sys/socket.h> | ||||
| #include <net/if.h> | ||||
| 
 | ||||
| #include <openssl/pem.h> | ||||
| #include <openssl/rsa.h> | ||||
| #include <openssl/rand.h> | ||||
| 
 | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| #include <avl_tree.h> | ||||
| #include <list.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| #include "interface.h" | ||||
| #include "connection.h" | ||||
| #include "meta.h" | ||||
| #include "net.h" | ||||
| #include "netutl.h" | ||||
| #include "process.h" | ||||
| #include "protocol.h" | ||||
| #include "subnet.h" | ||||
| #include "graph.h" | ||||
| #include "process.h" | ||||
| #include "route.h" | ||||
| #include "device.h" | ||||
| #include "event.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| char *myport; | ||||
| 
 | ||||
| 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)) | ||||
|         { | ||||
|           if((fp = fopen(fname, "r")) == NULL) | ||||
|             { | ||||
|               log(0, TLOG_ERROR, | ||||
| 		  _("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) | ||||
|             { | ||||
|               syslog(LOG_ERR, _("Reading RSA public key file `%s' failed: %s"), | ||||
|                      fname, strerror(errno)); | ||||
|               return -1; | ||||
|             } | ||||
|           return 0; | ||||
|         } | ||||
|       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); | ||||
|   if((fp = fopen(fname, "r"))) | ||||
|     { | ||||
|       c->rsa_key = PEM_read_RSAPublicKey(fp, &c->rsa_key, NULL, NULL); | ||||
|       fclose(fp); | ||||
|     } | ||||
| 
 | ||||
|   free(fname); | ||||
| 
 | ||||
|   if(c->rsa_key) | ||||
|     return 0; | ||||
|   else | ||||
|     { | ||||
|       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)) | ||||
|     { | ||||
|       if((fp = fopen(fname, "r")) == NULL) | ||||
|         { | ||||
|           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; | ||||
| } | ||||
| 
 | ||||
| int check_rsa_key(RSA *rsa_key) | ||||
| { | ||||
|   char *test1, *test2, *test3; | ||||
| cp | ||||
|   if(rsa_key->p && rsa_key->q) | ||||
|     { | ||||
|       if(RSA_check_key(rsa_key) != 1) | ||||
|           return -1; | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       test1 = xmalloc(RSA_size(rsa_key)); | ||||
|       test2 = xmalloc(RSA_size(rsa_key)); | ||||
|       test3 = xmalloc(RSA_size(rsa_key)); | ||||
| 
 | ||||
|       if(RSA_public_encrypt(RSA_size(rsa_key), test1, test2, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key)) | ||||
|           return -1; | ||||
| 
 | ||||
|       if(RSA_private_decrypt(RSA_size(rsa_key), test2, test3, rsa_key, RSA_NO_PADDING) != RSA_size(rsa_key)) | ||||
|           return -1; | ||||
| 
 | ||||
|       if(memcmp(test1, test3, RSA_size(rsa_key))) | ||||
|           return -1; | ||||
|     } | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   Configure node_t myself and set up the local sockets (listen only) | ||||
| */ | ||||
| int setup_myself(void) | ||||
| { | ||||
|   config_t *cfg; | ||||
|   subnet_t *subnet; | ||||
|   char *name, *mode, *afname, *cipher, *digest; | ||||
|   int choice; | ||||
| 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(check_rsa_key(myself->connection->rsa_key)) | ||||
|     { | ||||
|       syslog(LOG_ERR, _("Invalid public/private keypair!")); | ||||
|       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); | ||||
|     } | ||||
| 
 | ||||
| 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); | ||||
| #if !defined(SOL_IP) || !defined(IP_TOS) | ||||
|   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 | ||||
|         { | ||||
|           if(!(myself->cipher = EVP_get_cipherbyname(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 | ||||
|         { | ||||
|           if(!(myself->digest = EVP_get_digestbyname(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; | ||||
|   node_add(myself); | ||||
| 
 | ||||
|   graph(); | ||||
| 
 | ||||
|   syslog(LOG_NOTICE, _("Ready")); | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   setup all initial network connections | ||||
| */ | ||||
| int setup_network_connections(void) | ||||
| { | ||||
| 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_myself() < 0) | ||||
|     return -1; | ||||
| 
 | ||||
|   try_outgoing_connections(); | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   close all open network connections | ||||
| */ | ||||
| void close_network_connections(void) | ||||
| { | ||||
|   avl_node_t *node, *next; | ||||
|   connection_t *c; | ||||
|   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(); | ||||
| 
 | ||||
| cp | ||||
|   return; | ||||
| } | ||||
							
								
								
									
										491
									
								
								src/pokey/net_socket.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										491
									
								
								src/pokey/net_socket.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,491 @@ | |||
| /*
 | ||||
|     net_socket.c -- Handle various kinds of sockets. | ||||
|     Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <netdb.h> | ||||
| #include <netinet/in.h> | ||||
| #ifdef HAVE_LINUX | ||||
|  #include <netinet/ip.h> | ||||
|  #include <netinet/tcp.h> | ||||
| #endif | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <signal.h> | ||||
| #include <sys/time.h> | ||||
| #include <sys/types.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/ioctl.h> | ||||
| /* SunOS really wants sys/socket.h BEFORE net/if.h,
 | ||||
|    and FreeBSD wants these lines below the rest. */ | ||||
| #include <arpa/inet.h> | ||||
| #include <sys/socket.h> | ||||
| #include <net/if.h> | ||||
| 
 | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| #include <avl_tree.h> | ||||
| #include <list.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| #include "interface.h" | ||||
| #include "connection.h" | ||||
| #include "meta.h" | ||||
| #include "net.h" | ||||
| #include "netutl.h" | ||||
| #include "process.h" | ||||
| #include "protocol.h" | ||||
| #include "subnet.h" | ||||
| #include "graph.h" | ||||
| #include "process.h" | ||||
| #include "route.h" | ||||
| #include "device.h" | ||||
| #include "event.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| int addressfamily = AF_INET; | ||||
| int maxtimeout = 900; | ||||
| int seconds_till_retry = 5; | ||||
| 
 | ||||
| listen_socket_t listen_socket[MAXSOCKETS]; | ||||
| int listen_sockets = 0; | ||||
| 
 | ||||
| /* Setup sockets */ | ||||
| 
 | ||||
| int setup_listen_socket(sockaddr_t *sa) | ||||
| { | ||||
|   int nfd, flags; | ||||
|   char *addrstr; | ||||
|   int option; | ||||
| #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) | ||||
|   char *interface; | ||||
|   struct ifreq ifr; | ||||
| #endif | ||||
| cp | ||||
|   if((nfd = socket(sa->sa.sa_family, SOCK_STREAM, IPPROTO_TCP)) < 0) | ||||
|     { | ||||
|       log(0, TLOG_ERROR, | ||||
| 	  _("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)); | ||||
| 
 | ||||
| #if defined(SOL_TCP) && defined(TCP_NODELAY) | ||||
|   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)); | ||||
| #endif | ||||
| 
 | ||||
|   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; | ||||
| 	} | ||||
| #else | ||||
|       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; | ||||
| } | ||||
| 
 | ||||
| int setup_vpn_in_socket(sockaddr_t *sa) | ||||
| { | ||||
|   int nfd, flags; | ||||
|   char *addrstr; | ||||
|   int option; | ||||
| #if defined(SOL_SOCKET) && defined(SO_BINDTODEVICE) | ||||
|   char *interface; | ||||
|   struct ifreq ifr; | ||||
| #endif | ||||
| cp | ||||
|   if((nfd = socket(sa->sa.sa_family, SOCK_DGRAM, IPPROTO_UDP)) < 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; | ||||
| 	} | ||||
|     } | ||||
| #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; | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| 
 | ||||
|   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 */ | ||||
| 
 | ||||
| #ifdef HAVE_LINUX | ||||
|   option = 1; | ||||
|   setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option)); | ||||
| 
 | ||||
|   option = IPTOS_LOWDELAY; | ||||
|   setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option)); | ||||
| #endif | ||||
| 
 | ||||
|   /* 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(debug_lvl >= DEBUG_CONNECTIONS) | ||||
|     syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname); | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void finish_connecting(connection_t *c) | ||||
| { | ||||
| cp | ||||
|   if(debug_lvl >= DEBUG_CONNECTIONS) | ||||
|     syslog(LOG_INFO, _("Connected to %s (%s)"), c->name, c->hostname); | ||||
| 
 | ||||
|   c->last_ping_time = now; | ||||
| 
 | ||||
|   send_id(c); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| void do_outgoing_connection(connection_t *c) | ||||
| { | ||||
|   char *address, *port; | ||||
|   int option, result, flags; | ||||
| cp | ||||
| begin: | ||||
|   if(!c->outgoing->ai) | ||||
|     { | ||||
|       if(!c->outgoing->cfg) | ||||
|         { | ||||
|           log(DEBUG_CONNECTIONS, TLOG_ERROR, | ||||
| 	      _("Could not set up a meta connection to %s"), | ||||
| 	      c->name); | ||||
|           c->status.remove = 1; | ||||
| 	  do_prune = 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; | ||||
|     } | ||||
| 
 | ||||
|   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); | ||||
| 
 | ||||
|   c->hostname = sockaddr2hostname(&c->address); | ||||
| 
 | ||||
|   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); | ||||
| 
 | ||||
|   if(c->socket == -1) | ||||
|     { | ||||
|       if(debug_lvl >= DEBUG_CONNECTIONS) | ||||
|         syslog(LOG_ERR, _("Creating socket for %s failed: %s"), c->hostname, strerror(errno)); | ||||
| 
 | ||||
|       goto begin; | ||||
|     } | ||||
| 
 | ||||
|   /* Optimize TCP settings */ | ||||
| 
 | ||||
| #ifdef HAVE_LINUX | ||||
|   option = 1; | ||||
|   setsockopt(c->socket, SOL_TCP, TCP_NODELAY, &option, sizeof(option)); | ||||
| 
 | ||||
|   option = IPTOS_LOWDELAY; | ||||
|   setsockopt(c->socket, SOL_IP, IP_TOS, &option, sizeof(option)); | ||||
| #endif | ||||
| 
 | ||||
|   /* Non-blocking */ | ||||
| 
 | ||||
|   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)); | ||||
|     } | ||||
| 
 | ||||
|   /* Connect */ | ||||
| 
 | ||||
|   result = connect(c->socket, &c->address.sa, SALEN(c->address.sa)); | ||||
| 
 | ||||
|   if(result == -1) | ||||
|     { | ||||
|       if(errno == EINPROGRESS) | ||||
|         { | ||||
|           c->status.connecting = 1; | ||||
| 	  return; | ||||
| 	} | ||||
| 
 | ||||
|       close(c->socket); | ||||
| 
 | ||||
|       if(debug_lvl >= DEBUG_CONNECTIONS) | ||||
|         syslog(LOG_ERR, _("%s: %s"), c->hostname, strerror(errno)); | ||||
| 
 | ||||
|       goto begin; | ||||
|     } | ||||
| 
 | ||||
|   finish_connecting(c); | ||||
|   return; | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| void setup_outgoing_connection(outgoing_t *outgoing) | ||||
| { | ||||
|   connection_t *c; | ||||
|   node_t *n; | ||||
| cp | ||||
|   n = lookup_node(outgoing->name); | ||||
|    | ||||
|   if(n) | ||||
|     if(n->connection) | ||||
|       { | ||||
|         log(DEBUG_CONNECTIONS, TLOG_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); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   accept a new tcp connect and create a | ||||
|   new connection | ||||
| */ | ||||
| int handle_new_meta_connection(int sock) | ||||
| { | ||||
|   connection_t *c; | ||||
|   sockaddr_t sa; | ||||
|   int fd, len = sizeof(sa); | ||||
| cp | ||||
|   if((fd = accept(sock, &sa.sa, &len)) < 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; | ||||
| 
 | ||||
|   log(DEBUG_CONNECTIONS, TLOG_NOTICE, | ||||
|       _("Connection from %s"), | ||||
|       c->hostname); | ||||
| 
 | ||||
|   connection_add(c); | ||||
| 
 | ||||
|   c->allow_request = ID; | ||||
|   send_id(c); | ||||
| cp | ||||
|   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); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										250
									
								
								src/pokey/netutl.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								src/pokey/netutl.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,250 @@ | |||
| /*
 | ||||
|     netutl.c -- some supporting network utility code | ||||
|     Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com> | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <fcntl.h> | ||||
| #include <netdb.h> | ||||
| #include <netinet/in.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <signal.h> | ||||
| #include <sys/socket.h> | ||||
| #include <arpa/inet.h> | ||||
| 
 | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| 
 | ||||
| #include "errno.h" | ||||
| #include "interface.h" | ||||
| #include "conf.h" | ||||
| #include "net.h" | ||||
| #include "netutl.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| int hostnames = 0; | ||||
| 
 | ||||
| /*
 | ||||
|   Turn a string into a struct addrinfo. | ||||
|   Return NULL on failure. | ||||
| */ | ||||
| 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; | ||||
| 
 | ||||
|   if((err = getaddrinfo(address, service, &hint, &ai))) | ||||
|     { | ||||
|       log(DEBUG_ERROR, LOG_WARNING, | ||||
| 	  _("Error looking up %s port %s: %s\n"), | ||||
| 	  address, service, gai_strerror(err)); | ||||
|       cp_trace(); | ||||
|       return NULL; | ||||
|     } | ||||
| 
 | ||||
| cp | ||||
|   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; | ||||
| 
 | ||||
|   if((err = getaddrinfo(address, port, &hint, &ai) || !ai)) | ||||
|     { | ||||
|       log(0, TLOG_ERROR, | ||||
| 	  _("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; | ||||
| } | ||||
| 
 | ||||
| void sockaddr2str(sockaddr_t *sa, char **addrstr, char **portstr) | ||||
| { | ||||
|   char address[NI_MAXHOST]; | ||||
|   char port[NI_MAXSERV]; | ||||
|   char *scopeid; | ||||
|   int err; | ||||
| cp | ||||
|   if((err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV))) | ||||
|     { | ||||
|       syslog(LOG_ERR, _("Error while translating addresses: %s"), gai_strerror(err)); | ||||
|       cp_trace(); | ||||
|       raise(SIGFPE); | ||||
|       exit(0); | ||||
|     } | ||||
| 
 | ||||
| #ifdef HAVE_LINUX | ||||
|   if((scopeid = strchr(address, '%'))) | ||||
|     *scopeid = '\0';  /* Descope. */ | ||||
| #endif | ||||
| 
 | ||||
|   *addrstr = xstrdup(address); | ||||
|   *portstr = xstrdup(port); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| char *sockaddr2hostname(sockaddr_t *sa) | ||||
| { | ||||
|   char *str; | ||||
|   char address[NI_MAXHOST] = "unknown"; | ||||
|   char port[NI_MAXSERV] = "unknown"; | ||||
|   int err; | ||||
| cp | ||||
|   if((err = getnameinfo(&sa->sa, SALEN(sa->sa), address, sizeof(address), port, sizeof(port), hostnames?0:(NI_NUMERICHOST|NI_NUMERICSERV)))) | ||||
|     { | ||||
|       syslog(LOG_ERR, _("Error while looking up hostname: %s"), gai_strerror(err)); | ||||
|     } | ||||
| 
 | ||||
|   asprintf(&str, _("%s port %s"), address, port); | ||||
| cp | ||||
|   return str; | ||||
| } | ||||
| 
 | ||||
| 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)); | ||||
| 	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 | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /* Subnet mask handling */ | ||||
| 
 | ||||
| int maskcmp(char *a, char *b, int masklen, int len) | ||||
| { | ||||
|   int i, m, result; | ||||
| cp | ||||
|   for(m = masklen, i = 0; m >= 8; m -= 8, i++) | ||||
|     if((result = a[i] - b[i])) | ||||
|       return result; | ||||
| 
 | ||||
|   if(m) | ||||
|     return (a[i] & (0x100 - (m << 1))) - (b[i] & (0x100 - (m << 1))); | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| void mask(char *a, int masklen, int len) | ||||
| { | ||||
|   int i; | ||||
| cp | ||||
|   i = masklen / 8; | ||||
|   masklen %= 8; | ||||
|    | ||||
|   if(masklen) | ||||
|     a[i++] &= (0x100 - (masklen << 1)); | ||||
|    | ||||
|   for(; i < len; i++) | ||||
|     a[i] = 0; | ||||
| } | ||||
| 
 | ||||
| void maskcpy(char *a, char *b, int masklen, int len) | ||||
| { | ||||
|   int i, m; | ||||
| cp | ||||
|   for(m = masklen, i = 0; m >= 8; m -= 8, i++) | ||||
|     a[i] = b[i]; | ||||
| 
 | ||||
|   if(m) | ||||
|     { | ||||
|       a[i] = b[i] & (0x100 - (m << 1)); | ||||
|       i++; | ||||
|     } | ||||
| 
 | ||||
|   for(; i < len; i++) | ||||
|     a[i] = 0; | ||||
| } | ||||
| 
 | ||||
| int maskcheck(char *a, int masklen, int len) | ||||
| { | ||||
|   int i; | ||||
| cp | ||||
|   i = masklen / 8; | ||||
|   masklen %= 8; | ||||
|    | ||||
|   if(masklen) | ||||
|     if(a[i++] & ~(0x100 - (masklen << 1))) | ||||
|       return -1; | ||||
|    | ||||
|   for(; i < len; i++) | ||||
|     if(a[i] != 0) | ||||
|       return -1; | ||||
| 
 | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										46
									
								
								src/pokey/netutl.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/pokey/netutl.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | |||
| /*
 | ||||
|     netutl.h -- header file for netutl.c | ||||
|     Copyright (C) 1998-2002 Ivo Timmermans <zarq@iname.com> | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_NETUTL_H__ | ||||
| #define __TINC_NETUTL_H__ | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| #include <netdb.h> | ||||
| 
 | ||||
| #include "net.h" | ||||
| 
 | ||||
| extern int hostnames; | ||||
| 
 | ||||
| extern char *hostlookup(unsigned long); | ||||
| extern struct addrinfo *str2addrinfo(char *, char *, int); | ||||
| extern sockaddr_t str2sockaddr(char *, char *); | ||||
| extern void sockaddr2str(sockaddr_t *, char **, char **); | ||||
| extern char *sockaddr2hostname(sockaddr_t *); | ||||
| extern int sockaddrcmp(sockaddr_t *, sockaddr_t *); | ||||
| extern void sockaddrunmap(sockaddr_t *); | ||||
| extern int maskcmp(char *, char *, int, int); | ||||
| extern void maskcpy(char *, char *, int, int); | ||||
| extern void mask(char *, int, int); | ||||
| extern int maskcheck(char *, int, int); | ||||
| 
 | ||||
| #endif /* __TINC_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: pokey.c,v 1.2 2002/04/13 11:21:01 zarq Exp $ | ||||
|     $Id: pokey.c,v 1.3 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
|  | @ -323,16 +323,6 @@ main(int argc, char **argv, char **envp) | |||
| 
 | ||||
|   gnome_init("Pokey", "0.0", 1, fake_argv); | ||||
| 
 | ||||
|   glade_init(); | ||||
| 
 | ||||
|   xml = glade_xml_new("pokey.glade", "MainWindow"); | ||||
| 
 | ||||
|   if (!xml) | ||||
|     { | ||||
|       fprintf(stderr, _("Something bad happened while creating the interface.\n")); | ||||
|       exit(1); | ||||
|     } | ||||
| 
 | ||||
|   g_argv = argv; | ||||
| 
 | ||||
|   make_names(); | ||||
|  | @ -356,7 +346,8 @@ cp | |||
| 
 | ||||
|   if(init_interface()) | ||||
|     { | ||||
|       fprintf(stderr, _("Could not setup all necessary interface elements.\n")); | ||||
|       log(0, TLOG_ERROR, | ||||
| 	  _("Could not setup all necessary interface elements.\n")); | ||||
|       exit(1); | ||||
|     } | ||||
|    | ||||
|  | @ -365,9 +356,11 @@ cp | |||
|       main_loop(); | ||||
|       cleanup_and_exit(1); | ||||
|     } | ||||
|        | ||||
|   log(0, LOG_ERR, | ||||
|       _("Unrecoverable error")); | ||||
| 
 | ||||
|   log_add_hook(log_default); | ||||
|    | ||||
|   log(0, TLOG_ERROR, | ||||
|       _("Could not set up network connections")); | ||||
|   cp_trace(); | ||||
| 
 | ||||
|   return 1; | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										56
									
								
								src/pokey/pokey2.xpm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/pokey/pokey2.xpm
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,56 @@ | |||
| /* XPM */ | ||||
| static char * pokey2_xpm[] = { | ||||
| "36 49 4 1", | ||||
| " 	c None", | ||||
| ".	c #000000", | ||||
| "+	c #FFFFFF", | ||||
| "@	c #E9A500", | ||||
| "           ..........               ", | ||||
| "          .............             ", | ||||
| "         ................           ", | ||||
| "         .................          ", | ||||
| "        ..................          ", | ||||
| "        ...................         ", | ||||
| "       .....................        ", | ||||
| "       ........++.............      ", | ||||
| "      .........++..............     ", | ||||
| "     ..+....+..++................   ", | ||||
| "     .++++++...+.................   ", | ||||
| "     ....+.+......................  ", | ||||
| "  ..@@@@@@.++.....................  ", | ||||
| " .@@@@@@@@.+++..................... ", | ||||
| "...........++++.................... ", | ||||
| " .@@@@@@@@.++++.....................", | ||||
| "  .....@@@.++++.....................", | ||||
| "      .....+++++....................", | ||||
| "      .++++++++++...................", | ||||
| "     .++++++++++++..................", | ||||
| "     .++++++++++++..................", | ||||
| "    .+++++++++++++..................", | ||||
| "    .+++++++++++++..................", | ||||
| "    .+++++++++++++................. ", | ||||
| "    .+++++++++++++................. ", | ||||
| "    .+++++++++++++.....+........... ", | ||||
| "    .+++++++++++++.....+........... ", | ||||
| "    .++++++++++++++....+........... ", | ||||
| "    .++++++++++++++................ ", | ||||
| "    .++++++++++++++...+............ ", | ||||
| "    .++++++++++++++...+...........  ", | ||||
| "    .++++++++++++++...+...........  ", | ||||
| "    .++++++++++++++..++...........  ", | ||||
| "    .++++++++++++++++++...........  ", | ||||
| "    .++++++++++++++++++...........  ", | ||||
| "    .++++++++++++++++++..........   ", | ||||
| "     .+++++++++++++++++..........   ", | ||||
| "     .++++++++++++++++...........   ", | ||||
| "     .++++++++++++++++...........   ", | ||||
| "     .++++++++++++++++...........   ", | ||||
| "      .+++++++++++++++...........   ", | ||||
| "       ..+++++++++++.............   ", | ||||
| "       . .++++++++...............   ", | ||||
| "          ..+++++.+.............    ", | ||||
| "           ....+.++............     ", | ||||
| "            ...................     ", | ||||
| "        ....................        ", | ||||
| "        ..............   ..         ", | ||||
| "          . ..                      "}; | ||||
							
								
								
									
										469
									
								
								src/pokey/process.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										469
									
								
								src/pokey/process.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,469 @@ | |||
| /*
 | ||||
|     process.c -- process management functions | ||||
|     Copyright (C) 1999-2002 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <errno.h> | ||||
| #include <fcntl.h> | ||||
| #include <signal.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <syslog.h> | ||||
| #include <sys/ioctl.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/wait.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <termios.h> | ||||
| 
 | ||||
| #include <pidfile.h> | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| #include "interface.h" | ||||
| #include "process.h" | ||||
| #include "subnet.h" | ||||
| #include "connection.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| /* If zero, don't detach from the terminal. */ | ||||
| int do_detach = 1; | ||||
| 
 | ||||
| extern char *identname; | ||||
| extern char *pidfilename; | ||||
| extern char **g_argv; | ||||
| 
 | ||||
| sigset_t emptysigset; | ||||
| 
 | ||||
| static int saved_debug_lvl = 0; | ||||
| 
 | ||||
| extern int sighup; | ||||
| extern int sigalrm; | ||||
| extern int do_purge; | ||||
| 
 | ||||
| void memory_full(int size) | ||||
| { | ||||
|   log(0, TLOG_ERROR, | ||||
|       _("Memory exhausted (couldn't allocate %d bytes), exitting."), | ||||
|       size); | ||||
|   cp_trace(); | ||||
|   exit(1); | ||||
| } | ||||
| 
 | ||||
| /* Some functions the less gifted operating systems might lack... */ | ||||
| 
 | ||||
| #ifndef HAVE_FCLOSEALL | ||||
| int fcloseall(void) | ||||
| { | ||||
|   fflush(stdin); | ||||
|   fflush(stdout); | ||||
|   fflush(stderr); | ||||
|   fclose(stdin); | ||||
|   fclose(stdout); | ||||
|   fclose(stderr); | ||||
|   return 0; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|   Close network connections, and terminate neatly | ||||
| */ | ||||
| void cleanup_and_exit(int c) | ||||
| { | ||||
| cp | ||||
|   close_network_connections(); | ||||
| 
 | ||||
|   syslog(LOG_NOTICE, _("Terminating")); | ||||
| 
 | ||||
|   closelog(); | ||||
|   exit(c); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   check for an existing tinc for this net, and write pid to pidfile | ||||
| */ | ||||
| int write_pidfile(void) | ||||
| { | ||||
|   int pid; | ||||
| cp | ||||
|   if((pid = check_pid(pidfilename))) | ||||
|     { | ||||
|       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; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   kill older tincd for this net | ||||
| */ | ||||
| int kill_other(int signal) | ||||
| { | ||||
|   int pid; | ||||
| cp | ||||
|   if(!(pid = read_pid(pidfilename))) | ||||
|     { | ||||
|       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; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   Detach from current terminal, write pidfile, kill parent | ||||
| */ | ||||
| int detach(void) | ||||
| { | ||||
| cp | ||||
|   setup_signals(); | ||||
| 
 | ||||
|   /* First check if we can open a fresh new pidfile */ | ||||
|    | ||||
|   if(write_pidfile()) | ||||
|     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; | ||||
|     } | ||||
|    | ||||
|   openlog(identname, LOG_CONS | LOG_PID, LOG_DAEMON); | ||||
| 
 | ||||
|   if(debug_lvl > DEBUG_NOTHING) | ||||
|     log(0, TLOG_NOTICE, | ||||
| 	_("tincd %s (%s %s) starting, debug level %d"), | ||||
| 	VERSION, __DATE__, __TIME__, debug_lvl); | ||||
|   else | ||||
|     log(DEBUG_NOTHING, TLOG_NOTICE, | ||||
| 	_("tincd %s starting"), | ||||
| 	VERSION); | ||||
| 
 | ||||
|   xalloc_fail_func = memory_full; | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   Execute the program name, with sane environment.  All output will be | ||||
|   redirected to syslog. | ||||
| */ | ||||
| void _execute_script(const char *name)  __attribute__ ((noreturn)); | ||||
| void _execute_script(const char *name) | ||||
| { | ||||
|   char *scriptname; | ||||
|   char *s; | ||||
| cp | ||||
| #ifdef HAVE_UNSETENV | ||||
|   unsetenv("NETNAME"); | ||||
|   unsetenv("INTERFACE"); | ||||
| #endif | ||||
| 
 | ||||
|   if(netname) | ||||
|     { | ||||
|       asprintf(&s, "NETNAME=%s", netname); | ||||
|       putenv(s);	/* Don't free s! see man 3 putenv */ | ||||
|     } | ||||
| 
 | ||||
|   chdir("/"); | ||||
|    | ||||
|   asprintf(&scriptname, "%s/%s", confbase, name); | ||||
| 
 | ||||
|   /* Close all file descriptors */ | ||||
|   closelog();		/* <- this means we cannot use syslog() here anymore! */ | ||||
|   fcloseall(); | ||||
| 
 | ||||
|   execl(scriptname, NULL); | ||||
|   /* No return on success */ | ||||
|    | ||||
|   if(errno != ENOENT)	/* Ignore if the file does not exist */ | ||||
|     exit(1);		/* Some error while trying execl(). */ | ||||
|   else | ||||
|     exit(0); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|   Fork and execute the program pointed to by name. | ||||
| */ | ||||
| int execute_script(const char *name) | ||||
| { | ||||
|   pid_t pid; | ||||
|   int status; | ||||
| cp | ||||
|   if((pid = fork()) < 0) | ||||
|     { | ||||
|       syslog(LOG_ERR, _("System call `%s' failed: %s"), "fork", strerror(errno)); | ||||
|       return -1; | ||||
|     } | ||||
| 
 | ||||
|   if(pid) | ||||
|     { | ||||
|       log(DEBUG_STATUS, TLOG_INFO, | ||||
| 	  _("Executing script %s"), | ||||
| 	  name); | ||||
| 
 | ||||
|       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(name); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|   Signal handlers. | ||||
| */ | ||||
| 
 | ||||
| RETSIGTYPE | ||||
| sigterm_handler(int a) | ||||
| { | ||||
|   log(DEBUG_NOTHING, TLOG_NOTICE, | ||||
|       _("Got TERM signal")); | ||||
| 
 | ||||
|   cleanup_and_exit(0); | ||||
| } | ||||
| 
 | ||||
| RETSIGTYPE | ||||
| sigquit_handler(int a) | ||||
| { | ||||
|   log(DEBUG_NOTHING, TLOG_NOTICE, | ||||
|       _("Got QUIT signal")); | ||||
|   cleanup_and_exit(0); | ||||
| } | ||||
| 
 | ||||
| RETSIGTYPE | ||||
| fatal_signal_square(int a) | ||||
| { | ||||
|   syslog(LOG_ERR, _("Got another fatal signal %d (%s): not restarting."), a, strsignal(a)); | ||||
|   cp_trace(); | ||||
|   exit(1); | ||||
| } | ||||
| 
 | ||||
| RETSIGTYPE | ||||
| fatal_signal_handler(int a) | ||||
| { | ||||
|   syslog(LOG_ERR, _("Got fatal signal %d (%s)"), a, strsignal(a)); | ||||
|   cp_trace(); | ||||
| 
 | ||||
|   syslog(LOG_NOTICE, _("Not restarting.")); | ||||
|   exit(1); | ||||
| } | ||||
| 
 | ||||
| RETSIGTYPE | ||||
| sighup_handler(int a) | ||||
| { | ||||
|   if(debug_lvl > DEBUG_NOTHING) | ||||
|     syslog(LOG_NOTICE, _("Got HUP signal")); | ||||
|   sighup = 1; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| RETSIGTYPE | ||||
| sigalrm_handler(int a) | ||||
| { | ||||
|   if(debug_lvl > DEBUG_NOTHING) | ||||
|     syslog(LOG_NOTICE, _("Got ALRM signal")); | ||||
|   sigalrm = 1; | ||||
| } | ||||
| 
 | ||||
| RETSIGTYPE | ||||
| sigusr1_handler(int a) | ||||
| { | ||||
|   dump_connections(); | ||||
| } | ||||
| 
 | ||||
| RETSIGTYPE | ||||
| sigusr2_handler(int a) | ||||
| { | ||||
|   dump_nodes(); | ||||
|   dump_edges(); | ||||
|   dump_subnets(); | ||||
| } | ||||
| 
 | ||||
| RETSIGTYPE | ||||
| sigwinch_handler(int a) | ||||
| { | ||||
|   extern int do_purge; | ||||
|   do_purge = 1; | ||||
| } | ||||
| 
 | ||||
| RETSIGTYPE | ||||
| unexpected_signal_handler(int a) | ||||
| { | ||||
|   syslog(LOG_WARNING, _("Got unexpected signal %d (%s)"), a, strsignal(a)); | ||||
|   cp_trace(); | ||||
| } | ||||
| 
 | ||||
| RETSIGTYPE | ||||
| ignore_signal_handler(int a) | ||||
| { | ||||
|   if(debug_lvl >= DEBUG_SCARY_THINGS) | ||||
|   { | ||||
|     syslog(LOG_DEBUG, _("Ignored signal %d (%s)"), a, strsignal(a)); | ||||
|     cp_trace(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| struct { | ||||
|   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 } | ||||
| }; | ||||
| 
 | ||||
| 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)); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										36
									
								
								src/pokey/process.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/pokey/process.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | |||
| /*
 | ||||
|     process.h -- header file for process.c | ||||
|     Copyright (C) 1999-2002 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_PROCESS_H__ | ||||
| #define __TINC_PROCESS_H__ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| extern int do_detach; | ||||
| 
 | ||||
| extern void setup_signals(void); | ||||
| extern int execute_script(const char *); | ||||
| extern int detach(void); | ||||
| extern int kill_other(int); | ||||
| extern void cleanup_and_exit(int); | ||||
| 
 | ||||
| #endif /* __TINC_PROCESS_H__ */ | ||||
							
								
								
									
										245
									
								
								src/pokey/protocol.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								src/pokey/protocol.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,245 @@ | |||
| /*
 | ||||
|     protocol.c -- handle the meta-protocol, basic functions | ||||
|     Copyright (C) 1999-2001 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000,2001 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <sys/types.h> | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| #include "protocol.h" | ||||
| #include "meta.h" | ||||
| #include "connection.h" | ||||
| #include "interface.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| avl_tree_t *past_request_tree; | ||||
| 
 | ||||
| int check_id(char *id) | ||||
| { | ||||
|   int i; | ||||
| 
 | ||||
|   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, ...) | ||||
| { | ||||
|   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 | ||||
|   return send_meta(c, buffer, len); | ||||
| } | ||||
| 
 | ||||
| int receive_request(connection_t *c) | ||||
| { | ||||
|   int request; | ||||
| cp | ||||
|   if(sscanf(c->buffer, "%d", &request) == 1) | ||||
|     { | ||||
|       if((request < 0) || (request >= LAST) || (request_handlers[request] == NULL)) | ||||
|         { | ||||
|           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; | ||||
|     } | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| int past_request_compare(past_request_t *a, past_request_t *b) | ||||
| { | ||||
| cp | ||||
|   return strcmp(a->request, b->request); | ||||
| } | ||||
| 
 | ||||
| void free_past_request(past_request_t *r) | ||||
| { | ||||
| cp | ||||
|   if(r->request) | ||||
|     free(r->request); | ||||
|   free(r); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| void init_requests(void) | ||||
| { | ||||
| cp | ||||
|   past_request_tree = avl_alloc_tree((avl_compare_t)past_request_compare, (avl_action_t)free_past_request); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| void exit_requests(void) | ||||
| { | ||||
| cp | ||||
|   avl_delete_tree(past_request_tree); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| 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   | ||||
| } | ||||
| 
 | ||||
| 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 | ||||
| } | ||||
| 
 | ||||
| /* 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_node_h, del_node_h,
 | ||||
|   add_subnet_h, del_subnet_h, | ||||
|   add_edge_h, del_edge_h, | ||||
|   key_changed_h, req_key_h, ans_key_h, | ||||
| }; | ||||
| 
 | ||||
| /* Request names */ | ||||
| 
 | ||||
| char (*request_name[]) = { | ||||
|   "ID", "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", | ||||
| }; | ||||
							
								
								
									
										120
									
								
								src/pokey/protocol.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/pokey/protocol.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,120 @@ | |||
| /*
 | ||||
|     protocol.h -- header for protocol.c | ||||
|     Copyright (C) 1999-2001 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000,2001 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_PROTOCOL_H__ | ||||
| #define __TINC_PROTOCOL_H__ | ||||
| 
 | ||||
| #include "net.h" | ||||
| #include "node.h" | ||||
| #include "subnet.h" | ||||
| 
 | ||||
| /* Protocol version. Different versions are incompatible,
 | ||||
|    incompatible version have different protocols. | ||||
|  */ | ||||
| 
 | ||||
| #define PROT_CURRENT 14 | ||||
| 
 | ||||
| /* 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 */ | ||||
| }; | ||||
| 
 | ||||
| typedef struct past_request_t { | ||||
|   char *request; | ||||
|   time_t firstseen; | ||||
| } past_request_t; | ||||
| 
 | ||||
| /* Maximum size of strings in a request */ | ||||
| 
 | ||||
| #define MAX_STRING_SIZE 2048 | ||||
| #define MAX_STRING "%2048s" | ||||
| 
 | ||||
| /* Basic functions */ | ||||
| 
 | ||||
| extern int send_request(connection_t*, const char*, ...); | ||||
| extern int receive_request(connection_t *); | ||||
| extern int check_id(char *); | ||||
| 
 | ||||
| extern void init_requests(void); | ||||
| extern void exit_requests(void); | ||||
| extern int seen_request(char *); | ||||
| extern void age_past_requests(void); | ||||
| 
 | ||||
| /* Requests */ | ||||
| 
 | ||||
| extern int send_id(connection_t *); | ||||
| extern int send_metakey(connection_t *); | ||||
| extern int send_challenge(connection_t *); | ||||
| extern int send_chal_reply(connection_t *); | ||||
| extern int send_ack(connection_t *); | ||||
| extern int send_status(connection_t *, int, char *); | ||||
| 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 *); | ||||
| extern int send_del_edge(connection_t *, edge_t *); | ||||
| extern int send_key_changed(connection_t *, node_t *); | ||||
| extern int send_req_key(connection_t *, node_t *, node_t *); | ||||
| extern int send_ans_key(connection_t *, node_t *, node_t *); | ||||
| extern int send_tcppacket(connection_t *, vpn_packet_t *); | ||||
| 
 | ||||
| /* Request handlers  */ | ||||
| 
 | ||||
| extern int (*request_handlers[])(connection_t *); | ||||
| 
 | ||||
| extern int id_h(connection_t *); | ||||
| extern int metakey_h(connection_t *); | ||||
| extern int challenge_h(connection_t *); | ||||
| extern int chal_reply_h(connection_t *); | ||||
| extern int ack_h(connection_t *); | ||||
| extern int status_h(connection_t *); | ||||
| 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 *); | ||||
| extern int del_edge_h(connection_t *); | ||||
| extern int key_changed_h(connection_t *); | ||||
| extern int req_key_h(connection_t *); | ||||
| extern int ans_key_h(connection_t *); | ||||
| extern int tcppacket_h(connection_t *); | ||||
| 
 | ||||
| #endif /* __TINC_PROTOCOL_H__ */ | ||||
							
								
								
									
										609
									
								
								src/pokey/protocol_auth.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										609
									
								
								src/pokey/protocol_auth.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,609 @@ | |||
| /*
 | ||||
|     protocol_auth.c -- handle the meta-protocol, authentication | ||||
|     Copyright (C) 1999-2002 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| #include <avl_tree.h> | ||||
| 
 | ||||
| #include <openssl/sha.h> | ||||
| #include <openssl/rand.h> | ||||
| #include <openssl/evp.h> | ||||
| 
 | ||||
| #ifndef HAVE_RAND_PSEUDO_BYTES | ||||
| #define RAND_pseudo_bytes RAND_bytes | ||||
| #endif | ||||
| 
 | ||||
| #include "conf.h" | ||||
| #include "interface.h" | ||||
| #include "net.h" | ||||
| #include "netutl.h" | ||||
| #include "protocol.h" | ||||
| #include "meta.h" | ||||
| #include "connection.h" | ||||
| #include "node.h" | ||||
| #include "edge.h" | ||||
| #include "graph.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| int send_id(connection_t *c) | ||||
| { | ||||
| cp | ||||
|   return send_request(c, "%d %s %d", ID, myself->connection->name, myself->connection->protocol_version); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| 
 | ||||
|       if((bla = read_connection_config(c))) | ||||
|         { | ||||
|           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); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| 	} | ||||
| 
 | ||||
|       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; | ||||
| 	} | ||||
|        | ||||
|       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; | ||||
|     } | ||||
| 
 | ||||
|   c->incompression = compression; | ||||
| 
 | ||||
|   c->allow_request = CHALLENGE; | ||||
| cp | ||||
|   return send_challenge(c); | ||||
| } | ||||
| 
 | ||||
| int send_challenge(connection_t *c) | ||||
| { | ||||
|   char buffer[MAX_STRING_SIZE]; | ||||
|   int len, x; | ||||
| cp | ||||
|   /* CHECKME: what is most reasonable value for len? */ | ||||
| 
 | ||||
|   len = RSA_size(c->rsa_key); | ||||
| 
 | ||||
|   /* Allocate buffers for the challenge */ | ||||
| 
 | ||||
|   if(!c->hischallenge) | ||||
|     c->hischallenge = xmalloc(len); | ||||
| cp | ||||
|   /* Copy random data to the buffer */ | ||||
| 
 | ||||
|   RAND_bytes(c->hischallenge, len); | ||||
| 
 | ||||
| cp | ||||
|   /* Convert to hex */ | ||||
| 
 | ||||
|   bin2hex(c->hischallenge, buffer, len); | ||||
|   buffer[len*2] = '\0'; | ||||
| 
 | ||||
| cp | ||||
|   /* Send the challenge */ | ||||
| 
 | ||||
|   x = send_request(c, "%d %s", CHALLENGE, buffer); | ||||
| cp | ||||
|   return x; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|     } | ||||
| 
 | ||||
|   len = RSA_size(myself->connection->rsa_key); | ||||
| 
 | ||||
|   /* 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 */ | ||||
| 
 | ||||
|   if(!c->mychallenge) | ||||
|     c->mychallenge = xmalloc(len); | ||||
| 
 | ||||
|   /* Convert the challenge from hexadecimal back to binary */ | ||||
| 
 | ||||
|   hex2bin(buffer,c->mychallenge,len); | ||||
| 
 | ||||
|   c->allow_request = CHAL_REPLY; | ||||
| 
 | ||||
|   /* Rest is done by send_chal_reply() */ | ||||
| cp | ||||
|   return send_chal_reply(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 */ | ||||
| 
 | ||||
|   EVP_DigestInit(&ctx, c->indigest); | ||||
|   EVP_DigestUpdate(&ctx, c->mychallenge, RSA_size(myself->connection->rsa_key)); | ||||
|   EVP_DigestFinal(&ctx, hash, NULL); | ||||
| 
 | ||||
|   /* Convert the hash to a hexadecimal formatted string */ | ||||
| 
 | ||||
|   bin2hex(hash,hash,c->indigest->md_size); | ||||
|   hash[c->indigest->md_size*2] = '\0'; | ||||
| 
 | ||||
|   /* Send the reply */ | ||||
| 
 | ||||
| cp | ||||
|   return send_request(c, "%d %s", CHAL_REPLY, hash); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|   char *address, *port; | ||||
|   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; | ||||
|   sockaddr2str(&c->address, &address, &port); | ||||
|   x = send_request(c, "%d %s %s %d %lx", ACK, myport, address, c->estimated_weight, c->options); | ||||
|   free(address); | ||||
|   free(port); | ||||
| cp | ||||
|   return x; | ||||
| } | ||||
| 
 | ||||
| void send_everything(connection_t *c) | ||||
| { | ||||
|   avl_node_t *node, *node2; | ||||
|   node_t *n; | ||||
|   subnet_t *s; | ||||
|   edge_t *e; | ||||
| 
 | ||||
|   /* Send all known subnets */ | ||||
|    | ||||
|   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); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|   /* Send all known edges */ | ||||
| 
 | ||||
|   for(node = edge_tree->head; node; node = node->next) | ||||
|     { | ||||
|       e = (edge_t *)node->data; | ||||
| 
 | ||||
|       if(e == c->edge) | ||||
|         continue; | ||||
| 
 | ||||
|       send_add_edge(c, e); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int ack_h(connection_t *c) | ||||
| { | ||||
|   char myaddress[MAX_STRING_SIZE]; | ||||
|   char hisport[MAX_STRING_SIZE]; | ||||
|   char *hisaddress, *dummy; | ||||
|   int weight; | ||||
|   long int options; | ||||
|   node_t *n; | ||||
|   connection_t *other; | ||||
|   avl_node_t *node; | ||||
| cp | ||||
|   if(sscanf(c->buffer, "%*d "MAX_STRING" "MAX_STRING" %d %lx", hisport, myaddress, &weight, &options) != 4) | ||||
|     { | ||||
|        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. */ | ||||
| 	  log(DEBUG_CONNECTIONS, TLOG_DEBUG, | ||||
| 	      _("Established a second connection with %s (%s), closing old connection"), | ||||
| 	      n->name, n->hostname); | ||||
|           terminate_connection(n->connection, 0); | ||||
|         } | ||||
|            | ||||
|       /* FIXME: check if information in existing node matches that of the other end of this connection */ | ||||
|     } | ||||
|    | ||||
|   n->connection = c; | ||||
|   c->node = n; | ||||
|   c->options |= options; | ||||
| 
 | ||||
|   /* Create an edge_t for this connection */ | ||||
| 
 | ||||
|   c->edge = new_edge(); | ||||
| cp   | ||||
|   c->edge->from.node = myself; | ||||
| //  c->edge->from.tcpaddress = str2sockaddr(address, port);
 | ||||
|   c->edge->from.udpaddress = str2sockaddr(myaddress, myport); | ||||
|   c->edge->to.node = n; | ||||
| //  c->edge->to.tcpaddress = c->address;
 | ||||
|   sockaddr2str(&c->address, &hisaddress, &dummy); | ||||
|   c->edge->to.udpaddress = 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); | ||||
| 
 | ||||
|   /* 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); | ||||
| 
 | ||||
| cp | ||||
|   /* Send him everything we know */ | ||||
| 
 | ||||
|   send_everything(c); | ||||
| 
 | ||||
|   /* Notify others of this connection */ | ||||
| 
 | ||||
|   for(node = connection_tree->head; node; node = node->next) | ||||
|     { | ||||
|       other = (connection_t *)node->data; | ||||
| 
 | ||||
|       if(other->status.active && other != c) | ||||
|         send_add_edge(other, c->edge); | ||||
|     } | ||||
| 
 | ||||
|   /* Run MST and SSSP algorithms */ | ||||
|   | ||||
|   graph(); | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										311
									
								
								src/pokey/protocol_edge.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										311
									
								
								src/pokey/protocol_edge.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,311 @@ | |||
| /*
 | ||||
|     protocol_edge.c -- handle the meta-protocol, edges | ||||
|     Copyright (C) 1999-2002 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| #include <avl_tree.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| #include "interface.h" | ||||
| #include "net.h" | ||||
| #include "netutl.h" | ||||
| #include "protocol.h" | ||||
| #include "meta.h" | ||||
| #include "connection.h" | ||||
| #include "node.h" | ||||
| #include "edge.h" | ||||
| #include "graph.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| int send_add_edge(connection_t *c, edge_t *e) | ||||
| { | ||||
|   int x; | ||||
|   char *from_udpaddress, *from_udpport; | ||||
|   char *to_udpaddress, *to_udpport; | ||||
| cp | ||||
| //  sockaddr2str(&e->from.tcpaddress, &from_tcpaddress, &from_tcpport);
 | ||||
|   sockaddr2str(&e->from.udpaddress, &from_udpaddress, &from_udpport); | ||||
| //  sockaddr2str(&e->to.tcpaddress, &to_tcpaddress, &to_tcpport);
 | ||||
|   sockaddr2str(&e->to.udpaddress, &to_udpaddress, &to_udpport); | ||||
|   x = send_request(c, "%d %lx %s %s %s %s %s %s %lx %d", ADD_EDGE, random(), | ||||
|                       e->from.node->name, from_udpaddress, from_udpport, | ||||
| 		      e->to.node->name, to_udpaddress, to_udpport, | ||||
| 		      e->options, e->weight); | ||||
| //  free(from_tcpaddress);
 | ||||
| //  free(from_tcpport);
 | ||||
|   free(from_udpaddress); | ||||
|   free(from_udpport); | ||||
| //  free(to_tcpaddress);
 | ||||
| //  free(to_tcpport);
 | ||||
|   free(to_udpaddress); | ||||
|   free(to_udpport); | ||||
| cp | ||||
|   return x; | ||||
| } | ||||
| 
 | ||||
| int add_edge_h(connection_t *c) | ||||
| { | ||||
|   connection_t *other; | ||||
|   edge_t *e; | ||||
|   node_t *from, *to; | ||||
|   char from_name[MAX_STRING_SIZE]; | ||||
|   char to_name[MAX_STRING_SIZE]; | ||||
|   char from_address[MAX_STRING_SIZE]; | ||||
| //  char from_tcpport[MAX_STRING_SIZE];
 | ||||
|   char from_udpport[MAX_STRING_SIZE]; | ||||
|   char to_address[MAX_STRING_SIZE]; | ||||
| //  char to_tcpport[MAX_STRING_SIZE];
 | ||||
|   char to_udpport[MAX_STRING_SIZE]; | ||||
|   sockaddr_t from_udpaddress; | ||||
|   sockaddr_t to_udpaddress; | ||||
|   long int options; | ||||
|   int weight; | ||||
|   avl_node_t *node; | ||||
| cp | ||||
|   if(sscanf(c->buffer, "%*d %*x "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" "MAX_STRING" %lx %d", | ||||
|             from_name, from_address, from_udpport, | ||||
| 	    to_name, to_address, to_udpport, | ||||
| 	    &options, &weight) != 8) | ||||
|     { | ||||
|       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 */ | ||||
|    | ||||
| //  from_tcpaddress = str2sockaddr(from_address, from_tcpport);
 | ||||
|   from_udpaddress = str2sockaddr(from_address, from_udpport); | ||||
| //  to_tcpaddress = str2sockaddr(to_address, to_tcpport);
 | ||||
|   to_udpaddress = str2sockaddr(to_address, to_udpport); | ||||
| 
 | ||||
|   /* Check if edge already exists */ | ||||
|    | ||||
|   e = lookup_edge(from, to); | ||||
|    | ||||
|   if(e) | ||||
|   { | ||||
|     if(e->weight != weight || e->options != options | ||||
|        || ((e->from.node == from) && (sockaddrcmp(&e->from.udpaddress, &from_udpaddress)|| sockaddrcmp(&e->to.udpaddress, &to_udpaddress))) | ||||
|        || ((e->from.node == to) && (sockaddrcmp(&e->from.udpaddress, &to_udpaddress) || sockaddrcmp(&e->to.udpaddress, &from_udpaddress))) | ||||
|       ) | ||||
|     { | ||||
|       if(from == myself || to == 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 || to == 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.node = from; | ||||
|     e->to.node = to; | ||||
|     send_del_edge(c, e); | ||||
|     free_edge(e); | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   e = new_edge(); | ||||
|   e->from.node = from; | ||||
| //  e->from.tcpaddress = from_tcpaddress;
 | ||||
|   e->from.udpaddress = from_udpaddress; | ||||
|   e->to.node = to; | ||||
| //  e->to.tcpaddress = to_tcpaddress;
 | ||||
|   e->to.udpaddress = to_udpaddress; | ||||
|   e->options = options; | ||||
|   e->weight = weight; | ||||
|   edge_add(e); | ||||
| 
 | ||||
|   /* Tell the rest about the new edge */ | ||||
| 
 | ||||
|   for(node = connection_tree->head; node; node = node->next) | ||||
|     { | ||||
|       other = (connection_t *)node->data; | ||||
|       if(other->status.active && other != c) | ||||
|         send_request(other, "%s", c->buffer); | ||||
|     } | ||||
| 
 | ||||
|   /* Run MST before or after we tell the rest? */ | ||||
| 
 | ||||
|   graph(); | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| int send_del_edge(connection_t *c, edge_t *e) | ||||
| { | ||||
| cp | ||||
|   return send_request(c, "%d %lx %s %s", DEL_EDGE, random(), | ||||
|                       e->from.node->name, e->to.node->name); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|   connection_t *other; | ||||
|   avl_node_t *node; | ||||
| 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.node == myself || e->to.node == 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 */ | ||||
| 
 | ||||
|   for(node = connection_tree->head; node; node = node->next) | ||||
|     { | ||||
|       other = (connection_t *)node->data; | ||||
|       if(other->status.active && other != c) | ||||
|         send_request(other, "%s", c->buffer); | ||||
|     } | ||||
| 
 | ||||
|   /* Delete the edge */ | ||||
|    | ||||
|   edge_del(e); | ||||
| 
 | ||||
|   /* Run MST before or after we tell the rest? */ | ||||
| 
 | ||||
|   graph(); | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										285
									
								
								src/pokey/protocol_key.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										285
									
								
								src/pokey/protocol_key.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,285 @@ | |||
| /*
 | ||||
|     protocol_key.c -- handle the meta-protocol, key exchange | ||||
|     Copyright (C) 1999-2002 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| #include <avl_tree.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| #include "interface.h" | ||||
| #include "net.h" | ||||
| #include "netutl.h" | ||||
| #include "protocol.h" | ||||
| #include "meta.h" | ||||
| #include "connection.h" | ||||
| #include "node.h" | ||||
| #include "edge.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| int mykeyused = 0; | ||||
| 
 | ||||
| int send_key_changed(connection_t *c, node_t *n) | ||||
| { | ||||
|   connection_t *other; | ||||
|   avl_node_t *node; | ||||
| 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; | ||||
| 
 | ||||
|   for(node = connection_tree->head; node; node = node->next) | ||||
|     { | ||||
|       other = (connection_t *)node->data; | ||||
|       if(other->status.active && other != c) | ||||
|         send_request(other, "%d %lx %s", KEY_CHANGED, random(), n->name); | ||||
|     } | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| int key_changed_h(connection_t *c) | ||||
| { | ||||
|   char name[MAX_STRING_SIZE]; | ||||
|   avl_node_t *node; | ||||
|   connection_t *other; | ||||
|   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; | ||||
|   n->sent_seqno = 0; | ||||
| 
 | ||||
|   /* Tell the others */ | ||||
| 
 | ||||
|   for(node = connection_tree->head; node; node = node->next) | ||||
|     { | ||||
|       other = (connection_t *)node->data; | ||||
|       if(other->status.active && other != c) | ||||
|         send_request(other, "%s", c->buffer); | ||||
|     } | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
|     } | ||||
| 
 | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
|    | ||||
|   /* 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; | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										182
									
								
								src/pokey/protocol_misc.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								src/pokey/protocol_misc.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,182 @@ | |||
| /*
 | ||||
|     protocol_misc.c -- handle the meta-protocol, miscellaneous functions | ||||
|     Copyright (C) 1999-2002 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include <utils.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| #include "interface.h" | ||||
| #include "net.h" | ||||
| #include "netutl.h" | ||||
| #include "protocol.h" | ||||
| #include "meta.h" | ||||
| #include "connection.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| /* Status and error notification routines */ | ||||
| 
 | ||||
| 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); | ||||
| } | ||||
| 
 | ||||
| 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 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); | ||||
| } | ||||
| 
 | ||||
| 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 send_termreq(connection_t *c) | ||||
| { | ||||
| cp | ||||
|   return send_request(c, "%d", TERMREQ); | ||||
| } | ||||
| 
 | ||||
| int termreq_h(connection_t *c) | ||||
| { | ||||
| cp | ||||
|   terminate_connection(c, c->status.active); | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| int send_ping(connection_t *c) | ||||
| { | ||||
| cp | ||||
|   c->status.pinged = 1; | ||||
|   c->last_ping_time = now; | ||||
| cp | ||||
|   return send_request(c, "%d", PING); | ||||
| } | ||||
| 
 | ||||
| int ping_h(connection_t *c) | ||||
| { | ||||
| cp | ||||
|   return send_pong(c); | ||||
| } | ||||
| 
 | ||||
| int send_pong(connection_t *c) | ||||
| { | ||||
| cp | ||||
|   return send_request(c, "%d", PONG); | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| /* Sending and receiving packets via TCP */ | ||||
| 
 | ||||
| int send_tcppacket(connection_t *c, vpn_packet_t *packet) | ||||
| { | ||||
|   int x; | ||||
| cp   | ||||
|   /* Evil hack. */ | ||||
| 
 | ||||
|   x = send_request(c, "%d %hd", PACKET, packet->len); | ||||
| 
 | ||||
|   if(x) | ||||
|     return x; | ||||
| cp | ||||
|   return send_meta(c, packet->data, packet->len); | ||||
| } | ||||
| 
 | ||||
| /* Status strings */ | ||||
| 
 | ||||
| char (*status_text[]) = { | ||||
|   "Warning", | ||||
| }; | ||||
| 
 | ||||
| /* Error strings */ | ||||
| 
 | ||||
| char (*error_text[]) = { | ||||
|   "Error", | ||||
| }; | ||||
							
								
								
									
										238
									
								
								src/pokey/protocol_subnet.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										238
									
								
								src/pokey/protocol_subnet.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,238 @@ | |||
| /*
 | ||||
|     protocol_subnet.c -- handle the meta-protocol, subnets | ||||
|     Copyright (C) 1999-2002 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| #include <avl_tree.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| #include "interface.h" | ||||
| #include "net.h" | ||||
| #include "netutl.h" | ||||
| #include "protocol.h" | ||||
| #include "meta.h" | ||||
| #include "connection.h" | ||||
| #include "node.h" | ||||
| #include "edge.h" | ||||
| #include "graph.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| 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 add_subnet_h(connection_t *c) | ||||
| { | ||||
|   char subnetstr[MAX_STRING_SIZE]; | ||||
|   char name[MAX_STRING_SIZE]; | ||||
|   node_t *owner; | ||||
|   connection_t *other; | ||||
|   subnet_t *s; | ||||
|   avl_node_t *node; | ||||
| 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 */ | ||||
| 
 | ||||
|   if(!(s = str2net(subnetstr))) | ||||
|     { | ||||
|       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 */ | ||||
|    | ||||
|   for(node = connection_tree->head; node; node = node->next) | ||||
|     { | ||||
|       other = (connection_t *)node->data; | ||||
|       if(other->status.active && other != c) | ||||
|         send_request(other, "%s", c->buffer); | ||||
|     } | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| 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 del_subnet_h(connection_t *c) | ||||
| { | ||||
|   char subnetstr[MAX_STRING_SIZE]; | ||||
|   char name[MAX_STRING_SIZE]; | ||||
|   node_t *owner; | ||||
|   connection_t *other; | ||||
|   subnet_t *s, *find; | ||||
|   avl_node_t *node; | ||||
| 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 */ | ||||
| 
 | ||||
|   if(!(owner = lookup_node(name))) | ||||
|     { | ||||
|       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 */ | ||||
| 
 | ||||
|   if(!(s = str2net(subnetstr))) | ||||
|     { | ||||
|       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 */ | ||||
|    | ||||
|   for(node = connection_tree->head; node; node = node->next) | ||||
|     { | ||||
|       other = (connection_t *)node->data; | ||||
|       if(other->status.active && other != c) | ||||
|         send_request(other, "%s", c->buffer); | ||||
|     } | ||||
| 
 | ||||
|   /* Finally, delete it. */ | ||||
| 
 | ||||
|   subnet_del(owner, find); | ||||
| 
 | ||||
| cp | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										377
									
								
								src/pokey/route.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										377
									
								
								src/pokey/route.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,377 @@ | |||
| /*
 | ||||
|     route.c -- routing | ||||
|     Copyright (C) 2000-2002 Ivo Timmermans <itimmermans@bigfoot.com>, | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #if defined(HAVE_FREEBSD) || defined(HAVE_OPENBSD) | ||||
|  #include <sys/param.h> | ||||
| #endif | ||||
| #include <sys/socket.h> | ||||
| #include <netinet/in.h> | ||||
| #if defined(HAVE_SOLARIS) || defined(HAVE_OPENBSD) | ||||
|  #include <net/if.h> | ||||
|  #define ETHER_ADDR_LEN 6 | ||||
| #else | ||||
|  #include <net/ethernet.h> | ||||
| #endif | ||||
| #include <netinet/ip6.h> | ||||
| #include <netinet/icmp6.h> | ||||
| #include <netinet/if_ether.h> | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include <avl_tree.h> | ||||
| 
 | ||||
| #include "net.h" | ||||
| #include "interface.h" | ||||
| #include "connection.h" | ||||
| #include "subnet.h" | ||||
| #include "route.h" | ||||
| #include "protocol.h" | ||||
| #include "device.h" | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| int routing_mode = RMODE_ROUTER; | ||||
| int priorityinheritance = 0; | ||||
| int macexpire = 600; | ||||
| subnet_t mymac; | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| 	} | ||||
|     } | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| 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;   | ||||
| } | ||||
| 
 | ||||
| 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(*(short unsigned int *)&packet->data[38]), | ||||
| 	    ntohs(*(short unsigned int *)&packet->data[40]), | ||||
| 	    ntohs(*(short unsigned int *)&packet->data[42]), | ||||
| 	    ntohs(*(short unsigned int *)&packet->data[44]), | ||||
| 	    ntohs(*(short unsigned int *)&packet->data[46]), | ||||
| 	    ntohs(*(short unsigned int *)&packet->data[48]), | ||||
| 	    ntohs(*(short unsigned int *)&packet->data[50]), | ||||
| 	    ntohs(*(short unsigned int *)&packet->data[52])); | ||||
|         } | ||||
| 
 | ||||
|       return NULL; | ||||
|     } | ||||
| cp | ||||
|   return subnet->owner;   | ||||
| } | ||||
| 
 | ||||
| unsigned short int inet_checksum(unsigned short int *data, int len, unsigned short int prevsum) | ||||
| { | ||||
|   unsigned long int checksum = prevsum ^ 0xFFFF; | ||||
| 
 | ||||
|   while(len--) | ||||
|     checksum += ntohs(*data++); | ||||
| 
 | ||||
|   while(checksum >> 16) | ||||
|     checksum = (checksum & 0xFFFF) + (checksum >> 16); | ||||
| 
 | ||||
|   return checksum ^ 0xFFFF; | ||||
| } | ||||
| 
 | ||||
| void route_neighborsol(vpn_packet_t *packet) | ||||
| { | ||||
|   struct ip6_hdr *hdr; | ||||
|   struct nd_neighbor_solicit *ns; | ||||
|   struct nd_opt_hdr *opt; | ||||
|   subnet_t *subnet; | ||||
|   short unsigned int 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((unsigned short int *)&pseudo, sizeof(pseudo)/2, ~0); | ||||
|   checksum = inet_checksum((unsigned short int *)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((unsigned short int *)&pseudo, sizeof(pseudo)/2, ~0); | ||||
|   checksum = inet_checksum((unsigned short int *)ns, sizeof(*ns)/2 + 4, checksum); | ||||
| 
 | ||||
|   ns->nd_ns_hdr.icmp6_cksum = htons(checksum); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
| void route_arp(vpn_packet_t *packet) | ||||
| { | ||||
|   struct ether_arp *arp; | ||||
|   subnet_t *subnet; | ||||
|   unsigned char 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 || | ||||
|      (int) (arp->arp_hln) != ETHER_ADDR_LEN || | ||||
|      (int) (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); | ||||
| cp | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										41
									
								
								src/pokey/route.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/pokey/route.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | |||
| /*
 | ||||
|     route.h -- header file for route.c | ||||
|     Copyright (C) 2000-2002 Ivo Timmermans <zarq@iname.com> | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net>          | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     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 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_ROUTE_H__ | ||||
| #define __TINC_ROUTE_H__ | ||||
| 
 | ||||
| enum | ||||
| { | ||||
|   RMODE_HUB = 0, | ||||
|   RMODE_SWITCH, | ||||
|   RMODE_ROUTER, | ||||
| }; | ||||
| 
 | ||||
| extern int routing_mode; | ||||
| extern int priorityinheritance; | ||||
| extern int macexpire; | ||||
| 
 | ||||
| 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__ */ | ||||
|  | @ -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.7 2002/04/09 15:26:00 zarq Exp $ | ||||
|     $Id: protocol.h,v 1.8 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_PROTOCOL_H__ | ||||
|  | @ -40,7 +40,7 @@ enum { | |||
|   ID = 0, METAKEY, CHALLENGE, CHAL_REPLY, ACK, | ||||
|   STATUS, ERROR, TERMREQ, | ||||
|   PING, PONG, | ||||
| //  ADD_NODE, DEL_NODE,
 | ||||
|   /*  ADD_NODE, DEL_NODE, */ | ||||
|   ADD_SUBNET, DEL_SUBNET, | ||||
|   ADD_EDGE, DEL_EDGE, | ||||
|   KEY_CHANGED, REQ_KEY, ANS_KEY, | ||||
|  | @ -81,8 +81,8 @@ 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_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 *); | ||||
|  | @ -106,8 +106,8 @@ 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_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 *); | ||||
|  |  | |||
|  | @ -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.3 2002/04/13 11:07:12 zarq Exp $ | ||||
|     $Id: protocol_auth.c,v 1.4 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
|  | @ -32,9 +32,15 @@ | |||
| #include <xalloc.h> | ||||
| #include <avl_tree.h> | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
| #include <openssl/sha.h> | ||||
| #include <openssl/rand.h> | ||||
| #include <openssl/evp.h> | ||||
| #endif | ||||
| 
 | ||||
| #ifdef USE_GCRYPT | ||||
| #include <gcrypt.h> | ||||
| #endif | ||||
| 
 | ||||
| #ifndef HAVE_RAND_PSEUDO_BYTES | ||||
| #define RAND_pseudo_bytes RAND_bytes | ||||
|  | @ -142,6 +148,7 @@ int send_metakey(connection_t *c) | |||
|   char buffer[MAX_STRING_SIZE]; | ||||
|   int len, x; | ||||
| cp | ||||
| #ifdef USE_OPENSSL | ||||
|   len = RSA_size(c->rsa_key); | ||||
| 
 | ||||
|   /* Allocate buffers for the meta key */ | ||||
|  | @ -155,6 +162,12 @@ cp | |||
|   /* Copy random data to the buffer */ | ||||
| 
 | ||||
|   RAND_bytes(c->outkey, len); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef USE_GCRYPT | ||||
|   len = 123; /* FIXME: RSA key length */ | ||||
|   c->outkey = gcry_random_bytes(len, GCRY_WEAK_RANDOM); | ||||
| #endif | ||||
| 
 | ||||
|   /* 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: | ||||
|  | @ -182,25 +195,32 @@ cp | |||
|      with a length equal to that of the modulus of the RSA key. | ||||
|   */ | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   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; | ||||
|     } | ||||
| #endif | ||||
| cp | ||||
|   /* Convert the encrypted random data to a hexadecimal formatted string */ | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   bin2hex(buffer, buffer, len); | ||||
| #endif | ||||
|   buffer[len*2] = '\0'; | ||||
| 
 | ||||
|   /* Send the meta key */ | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   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); | ||||
| #endif | ||||
| 
 | ||||
|   /* Further outgoing requests are encrypted with the key we just generated */ | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   if(c->outcipher) | ||||
|     { | ||||
|       EVP_EncryptInit(c->outctx, c->outcipher, | ||||
|  | @ -209,6 +229,7 @@ cp | |||
| 
 | ||||
|       c->status.encryptout = 1; | ||||
|     } | ||||
| #endif | ||||
| cp | ||||
|   return x; | ||||
| } | ||||
|  | @ -225,7 +246,9 @@ cp | |||
|        return -1; | ||||
|     } | ||||
| cp | ||||
| #ifdef USE_OPENSSL | ||||
|   len = RSA_size(myself->connection->rsa_key); | ||||
| #endif | ||||
| 
 | ||||
|   /* Check if the length of the meta key is all right */ | ||||
| 
 | ||||
|  | @ -240,20 +263,24 @@ cp | |||
|   if(!c->inkey) | ||||
|     c->inkey = xmalloc(len); | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   if(!c->inctx) | ||||
|     c->inctx = xmalloc(sizeof(*c->inctx)); | ||||
| #endif | ||||
| 
 | ||||
|   /* Convert the challenge from hexadecimal back to binary */ | ||||
| cp | ||||
|   hex2bin(buffer,buffer,len); | ||||
| 
 | ||||
|   /* Decrypt the meta key */ | ||||
| cp   | ||||
| cp | ||||
| #ifdef USE_OPENSSL | ||||
|   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; | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|   if(debug_lvl >= DEBUG_SCARY_THINGS) | ||||
|     { | ||||
|  | @ -268,6 +295,7 @@ cp | |||
| 
 | ||||
|   if(cipher) | ||||
|     { | ||||
| #ifdef USE_OPENSSL | ||||
|       c->incipher = EVP_get_cipherbynid(cipher); | ||||
|       if(!c->incipher) | ||||
| 	{ | ||||
|  | @ -280,6 +308,7 @@ cp | |||
|                       c->inkey + len - c->incipher->key_len - c->incipher->iv_len); | ||||
| 
 | ||||
|       c->status.decryptin = 1; | ||||
| #endif | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|  | @ -290,6 +319,7 @@ cp | |||
| 
 | ||||
|   if(digest) | ||||
|     { | ||||
| #ifdef USE_OPENSSL | ||||
|       c->indigest = EVP_get_digestbynid(digest); | ||||
|       if(!c->indigest) | ||||
| 	{ | ||||
|  | @ -302,6 +332,7 @@ cp | |||
| 	  syslog(LOG_ERR, _("%s (%s) uses bogus MAC length!"), c->name, c->hostname); | ||||
| 	  return -1; | ||||
| 	} | ||||
| #endif | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|  | @ -322,7 +353,9 @@ int send_challenge(connection_t *c) | |||
| cp | ||||
|   /* CHECKME: what is most reasonable value for len? */ | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   len = RSA_size(c->rsa_key); | ||||
| #endif | ||||
| 
 | ||||
|   /* Allocate buffers for the challenge */ | ||||
| 
 | ||||
|  | @ -331,7 +364,9 @@ cp | |||
| cp | ||||
|   /* Copy random data to the buffer */ | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   RAND_bytes(c->hischallenge, len); | ||||
| #endif | ||||
| 
 | ||||
| cp | ||||
|   /* Convert to hex */ | ||||
|  | @ -358,7 +393,9 @@ cp | |||
|        return -1; | ||||
|     } | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
|   len = RSA_size(myself->connection->rsa_key); | ||||
| #endif | ||||
| 
 | ||||
|   /* Check if the length of the challenge is all right */ | ||||
| 
 | ||||
|  | @ -386,6 +423,7 @@ cp | |||
| 
 | ||||
| int send_chal_reply(connection_t *c) | ||||
| { | ||||
| #ifdef USE_OPENSSL | ||||
|   char hash[EVP_MAX_MD_SIZE*2+1]; | ||||
|   EVP_MD_CTX ctx; | ||||
| cp | ||||
|  | @ -404,10 +442,15 @@ cp | |||
| 
 | ||||
| cp | ||||
|   return send_request(c, "%d %s", CHAL_REPLY, hash); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|   return 0; | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| int chal_reply_h(connection_t *c) | ||||
| { | ||||
| #ifdef USE_OPENSSL | ||||
|   char hishash[MAX_STRING_SIZE]; | ||||
|   char myhash[EVP_MAX_MD_SIZE]; | ||||
|   EVP_MD_CTX ctx; | ||||
|  | @ -454,6 +497,8 @@ cp | |||
|      Send an acknowledgement with the rest of the information needed. | ||||
|    */ | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
|   c->allow_request = ACK; | ||||
| cp | ||||
|   return send_ack(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.2 2002/04/09 15:26:01 zarq Exp $ | ||||
|     $Id: protocol_key.c,v 1.3 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
|  | @ -179,8 +179,14 @@ cp | |||
|   bin2hex(from->key, key, from->keylength); | ||||
|   key[from->keylength * 2] = '\0'; | ||||
| cp | ||||
| #ifdef USE_OPENSSL | ||||
|   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); | ||||
| #endif | ||||
| #ifdef USE_GCRYPT | ||||
|   return send_request(c, "%d %s %s %s %d %d %d %d", ANS_KEY, | ||||
|                       from->name, to->name, key, from->cipher?-1:0, from->digest?-1:0, from->maclength, from->compression); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| int ans_key_h(connection_t *c) | ||||
|  | @ -240,6 +246,7 @@ cp | |||
| 
 | ||||
|   if(cipher) | ||||
|     { | ||||
| #ifdef USE_OPENSSL | ||||
|       from->cipher = EVP_get_cipherbynid(cipher); | ||||
|       if(!from->cipher) | ||||
| 	{ | ||||
|  | @ -251,6 +258,7 @@ cp | |||
| 	  syslog(LOG_ERR, _("Node %s (%s) uses wrong keylength!"), from->name, from->hostname); | ||||
| 	  return -1; | ||||
|         } | ||||
| #endif | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|  | @ -261,6 +269,7 @@ cp | |||
| 
 | ||||
|   if(digest) | ||||
|     { | ||||
| #ifdef USE_OPENSSL | ||||
|       from->digest = EVP_get_digestbynid(digest); | ||||
|       if(!from->digest) | ||||
| 	{ | ||||
|  | @ -272,6 +281,7 @@ cp | |||
| 	  syslog(LOG_ERR, _("Node %s (%s) uses bogus MAC length!"), from->name, from->hostname); | ||||
| 	  return -1; | ||||
| 	} | ||||
| #endif | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|  |  | |||
							
								
								
									
										411
									
								
								src/read_conf.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										411
									
								
								src/read_conf.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,411 @@ | |||
| /*
 | ||||
|     read_conf.c -- read the configuration files | ||||
|     Copyright (C) 1998 Robert van der Meulen | ||||
|                   1998-2002 Ivo Timmermans <ivo@o2w.nl> | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 		  2000 Cris van Pelt <tribbel@arise.dhs.org> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| 
 | ||||
|     $Id: read_conf.c,v 1.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
| 
 | ||||
| #include <ctype.h> | ||||
| #include <errno.h> | ||||
| #include <netdb.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <sys/stat.h> | ||||
| #include <sys/types.h> | ||||
| #include <unistd.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include <xalloc.h> | ||||
| #include <utils.h> /* for cp */ | ||||
| #include <avl_tree.h> | ||||
| 
 | ||||
| #include "conf.h" | ||||
| #include "netutl.h" /* for str2address */ | ||||
| #include "logging.h" | ||||
| 
 | ||||
| #include "system.h" | ||||
| 
 | ||||
| /*
 | ||||
|   Read exactly one line and strip the trailing newline if any.  If the | ||||
|   file was on EOF, return NULL. Otherwise, return all the data in a | ||||
|   dynamically allocated buffer. | ||||
| 
 | ||||
|   If line is non-NULL, it will be used as an initial buffer, to avoid | ||||
|   unnecessary mallocing each time this function is called.  If buf is | ||||
|   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 *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 != NULL) && (buflen != NULL)) | ||||
|     { | ||||
|       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 == NULL)  /* 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 == NULL) | ||||
| 	/* 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 */ | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|   if((buf != NULL) && (buflen != NULL)) | ||||
|     { | ||||
|       *buflen = size; | ||||
|       *buf = 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 err = -2; /* Parse error */ | ||||
|   FILE *fp; | ||||
|   char *buffer, *line; | ||||
|   char *variable, *value; | ||||
|   int lineno = 0, ignore = 0; | ||||
|   config_t *cfg; | ||||
|   size_t bufsize; | ||||
| 
 | ||||
| cp | ||||
|   if((fp = fopen (fname, "r")) == NULL) | ||||
|     { | ||||
|       syslog(LOG_ERR, _("Cannot open config file %s: %s"), fname, strerror(errno)); | ||||
|       return -3; | ||||
|     } | ||||
| 
 | ||||
|   bufsize = 100; | ||||
|   buffer = xmalloc(bufsize); | ||||
| 
 | ||||
|   for(;;) | ||||
|     { | ||||
|       if((line = readline(fp, &buffer, &bufsize)) == NULL) | ||||
| 	{ | ||||
| 	  err = -1; | ||||
| 	  break; | ||||
| 	} | ||||
| 
 | ||||
|       if(feof(fp)) | ||||
| 	{ | ||||
| 	  err = 0; | ||||
| 	  break; | ||||
| 	} | ||||
| 
 | ||||
|       lineno++; | ||||
| 
 | ||||
|       if((variable = strtok(line, "\t =")) == NULL) | ||||
| 	continue; /* no tokens on this line */ | ||||
| 
 | ||||
|       if(variable[0] == '#') | ||||
| 	continue; /* comment: ignore */ | ||||
| 
 | ||||
|       if(!strcmp(variable, "-----BEGIN")) | ||||
|         ignore = 1; | ||||
| 
 | ||||
|       if(!ignore) | ||||
|         { | ||||
|           if(((value = strtok(NULL, "\t\n\r =")) == NULL) || value[0] == '#') | ||||
| 	    { | ||||
| 	      syslog(LOG_ERR, _("No value for variable `%s' on line %d while reading config file %s"), | ||||
| 		      variable, lineno, fname); | ||||
| 	      break; | ||||
| 	    } | ||||
| 
 | ||||
|           cfg = new_config(); | ||||
|           cfg->variable = xstrdup(variable); | ||||
|           cfg->value = xstrdup(value); | ||||
|           cfg->file = xstrdup(fname); | ||||
|           cfg->line = lineno; | ||||
| 
 | ||||
|           config_add(config_tree, cfg); | ||||
|        } | ||||
| 
 | ||||
|       if(!strcmp(variable, "-----END")) | ||||
|         ignore = 0; | ||||
|     } | ||||
| 
 | ||||
|   free(buffer); | ||||
|   fclose (fp); | ||||
| cp | ||||
|   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; | ||||
| } | ||||
| 
 | ||||
| int isadir(const char* f) | ||||
| { | ||||
|   struct stat s; | ||||
| 
 | ||||
|   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]; | ||||
| 
 | ||||
|   if(*file != '/') | ||||
|     { | ||||
|       syslog(LOG_ERR, _("`%s' is not an absolute path"), file); | ||||
|       return 0; | ||||
|     } | ||||
| 
 | ||||
|   p = strrchr(file, '/'); | ||||
| 
 | ||||
|   if(p == file)		/* It's in the root */ | ||||
|     p++; | ||||
| 
 | ||||
|   x = *p; | ||||
|   *p = '\0'; | ||||
| 
 | ||||
|   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; | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
| 
 | ||||
|       if((fn = readline(stdin, NULL, NULL)) == NULL) | ||||
| 	{ | ||||
| 	  fprintf(stderr, _("Error while reading stdin: %s\n"), strerror(errno)); | ||||
| 	  return NULL; | ||||
| 	} | ||||
| 
 | ||||
|       if(strlen(fn) == 0) | ||||
| 	/* User just pressed enter. */ | ||||
| 	fn = xstrdup(filename); | ||||
|     } | ||||
| 
 | ||||
|   if((strchr(fn, '/') == NULL) || (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 */ | ||||
|   if((r = fopen(fn, mode)) == NULL) | ||||
|     { | ||||
|       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; | ||||
| } | ||||
| 
 | ||||
| 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; | ||||
| } | ||||
							
								
								
									
										31
									
								
								src/read_conf.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/read_conf.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | |||
| /*
 | ||||
|     conf.h -- header for conf.c | ||||
|     Copyright (C) 1998-2002 Ivo Timmermans <itimmermans@bigfoot.com> | ||||
|                   2000-2002 Guus Sliepen <guus@sliepen.warande.net> | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
| 
 | ||||
|     $Id: read_conf.h,v 1.1 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #ifndef __TINC_READ_CONF_H__ | ||||
| #define __TINC_READ_CONF_H__ | ||||
| 
 | ||||
| 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 int is_safe_path(const char *); | ||||
| 
 | ||||
| #endif /* __TINC_READ_CONF_H__ */ | ||||
							
								
								
									
										12
									
								
								src/tincd.c
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								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.14 2002/04/13 11:07:12 zarq Exp $ | ||||
|     $Id: tincd.c,v 1.15 2002/04/28 12:46:26 zarq Exp $ | ||||
| */ | ||||
| 
 | ||||
| #include "config.h" | ||||
|  | @ -37,10 +37,16 @@ | |||
| # include <sys/ioctl.h> | ||||
| #endif | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
| #include <openssl/rand.h> | ||||
| #include <openssl/rsa.h> | ||||
| #include <openssl/pem.h> | ||||
| #include <openssl/evp.h> | ||||
| #endif | ||||
| 
 | ||||
| #ifdef USE_GCRYPT | ||||
| #include <gcrypt.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <utils.h> | ||||
| #include <xalloc.h> | ||||
|  | @ -231,6 +237,7 @@ void indicator(int a, int b, void *p) | |||
|   } | ||||
| } | ||||
| 
 | ||||
| #ifdef USE_OPENSSL | ||||
| /*
 | ||||
|   Generate a public/private RSA keypair, and ask for a file to store | ||||
|   them in. | ||||
|  | @ -283,6 +290,7 @@ int keygen(int bits) | |||
| 
 | ||||
|   return 0; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|   Set all files and paths according to netname | ||||
|  | @ -347,6 +355,7 @@ main(int argc, char **argv, char **envp) | |||
| 
 | ||||
|   /* Slllluuuuuuurrrrp! */ | ||||
| cp | ||||
| #ifdef USE_OPENSSL | ||||
|   RAND_load_file("/dev/urandom", 1024); | ||||
| 
 | ||||
| #ifdef HAVE_SSLEAY_ADD_ALL_ALGORITHMS | ||||
|  | @ -361,6 +370,7 @@ cp | |||
|       read_server_config(); | ||||
|       exit(keygen(generate_keys)); | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
|   if(kill_tincd) | ||||
|     exit(kill_other(kill_tincd)); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue