diff options
author | Roger Dingledine <arma@torproject.org> | 2002-06-26 22:45:49 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2002-06-26 22:45:49 +0000 |
commit | 9a928eeb1215f0d7c9b6d0bb9e4571d0a16ed79a (patch) | |
tree | fac560bf2dce8a8d2b82e296b71ff24f59ab1a7a /src/or/routers.c | |
parent | 766a465a6043ac4e643c398feb14f708fd0d863f (diff) | |
download | tor-9a928eeb1215f0d7c9b6d0bb9e4571d0a16ed79a.tar.gz tor-9a928eeb1215f0d7c9b6d0bb9e4571d0a16ed79a.zip |
Initial revision
svn:r2
Diffstat (limited to 'src/or/routers.c')
-rw-r--r-- | src/or/routers.c | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/src/or/routers.c b/src/or/routers.c new file mode 100644 index 0000000000..d24d4d1bdb --- /dev/null +++ b/src/or/routers.c @@ -0,0 +1,365 @@ +/** + * routers.c + * Routines for loading the list of routers and their public RSA keys. + * + * Matej Pfajfar <mp292@cam.ac.uk> + */ + +#define OR_ROUTERLIST_SEPCHARS " \t\n" +#define OR_PUBLICKEY_BEGIN_TAG "-----BEGIN RSA PUBLIC KEY-----\n" + +#include "or.h" + +/* delete a list of routers from memory */ +void delete_routerlist(routerinfo_t *list) +{ + routerinfo_t *tmp = NULL; + + if (!list) + return; + + do + { + tmp=list->next; + free((void *)list->address); + RSA_free(list->pkey); + free((void *)list); + list = tmp; + } + while (list != NULL); + + return; +} + +/* create an NULL-terminated array of pointers pointing to elements of a router list */ +/* this is done in two passes through the list - inefficient but irrelevant as this is + * only done once when op/or start up */ +routerinfo_t **make_rarray(routerinfo_t* list, size_t *len) +{ + routerinfo_t *tmp=NULL; + int listlen = 0; + routerinfo_t **array=NULL; + routerinfo_t **p=NULL; + + if ((!list) || (!len)) + return NULL; + + /* get the length of the list */ + tmp = list; + do + { + listlen++; + tmp = tmp->next; + } + while (tmp != NULL); + + array = malloc((listlen+1)*sizeof(routerinfo_t *)); + if (!array) + { + log(LOG_ERR,"Error allocating memory."); + return NULL; + } + + tmp=list; + p = array; + do + { + *p = tmp; + p++; + tmp = tmp->next; + } + while(tmp != NULL); + *p=NULL; + + *len = listlen; + return array; +} + +/* load the router list */ +routerinfo_t **getrouters(char *routerfile, size_t *lenp) +{ + int retval = 0; + char *retp = NULL; + routerinfo_t *router=NULL, *routerlist=NULL, *lastrouter=NULL; + FILE *rf; /* router file */ + fpos_t fpos; + char line[512]; + char *token; + char *errtest; /* detecting errors in strtoul() calls */ + struct hostent *rent; + + if ((!routerfile) || (!lenp)) + return NULL; + + if (strcspn(routerfile,CONFIG_LEGAL_FILENAME_CHARACTERS) != 0) + { + log(LOG_ERR,"Filename %s contains illegal characters.",routerfile); + return NULL; + } + + /* open the router list */ + rf = fopen(routerfile,"r"); + if (!rf) + { + log(LOG_ERR,"Could not open %s.",routerfile); + return NULL; + } + + retp= fgets(line,512,rf); + while (retp) + { + log(LOG_DEBUG,"getrouters():Line :%s",line); + token = (char *)strtok(line,OR_ROUTERLIST_SEPCHARS); + if (token) + { + log(LOG_DEBUG,"getrouters():Token : %s",token); + if (token[0] != '#') /* ignore comment lines */ + { + router = malloc(sizeof(routerinfo_t)); + if (!router) + { + log(LOG_ERR,"Could not allocate memory."); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + +#if 0 + router->conn_bufs = NULL; /* no output buffers */ + router->last_conn_buf = NULL; + router->next_to_service = 0; + + router->s = -1; /* to signify this router is as yet unconnected */ + router->celllen = 0; /* cell buffer is empty */ +#endif + + /* read the address */ + router->address = malloc(strlen(token)+1); + if (!router->address) + { + log(LOG_ERR,"Could not allocate memory."); + fclose(rf); + free((void *)router); + delete_routerlist(routerlist); + return NULL; + } + strcpy(router->address,token); + + rent = (struct hostent *)gethostbyname(router->address); + if (!rent) + { + log(LOG_ERR,"Could not get address for router %s.",router->address); + fclose(rf); + free((void *)router->address); + free((void *)router); + delete_routerlist(routerlist); + return NULL; + } + + memcpy(&router->addr, rent->h_addr,rent->h_length); + + /* read the port */ + token = (char *)strtok(NULL,OR_ROUTERLIST_SEPCHARS); + if (token) + { + log(LOG_DEBUG,"getrouters():Token :%s",token); + router->port = (uint16_t)strtoul(token,&errtest,0); + if ((*token != '\0') && (*errtest == '\0')) /* conversion was successful */ + { + /* convert port to network format */ + router->port = htons(router->port); + + /* read min bandwidth */ + token = (char *)strtok(NULL,OR_ROUTERLIST_SEPCHARS); + if (token) /* min bandwidth */ + { + router->min = (uint32_t)strtoul(token,&errtest,0); + if ((*token != '\0') && (*errtest == '\0')) /* conversion was successful */ + { + if (router->min) /* must not be zero */ + { + /* read max bandwidth */ + token = (char *)strtok(NULL,OR_ROUTERLIST_SEPCHARS); + if (token) /* max bandwidth */ + { + router->max = (uint32_t)strtoul(token,&errtest,0); + if ((*token != '\0') && (*errtest == '\0')) /* conversion was successful */ + { + if (router->max) /* must not be zero */ + { + /* check that there is a public key entry for that router */ + retval = fgetpos(rf, &fpos); /* save the current file position + * we wil return to it later if we find a public key */ + if (retval == -1) + { + log(LOG_ERR,"Could not save position in %s.",routerfile); + free((void *)router->address); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + do /* read through to the next non-empty line */ + { + retp=fgets(line,512,rf); + if (!retp) + { + log(LOG_ERR,"Could not find a public key entry for router %s:%u.",router->address,router->port); + free((void *)router->address); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + log(LOG_DEBUG,"getrouters():Line:%s",line); + if ((*line != '#') && ( strspn(line,OR_ROUTERLIST_SEPCHARS) != strlen(line) )) + { + break; + } + } while (1); + + if (!strcmp(line,OR_PUBLICKEY_BEGIN_TAG)) /* we've got the public key */ + { + retval = fsetpos(rf,&fpos); /* get us back to where we were otherwise crypto lib won't find the key */ + if (retval == -1) + { + log(LOG_ERR,"Could not set position in %s.",routerfile); + free((void *)router->address); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + } + else /* we found something else; this isn't right */ + { + log(LOG_ERR,"Could not find a public key entry for router %s:%u.",router->address,router->port); + free((void *)router->address); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + + log(LOG_DEBUG,"getrouters():Reading the key ..."); + /* read the public key into router->pkey */ + router->pkey=NULL; + router->pkey = PEM_read_RSAPublicKey(rf,&router->pkey,NULL,NULL); + if (!router->pkey) /* something went wrong */ + { + log(LOG_ERR,"Could not read public key for router %s:%u.",router->address,router->port); + free((void *)router->address); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + else /* read the key */ + { + log(LOG_DEBUG,"getrouters():Public key size = %u.", RSA_size(router->pkey)); + if (RSA_size(router->pkey) != 128) /* keys MUST be 1024 bits in size */ + { + log(LOG_ERR,"Key for router %s:%u is not 1024 bits. All keys must be exactly 1024 bits long.",router->address,router->port); + free((void *)router->address); + RSA_free(router->pkey); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + router->next = NULL; + /* save the entry into the routerlist linked list */ + if (!routerlist) /* this is the first entry */ + routerlist = router; + else + lastrouter->next = (void *)router; + lastrouter = router; + } + } + else /* maximum link utilisation is zero */ + { + log(LOG_ERR,"Entry for router %s doesn't contain a valid maximum bandwidth entry (must be > 0).",router->address); + free((void *)router->address); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + } + else + { + log(LOG_ERR,"Entry for router %s doesn't seem to contain a valid maximum bandwidth entry.",router->address); + free((void *)router->address); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + } + else + { + log(LOG_ERR,"Entry for router %s doesn't seem to contain a maximum bandwidth entry.",router->address); + free((void *)router->address); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + } + else + { + log(LOG_ERR,"Entry for router %s doesn't contain a valid minimum bandwidth entry (must be > 0).",router->address); + free((void *)router->address); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + } + else + { + log(LOG_ERR,"Entry for router %s doesn't seem to contain a valid minimum bandwidth entry.",router->address); + free((void *)router->address); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + } + else + { + log(LOG_ERR,"Entry for router %s doesn't seem to contain a minimum bandwidth entry.",router->address); + free((void *)router->address); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + } + else + { + log(LOG_ERR,"Entry for router %s doesn't seem to contain a valid port number.",router->address); + free((void *)router->address); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + } + else + { + log(LOG_ERR,"Entry for router %s doesn't seem to contain a port number.",router->address); + free((void *)router->address); + free((void *)router); + fclose(rf); + delete_routerlist(routerlist); + return NULL; + } + } + } + retp=fgets(line,512,rf); + } + + fclose(rf); + return make_rarray(routerlist, lenp); +} |