Implemented link padding and receiver token buckets
Each socket reads at most 'bandwidth' bytes per second sustained, but
can handle bursts of up to 10*bandwidth bytes.
Cells are now sent out at evenly-spaced intervals, with padding sent
out otherwise. Set Linkpadding=0 in the rc file to send cells as soon
as they're available (and to never send padding cells).
Added license/copyrights statements at the top of most files.
router->min and router->max have been merged into a single 'bandwidth'
value. We should make the routerinfo_t reflect this (want to do that,
Mat?)
As the bandwidth increases, and we want to stop sleeping more and more
frequently to send a single cell, cpu usage goes up. At 128kB/s we're
pretty much calling poll with a timeout of 1ms or even 0ms. The current
code takes a timeout of 0-9ms and makes it 10ms. prepare_for_poll()
handles everything that should have happened in the past, so as long as
our buffers don't get too full in that 10ms, we're ok.
Speaking of too full, if you run three servers at 100kB/s with -l debug,
it spends too much time printing debugging messages to be able to keep
up with the cells. The outbuf ultimately fills up and it kills that
connection. If you run with -l err, it works fine up through 500kB/s and
probably beyond. Down the road we'll want to teach it to recognize when
an outbuf is getting full, and back off.
svn:r50
2002-07-16 03:12:15 +02:00
|
|
|
/* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
|
|
|
|
/* See LICENSE for licensing information */
|
|
|
|
/* $Id$ */
|
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
#define OR_PUBLICKEY_BEGIN_TAG "-----BEGIN RSA PUBLIC KEY-----\n"
|
2002-09-24 12:43:57 +02:00
|
|
|
#define OR_PUBLICKEY_END_TAG "-----END RSA PUBLIC KEY-----\n"
|
2003-05-07 20:30:46 +02:00
|
|
|
#define OR_SIGNATURE_BEGIN_TAG "-----BEGIN SIGNATURE-----\n"
|
|
|
|
#define OR_SIGNATURE_END_TAG "-----END SIGNATURE-----\n"
|
2002-06-27 00:45:49 +02:00
|
|
|
|
|
|
|
#include "or.h"
|
|
|
|
|
2002-09-26 14:09:10 +02:00
|
|
|
/****************************************************************************/
|
|
|
|
|
|
|
|
/* router array */
|
2003-05-06 19:38:16 +02:00
|
|
|
static directory_t *directory = NULL;
|
2002-09-26 14:09:10 +02:00
|
|
|
|
|
|
|
extern or_options_t options; /* command-line and config-file options */
|
2002-09-26 15:17:14 +02:00
|
|
|
extern routerinfo_t *my_routerinfo; /* from main.c */
|
2002-09-26 14:09:10 +02:00
|
|
|
|
|
|
|
/****************************************************************************/
|
2002-09-04 08:29:28 +02:00
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
struct directory_token;
|
|
|
|
typedef struct directory_token directory_token_t;
|
|
|
|
|
2002-09-24 12:43:57 +02:00
|
|
|
/* static function prototypes */
|
2003-05-07 04:13:23 +02:00
|
|
|
void routerlist_free(routerinfo_t *list);
|
2002-09-24 12:43:57 +02:00
|
|
|
static routerinfo_t **make_rarray(routerinfo_t* list, int *len);
|
|
|
|
static char *eat_whitespace(char *s);
|
2003-05-07 20:30:46 +02:00
|
|
|
static char *eat_whitespace_no_nl(char *s);
|
2002-09-24 12:43:57 +02:00
|
|
|
static char *find_whitespace(char *s);
|
2003-04-07 06:38:19 +02:00
|
|
|
static void router_free_exit_policy(routerinfo_t *router);
|
2003-05-07 20:30:46 +02:00
|
|
|
static routerinfo_t *router_get_entry_from_string_tok(char**s,
|
|
|
|
directory_token_t *tok);
|
|
|
|
static int router_get_list_from_string_tok(char **s, directory_t **dest,
|
|
|
|
directory_token_t *tok);
|
|
|
|
static int router_add_exit_policy(routerinfo_t *router,
|
|
|
|
directory_token_t *tok);
|
2002-09-24 12:43:57 +02:00
|
|
|
|
2002-09-26 14:09:10 +02:00
|
|
|
/****************************************************************************/
|
|
|
|
|
2002-10-03 00:54:20 +02:00
|
|
|
int learn_my_address(struct sockaddr_in *me) {
|
|
|
|
/* local host information */
|
|
|
|
char localhostname[512];
|
|
|
|
struct hostent *localhost;
|
|
|
|
|
|
|
|
/* obtain local host information */
|
|
|
|
if(gethostname(localhostname,512) < 0) {
|
|
|
|
log(LOG_ERR,"Error obtaining local hostname.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
log(LOG_DEBUG,"learn_my_address(): localhostname is '%s'.",localhostname);
|
|
|
|
localhost = gethostbyname(localhostname);
|
|
|
|
if (!localhost) {
|
|
|
|
log(LOG_ERR,"Error obtaining local host info.");
|
|
|
|
return -1;
|
|
|
|
}
|
2003-04-07 06:38:19 +02:00
|
|
|
memset(me,0,sizeof(struct sockaddr_in));
|
2002-10-03 00:54:20 +02:00
|
|
|
me->sin_family = AF_INET;
|
|
|
|
memcpy((void *)&me->sin_addr,(void *)localhost->h_addr,sizeof(struct in_addr));
|
|
|
|
me->sin_port = htons(options.ORPort);
|
|
|
|
log(LOG_DEBUG,"learn_my_address(): chose address as '%s'.",inet_ntoa(me->sin_addr));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void router_retry_connections(void) {
|
2002-09-26 14:09:10 +02:00
|
|
|
int i;
|
|
|
|
routerinfo_t *router;
|
|
|
|
|
2003-05-06 19:38:16 +02:00
|
|
|
for (i=0;i<directory->n_routers;i++) {
|
|
|
|
router = directory->routers[i];
|
2002-09-26 14:09:10 +02:00
|
|
|
if(!connection_exact_get_by_addr_port(router->addr,router->or_port)) { /* not in the list */
|
|
|
|
log(LOG_DEBUG,"retry_all_connections(): connecting to OR %s:%u.",router->address,router->or_port);
|
2002-10-03 00:54:20 +02:00
|
|
|
connection_or_connect_as_or(router);
|
2002-09-26 14:09:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
routerinfo_t *router_pick_directory_server(void) {
|
|
|
|
/* currently, pick the first router with a positive dir_port */
|
|
|
|
int i;
|
|
|
|
routerinfo_t *router;
|
|
|
|
|
2003-05-06 19:38:16 +02:00
|
|
|
if(!directory)
|
2002-09-26 14:09:10 +02:00
|
|
|
return NULL;
|
|
|
|
|
2003-05-06 19:38:16 +02:00
|
|
|
for(i=0;i<directory->n_routers;i++) {
|
|
|
|
router = directory->routers[i];
|
2002-09-26 14:09:10 +02:00
|
|
|
if(router->dir_port > 0)
|
|
|
|
return router;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port) {
|
|
|
|
int i;
|
|
|
|
routerinfo_t *router;
|
|
|
|
|
2003-05-06 19:38:16 +02:00
|
|
|
assert(directory);
|
2002-09-26 14:09:10 +02:00
|
|
|
|
2003-05-06 19:38:16 +02:00
|
|
|
for(i=0;i<directory->n_routers;i++) {
|
|
|
|
router = directory->routers[i];
|
2002-09-26 14:09:10 +02:00
|
|
|
if ((router->addr == addr) && (router->or_port == port))
|
|
|
|
return router;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2003-05-06 19:38:16 +02:00
|
|
|
void router_get_directory(directory_t **pdirectory) {
|
|
|
|
*pdirectory = directory;
|
2002-09-26 14:09:10 +02:00
|
|
|
}
|
|
|
|
|
2002-10-03 00:54:20 +02:00
|
|
|
/* return 1 if addr and port corresponds to my addr and my or_listenport. else 0,
|
|
|
|
* or -1 for failure.
|
|
|
|
*/
|
|
|
|
int router_is_me(uint32_t addr, uint16_t port)
|
2002-07-10 14:35:59 +02:00
|
|
|
{
|
2002-10-03 00:54:20 +02:00
|
|
|
struct sockaddr_in me; /* my router identity */
|
|
|
|
|
2003-03-18 02:49:55 +01:00
|
|
|
if(!options.ORPort) {
|
2002-10-03 00:54:20 +02:00
|
|
|
/* we're not an OR. This obviously isn't us. */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(learn_my_address(&me) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if(ntohl(me.sin_addr.s_addr) == addr && ntohs(me.sin_port) == port)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2002-07-10 14:35:59 +02:00
|
|
|
}
|
|
|
|
|
2002-06-27 00:45:49 +02:00
|
|
|
/* delete a list of routers from memory */
|
2003-05-07 04:13:23 +02:00
|
|
|
void routerlist_free(routerinfo_t *list)
|
2002-06-27 00:45:49 +02:00
|
|
|
{
|
|
|
|
routerinfo_t *tmp = NULL;
|
2003-05-06 19:38:16 +02:00
|
|
|
struct exit_policy_t *e = NULL, *etmp = NULL;
|
2002-06-27 00:45:49 +02:00
|
|
|
|
|
|
|
if (!list)
|
|
|
|
return;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
tmp=list->next;
|
2003-05-06 19:38:16 +02:00
|
|
|
if (list->address)
|
|
|
|
free((void *)list->address);
|
|
|
|
if (list->pkey)
|
|
|
|
crypto_free_pk_env(list->pkey);
|
|
|
|
e = list->exit_policy;
|
|
|
|
while (e) {
|
|
|
|
etmp = e->next;
|
|
|
|
if (e->string) free(e->string);
|
|
|
|
if (e->address) free(e->address);
|
|
|
|
if (e->port) free(e->port);
|
|
|
|
free(e);
|
|
|
|
e = etmp;
|
|
|
|
}
|
2002-06-27 00:45:49 +02:00
|
|
|
free((void *)list);
|
|
|
|
list = tmp;
|
|
|
|
}
|
|
|
|
while (list != NULL);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-09-24 12:43:57 +02:00
|
|
|
void rarray_free(routerinfo_t **list) {
|
|
|
|
if(!list)
|
|
|
|
return;
|
|
|
|
routerlist_free(*list);
|
|
|
|
free(list);
|
|
|
|
}
|
|
|
|
|
2003-05-06 19:38:16 +02:00
|
|
|
void directory_free(directory_t *directory)
|
|
|
|
{
|
|
|
|
rarray_free(directory->routers);
|
|
|
|
free(directory);
|
|
|
|
}
|
|
|
|
|
2002-09-26 15:17:14 +02:00
|
|
|
void router_forget_router(uint32_t addr, uint16_t port) {
|
|
|
|
int i;
|
|
|
|
routerinfo_t *router;
|
|
|
|
|
|
|
|
router = router_get_by_addr_port(addr,port);
|
|
|
|
if(!router) /* we don't seem to know about him in the first place */
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* now walk down router_array until we get to router */
|
2003-05-06 19:38:16 +02:00
|
|
|
for(i=0;i<directory->n_routers;i++)
|
|
|
|
if(directory->routers[i] == router)
|
2002-09-26 15:17:14 +02:00
|
|
|
break;
|
|
|
|
|
2003-05-06 19:38:16 +02:00
|
|
|
assert(i != directory->n_routers); /* if so then router_get_by_addr_port should have returned null */
|
2002-09-26 15:17:14 +02:00
|
|
|
|
2002-09-26 15:19:13 +02:00
|
|
|
// free(router); /* don't actually free; we'll free it when we free the whole thing */
|
|
|
|
|
2002-09-26 15:17:14 +02:00
|
|
|
// log(LOG_DEBUG,"router_forget_router(): Forgot about router %d:%d",addr,port);
|
2003-05-06 19:38:16 +02:00
|
|
|
for(; i<directory->n_routers-1;i++)
|
|
|
|
directory->routers[i] = directory->routers[i+1];
|
2002-09-26 15:17:14 +02:00
|
|
|
}
|
|
|
|
|
2002-07-22 06:08:37 +02:00
|
|
|
/* create a NULL-terminated array of pointers pointing to elements of a router list */
|
2002-06-27 00:45:49 +02:00
|
|
|
/* this is done in two passes through the list - inefficient but irrelevant as this is
|
|
|
|
* only done once when op/or start up */
|
2002-09-24 12:43:57 +02:00
|
|
|
static routerinfo_t **make_rarray(routerinfo_t* list, int *len)
|
2002-06-27 00:45:49 +02:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2002-09-24 12:43:57 +02:00
|
|
|
|
2002-06-27 00:45:49 +02:00
|
|
|
/* load the router list */
|
2002-10-03 00:54:20 +02:00
|
|
|
int router_get_list_from_file(char *routerfile)
|
2002-06-27 00:45:49 +02:00
|
|
|
{
|
2002-09-24 12:43:57 +02:00
|
|
|
int fd; /* router file */
|
|
|
|
struct stat statbuf;
|
|
|
|
char *string;
|
2002-06-27 00:45:49 +02:00
|
|
|
|
2002-09-26 14:09:10 +02:00
|
|
|
assert(routerfile);
|
2002-06-27 00:45:49 +02:00
|
|
|
|
2002-07-22 06:08:37 +02:00
|
|
|
if (strcspn(routerfile,CONFIG_LEGAL_FILENAME_CHARACTERS) != 0) {
|
2002-09-24 12:43:57 +02:00
|
|
|
log(LOG_ERR,"router_get_list_from_file(): Filename %s contains illegal characters.",routerfile);
|
2002-09-26 14:09:10 +02:00
|
|
|
return -1;
|
2002-06-27 00:45:49 +02:00
|
|
|
}
|
|
|
|
|
2002-09-24 12:43:57 +02:00
|
|
|
if(stat(routerfile, &statbuf) < 0) {
|
|
|
|
log(LOG_ERR,"router_get_list_from_file(): Could not stat %s.",routerfile);
|
2002-09-26 14:09:10 +02:00
|
|
|
return -1;
|
2002-09-24 12:43:57 +02:00
|
|
|
}
|
|
|
|
|
2002-06-27 00:45:49 +02:00
|
|
|
/* open the router list */
|
2002-09-24 12:43:57 +02:00
|
|
|
fd = open(routerfile,O_RDONLY,0);
|
|
|
|
if (fd<0) {
|
|
|
|
log(LOG_ERR,"router_get_list_from_file(): Could not open %s.",routerfile);
|
2002-09-26 14:09:10 +02:00
|
|
|
return -1;
|
2002-09-24 12:43:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
string = malloc(statbuf.st_size+1);
|
|
|
|
if(!string) {
|
|
|
|
log(LOG_ERR,"router_get_list_from_file(): Out of memory.");
|
2002-09-26 14:09:10 +02:00
|
|
|
return -1;
|
2002-09-24 12:43:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if(read(fd,string,statbuf.st_size) != statbuf.st_size) {
|
|
|
|
log(LOG_ERR,"router_get_list_from_file(): Couldn't read all %d bytes of file '%s'.",statbuf.st_size,routerfile);
|
2002-09-26 14:09:10 +02:00
|
|
|
free(string);
|
|
|
|
close(fd);
|
|
|
|
return -1;
|
2002-06-27 00:45:49 +02:00
|
|
|
}
|
2002-09-24 12:43:57 +02:00
|
|
|
close(fd);
|
2002-06-27 00:45:49 +02:00
|
|
|
|
2002-09-24 12:43:57 +02:00
|
|
|
string[statbuf.st_size] = 0; /* null terminate it */
|
2002-09-26 14:09:10 +02:00
|
|
|
|
2002-10-03 00:54:20 +02:00
|
|
|
if(router_get_list_from_string(string) < 0) {
|
2002-09-26 14:09:10 +02:00
|
|
|
log(LOG_ERR,"router_get_list_from_file(): The routerfile itself was corrupt.");
|
|
|
|
free(string);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
free(string);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
K_ACCEPT,
|
|
|
|
K_CLIENT_SOFTWARE,
|
|
|
|
K_DIRECTORY_SIGNATURE,
|
|
|
|
K_REJECT,
|
|
|
|
K_ROUTER,
|
|
|
|
K_SERVER_SOFTWARE,
|
|
|
|
K_SIGNED_DIRECTORY,
|
|
|
|
K_SIGNING_KEY,
|
|
|
|
_SIGNATURE,
|
|
|
|
_PUBLIC_KEY,
|
|
|
|
_ERR,
|
|
|
|
_EOF
|
|
|
|
} directory_keyword;
|
|
|
|
|
|
|
|
struct token_table_ent { char *t; int v; };
|
|
|
|
|
|
|
|
static struct token_table_ent token_table[] = {
|
|
|
|
{ "accept", K_ACCEPT },
|
|
|
|
{ "client-software", K_CLIENT_SOFTWARE },
|
|
|
|
{ "directory-signature", K_DIRECTORY_SIGNATURE },
|
|
|
|
{ "reject", K_REJECT },
|
|
|
|
{ "router", K_ROUTER },
|
|
|
|
{ "server-software", K_SERVER_SOFTWARE },
|
|
|
|
{ "signed-directory", K_SIGNED_DIRECTORY },
|
|
|
|
{ "signing-key", K_SIGNING_KEY },
|
|
|
|
{ NULL, -1 }
|
|
|
|
};
|
|
|
|
|
|
|
|
#define MAX_ARGS 8
|
|
|
|
struct directory_token {
|
|
|
|
directory_keyword tp;
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
char *args[MAX_ARGS+1];
|
|
|
|
int n_args;
|
|
|
|
} cmd;
|
|
|
|
char *signature;
|
|
|
|
char *error;
|
|
|
|
crypto_pk_env_t *public_key;
|
|
|
|
} val;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
_router_get_next_token(char **s, directory_token_t *tok) {
|
|
|
|
char *next;
|
|
|
|
crypto_pk_env_t *pkey = NULL;
|
|
|
|
char *signature = NULL;
|
|
|
|
int i, done;
|
|
|
|
|
|
|
|
tok->tp = _ERR;
|
|
|
|
tok->val.error = "";
|
|
|
|
|
|
|
|
*s = eat_whitespace(*s);
|
|
|
|
if (!**s) {
|
|
|
|
tok->tp = _EOF;
|
|
|
|
return 0;
|
|
|
|
} else if (**s == '-') {
|
|
|
|
next = strchr(*s, '\n');
|
|
|
|
if (! next) { tok->val.error = "No newline at EOF"; return -1; }
|
|
|
|
++next;
|
|
|
|
if (! strncmp(*s, OR_PUBLICKEY_BEGIN_TAG, next-*s)) {
|
|
|
|
next = strstr(*s, OR_PUBLICKEY_END_TAG);
|
|
|
|
if (!next) { tok->val.error = "No public key end tag found"; return -1; }
|
|
|
|
next = strchr(next, '\n'); /* Part of OR_PUBLICKEY_END_TAG; can't fail.*/
|
|
|
|
++next;
|
|
|
|
if (!(pkey = crypto_new_pk_env(CRYPTO_PK_RSA)))
|
|
|
|
return -1;
|
|
|
|
if (crypto_pk_read_public_key_from_string(pkey, *s, next-*s)) {
|
|
|
|
crypto_free_pk_env(pkey);
|
|
|
|
tok->val.error = "Couldn't parse public key.";
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
tok->tp = _PUBLIC_KEY;
|
|
|
|
tok->val.public_key = pkey;
|
|
|
|
*s = next;
|
|
|
|
return 0;
|
|
|
|
} else if (! strncmp(*s, OR_SIGNATURE_BEGIN_TAG, next-*s)) {
|
|
|
|
/* Advance past newline; can't fail. */
|
|
|
|
*s = strchr(*s, '\n');
|
|
|
|
++*s;
|
|
|
|
/* Find end of base64'd data */
|
|
|
|
next = strstr(*s, OR_SIGNATURE_END_TAG);
|
|
|
|
if (!next) { tok->val.error = "No signature end tag found"; return -1; }
|
|
|
|
|
|
|
|
signature = malloc(256);
|
|
|
|
i = base64_decode(signature, 256, *s, next-*s);
|
|
|
|
if (i<0) {
|
|
|
|
free(signature);
|
|
|
|
tok->val.error = "Error decoding signature."; return -1;
|
|
|
|
} else if (i != 128) {
|
|
|
|
free(signature);
|
|
|
|
tok->val.error = "Bad length on decoded signature."; return -1;
|
|
|
|
}
|
|
|
|
tok->tp = _SIGNATURE;
|
|
|
|
tok->val.signature = signature;
|
|
|
|
|
|
|
|
next = strchr(next, '\n'); /* Part of OR_SIGNATURE_END_TAG; can't fail.*/
|
|
|
|
*s = next+1;
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
tok->val.error = "Unrecognized begin line"; return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
next = find_whitespace(*s);
|
|
|
|
if (!next) {
|
|
|
|
tok->val.error = "Unexpected EOF"; return -1;
|
|
|
|
}
|
|
|
|
for (i = 0 ; token_table[i].t ; ++i) {
|
|
|
|
if (!strncmp(token_table[i].t, *s, next-*s)) {
|
|
|
|
tok->tp = token_table[i].v;
|
|
|
|
i = 0;
|
|
|
|
done = (*next == '\n');
|
|
|
|
*s = eat_whitespace_no_nl(next);
|
|
|
|
while (**s != '\n' && i <= MAX_ARGS && !done) {
|
|
|
|
next = find_whitespace(*s);
|
|
|
|
if (*next == '\n')
|
|
|
|
done = 1;
|
|
|
|
*next = 0;
|
|
|
|
tok->val.cmd.args[i++] = *s;
|
|
|
|
*s = eat_whitespace_no_nl(next+1);
|
|
|
|
};
|
|
|
|
tok->val.cmd.n_args = i;
|
|
|
|
if (i > MAX_ARGS) {
|
|
|
|
tok->tp = _ERR;
|
|
|
|
tok->val.error = "Too many arguments"; return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tok->val.error = "Unrecognized command"; return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
router_dump_token(directory_token_t *tok) {
|
|
|
|
int i;
|
|
|
|
switch(tok->tp)
|
|
|
|
{
|
|
|
|
case _SIGNATURE:
|
|
|
|
puts("(signature)");
|
|
|
|
return;
|
|
|
|
case _PUBLIC_KEY:
|
|
|
|
puts("(public key)");
|
|
|
|
return;
|
|
|
|
case _ERR:
|
|
|
|
printf("(Error: %s\n)", tok->val.error);
|
|
|
|
return;
|
|
|
|
case _EOF:
|
|
|
|
puts("EOF");
|
|
|
|
return;
|
|
|
|
case K_ACCEPT: printf("Accept"); break;
|
|
|
|
case K_CLIENT_SOFTWARE: printf("Client-Software"); break;
|
|
|
|
case K_DIRECTORY_SIGNATURE: printf("Directory-Signature"); break;
|
|
|
|
case K_REJECT: printf("Reject"); break;
|
|
|
|
case K_ROUTER: printf("Router"); break;
|
|
|
|
case K_SERVER_SOFTWARE: printf("Server-Software"); break;
|
|
|
|
case K_SIGNED_DIRECTORY: printf("Signed-Directory"); break;
|
|
|
|
case K_SIGNING_KEY: printf("Signing-Key"); break;
|
|
|
|
default:
|
|
|
|
printf("?????? %d\n", tok->tp); return;
|
|
|
|
}
|
|
|
|
for (i = 0; i < tok->val.cmd.n_args; ++i) {
|
|
|
|
printf(" \"%s\"", tok->val.cmd.args[i]);
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG_ROUTER_TOKENS
|
|
|
|
static int
|
|
|
|
router_get_next_token(char **s, directory_token_t *tok) {
|
|
|
|
int i;
|
|
|
|
i = _router_get_next_token(s, tok);
|
|
|
|
router_dump_token(tok);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define router_get_next_token _router_get_next_token
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* return the first char of s that is not whitespace and not a comment */
|
|
|
|
static char *eat_whitespace(char *s) {
|
|
|
|
assert(s);
|
|
|
|
|
|
|
|
while(isspace(*s) || *s == '#') {
|
|
|
|
while(isspace(*s))
|
|
|
|
s++;
|
|
|
|
if(*s == '#') { /* read to a \n or \0 */
|
|
|
|
while(*s && *s != '\n')
|
|
|
|
s++;
|
|
|
|
if(!*s)
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *eat_whitespace_no_nl(char *s) {
|
|
|
|
while(*s == ' ' || *s == '\t')
|
|
|
|
++s;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* return the first char of s that is whitespace or '#' or '\0 */
|
|
|
|
static char *find_whitespace(char *s) {
|
|
|
|
assert(s);
|
|
|
|
|
|
|
|
while(*s && !isspace(*s) && *s != '#')
|
|
|
|
s++;
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2003-05-06 19:38:16 +02:00
|
|
|
int router_get_list_from_string(char *s)
|
|
|
|
{
|
|
|
|
return router_get_list_from_string_impl(s, &directory);
|
|
|
|
}
|
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
int router_get_list_from_string_impl(char *s, directory_t **dest) {
|
|
|
|
directory_token_t tok;
|
|
|
|
if (router_get_next_token(&s, &tok)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return router_get_list_from_string_tok(&s, dest, &tok);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int router_get_dir_hash(char *s, char *digest)
|
|
|
|
{
|
|
|
|
char *start, *end;
|
|
|
|
start = strstr(s, "signed-directory");
|
|
|
|
if (!start) return -1;
|
|
|
|
end = strstr(start, "directory-signature");
|
|
|
|
if (!end) return -1;
|
|
|
|
end = strchr(end, '\n');
|
|
|
|
if (!end) return -1;
|
|
|
|
++end;
|
|
|
|
|
|
|
|
if (crypto_SHA_digest(start, end-start, digest))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int router_get_dir_from_string(char *s, crypto_pk_env_t *pkey)
|
|
|
|
{
|
|
|
|
return router_get_dir_from_string_impl(s, &directory, pkey);
|
|
|
|
}
|
|
|
|
|
|
|
|
int router_get_dir_from_string_impl(char *s, directory_t **dest,
|
|
|
|
crypto_pk_env_t *pkey)
|
|
|
|
{
|
|
|
|
directory_token_t tok;
|
|
|
|
char digest[20];
|
|
|
|
char signed_digest[128];
|
|
|
|
|
|
|
|
#define NEXT_TOK() \
|
|
|
|
do { \
|
|
|
|
if (router_get_next_token(&s, &tok)) { \
|
|
|
|
log(LOG_ERR, "Error reading directory: %s", tok.val.error); \
|
|
|
|
return -1; \
|
|
|
|
} } while (0)
|
|
|
|
#define TOK_IS(type,name) \
|
|
|
|
do { \
|
|
|
|
if (tok.tp != type) { \
|
|
|
|
log(LOG_ERR, "Error reading directory: expected %s", name); \
|
|
|
|
return -1; \
|
|
|
|
} } while(0)
|
|
|
|
|
|
|
|
if (router_get_dir_hash(s, digest))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
NEXT_TOK();
|
|
|
|
TOK_IS(K_SIGNED_DIRECTORY, "signed-directory");
|
|
|
|
|
|
|
|
NEXT_TOK();
|
|
|
|
TOK_IS(K_CLIENT_SOFTWARE, "client-software");
|
|
|
|
|
|
|
|
NEXT_TOK();
|
|
|
|
TOK_IS(K_SERVER_SOFTWARE, "server-software");
|
|
|
|
|
|
|
|
NEXT_TOK();
|
|
|
|
if (router_get_list_from_string_tok(&s, dest, &tok))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
TOK_IS(K_DIRECTORY_SIGNATURE, "directory-signature");
|
|
|
|
NEXT_TOK();
|
|
|
|
TOK_IS(_SIGNATURE, "signature");
|
|
|
|
if (pkey) {
|
|
|
|
if (crypto_pk_public_checksig(pkey, tok.val.signature, 128, signed_digest)
|
|
|
|
!= 20) {
|
|
|
|
log(LOG_ERR, "Error reading directory: invalid signature.");
|
|
|
|
free(tok.val.signature);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (memcmp(digest, signed_digest, 20)) {
|
|
|
|
log(LOG_ERR, "Error reading directory: signature does not match.");
|
|
|
|
free(tok.val.signature);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(tok.val.signature);
|
|
|
|
|
|
|
|
NEXT_TOK();
|
|
|
|
TOK_IS(_EOF, "end of directory");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
#undef NEXT_TOK
|
|
|
|
#undef TOK_IS
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int router_get_list_from_string_tok(char **s, directory_t **dest,
|
|
|
|
directory_token_t *tok)
|
2003-05-06 19:38:16 +02:00
|
|
|
{
|
2002-09-26 14:09:10 +02:00
|
|
|
routerinfo_t *routerlist=NULL;
|
|
|
|
routerinfo_t *router;
|
|
|
|
routerinfo_t **new_router_array;
|
|
|
|
int new_rarray_len;
|
|
|
|
|
|
|
|
assert(s);
|
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
while (tok->tp == K_ROUTER) {
|
|
|
|
router = router_get_entry_from_string_tok(s, tok);
|
2002-10-03 00:54:20 +02:00
|
|
|
switch(router_is_me(router->addr, router->or_port)) {
|
|
|
|
case 0: /* it's not me */
|
|
|
|
router->next = routerlist;
|
|
|
|
routerlist = router;
|
|
|
|
break;
|
|
|
|
case 1: /* it is me */
|
|
|
|
if(!my_routerinfo) /* save it, so we can use it for directories */
|
|
|
|
my_routerinfo = router;
|
2002-12-03 06:12:30 +01:00
|
|
|
else
|
|
|
|
routerlist_free(router);
|
2002-10-03 00:54:20 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
log(LOG_ERR,"router_get_list_from_string(): router_is_me returned error.");
|
|
|
|
routerlist_free(routerlist);
|
|
|
|
return -1;
|
2002-06-27 00:45:49 +02:00
|
|
|
}
|
|
|
|
}
|
2002-09-26 14:09:10 +02:00
|
|
|
|
|
|
|
new_router_array = make_rarray(routerlist, &new_rarray_len);
|
|
|
|
if(new_router_array) { /* success! replace the old one */
|
2003-05-06 19:38:16 +02:00
|
|
|
if (*dest)
|
|
|
|
directory_free(*dest);
|
|
|
|
*dest = (directory_t*) malloc(sizeof(directory_t));
|
|
|
|
(*dest)->routers = new_router_array;
|
|
|
|
(*dest)->n_routers = new_rarray_len;
|
2002-09-26 14:09:10 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
2003-05-06 19:38:16 +02:00
|
|
|
static int
|
|
|
|
router_resolve(routerinfo_t *router)
|
|
|
|
{
|
|
|
|
struct hostent *rent;
|
|
|
|
|
|
|
|
rent = (struct hostent *)gethostbyname(router->address);
|
|
|
|
if (!rent) {
|
|
|
|
log(LOG_ERR,"router_resolve(): Could not get address for router %s.",router->address);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
assert(rent->h_length == 4);
|
|
|
|
memcpy(&router->addr, rent->h_addr,rent->h_length);
|
|
|
|
router->addr = ntohl(router->addr); /* get it back into host order */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
|
|
|
|
routerinfo_t *router_get_entry_from_string(char **s) {
|
|
|
|
directory_token_t tok;
|
|
|
|
routerinfo_t *router;
|
|
|
|
if (router_get_next_token(s, &tok)) return NULL;
|
|
|
|
router = router_get_entry_from_string_tok(s, &tok);
|
|
|
|
if (tok.tp != _EOF)
|
|
|
|
return NULL;
|
|
|
|
return router;
|
|
|
|
}
|
|
|
|
|
2002-09-24 12:43:57 +02:00
|
|
|
/* reads a single router entry from s.
|
|
|
|
* updates s so it points to after the router it just read.
|
|
|
|
* mallocs a new router, returns it if all goes well, else returns NULL.
|
|
|
|
*/
|
2003-05-07 20:30:46 +02:00
|
|
|
static routerinfo_t *router_get_entry_from_string_tok(char**s, directory_token_t *tok) {
|
|
|
|
routerinfo_t *router = NULL;
|
2003-05-06 19:38:16 +02:00
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
#define NEXT_TOKEN() \
|
|
|
|
do { if (router_get_next_token(s, tok)) goto err; \
|
|
|
|
} while(0)
|
|
|
|
|
|
|
|
#define ARGS tok->val.cmd.args
|
|
|
|
|
|
|
|
if (tok->tp != K_ROUTER) {
|
2003-05-06 19:38:16 +02:00
|
|
|
log(LOG_ERR,"router_get_entry_from_string(): Entry does not start with \"router\"");
|
|
|
|
return NULL;
|
|
|
|
}
|
2003-05-07 20:30:46 +02:00
|
|
|
if (!(router = malloc(sizeof(routerinfo_t)))) {
|
2002-09-24 12:43:57 +02:00
|
|
|
log(LOG_ERR,"router_get_entry_from_string(): Could not allocate memory.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
memset(router,0,sizeof(routerinfo_t)); /* zero it out first */
|
2003-05-06 19:38:16 +02:00
|
|
|
router->next = NULL;
|
2002-09-24 12:43:57 +02:00
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
if (tok->val.cmd.n_args != 6) {
|
|
|
|
log(LOG_ERR,"router_get_entry_from_string(): Wrong # of arguments to \"router\"");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read router.address */
|
|
|
|
if (!(router->address = strdup(ARGS[0])))
|
|
|
|
goto err;
|
2003-05-06 19:38:16 +02:00
|
|
|
router->addr = 0;
|
2002-09-24 12:43:57 +02:00
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
/* Read router->or_port */
|
|
|
|
router->or_port = atoi(ARGS[1]);
|
2002-09-24 12:43:57 +02:00
|
|
|
if(!router->or_port) {
|
2003-05-07 20:30:46 +02:00
|
|
|
log(LOG_ERR,"router_get_entry_from_string(): or_port unreadable or 0. Failing.");
|
|
|
|
goto err;
|
2002-09-24 12:43:57 +02:00
|
|
|
}
|
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
/* Router->op_port */
|
|
|
|
router->op_port = atoi(ARGS[2]);
|
2002-09-24 12:43:57 +02:00
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
/* Router->ap_port */
|
|
|
|
router->ap_port = atoi(ARGS[3]);
|
2002-09-24 12:43:57 +02:00
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
/* Router->dir_port */
|
|
|
|
router->dir_port = atoi(ARGS[4]);
|
2002-09-24 12:43:57 +02:00
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
/* Router->bandwidth */
|
|
|
|
router->bandwidth = atoi(ARGS[5]);
|
|
|
|
if (!router->bandwidth) {
|
|
|
|
log(LOG_ERR,"router_get_entry_from_string(): bandwidth unreadable or 0. Failing.");
|
2002-09-24 12:43:57 +02:00
|
|
|
}
|
2003-05-07 20:30:46 +02:00
|
|
|
|
2002-09-24 12:43:57 +02:00
|
|
|
log(LOG_DEBUG,"or_port %d, op_port %d, ap_port %d, dir_port %d, bandwidth %d.",
|
|
|
|
router->or_port, router->op_port, router->ap_port, router->dir_port, router->bandwidth);
|
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
NEXT_TOKEN();
|
|
|
|
if (tok->tp != _PUBLIC_KEY) {
|
|
|
|
log(LOG_ERR,"router_get_entry_from_string(): Missing public key");
|
|
|
|
goto err;
|
|
|
|
} /* Check key length */
|
|
|
|
router->pkey = tok->val.public_key;
|
|
|
|
|
|
|
|
NEXT_TOKEN();
|
|
|
|
if (tok->tp == K_SIGNING_KEY) {
|
|
|
|
NEXT_TOKEN();
|
|
|
|
if (tok->tp != _PUBLIC_KEY) {
|
|
|
|
log(LOG_ERR,"router_get_entry_from_string(): Missing signing key");
|
|
|
|
goto err;
|
2003-05-07 04:13:23 +02:00
|
|
|
}
|
2003-05-07 20:30:46 +02:00
|
|
|
router->signing_pkey = tok->val.public_key;
|
|
|
|
NEXT_TOKEN();
|
|
|
|
}
|
2003-05-07 04:13:23 +02:00
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
while (tok->tp == K_ACCEPT || tok->tp == K_REJECT) {
|
|
|
|
router_add_exit_policy(router, tok);
|
|
|
|
NEXT_TOKEN();
|
2003-04-07 06:38:19 +02:00
|
|
|
}
|
2003-05-07 20:30:46 +02:00
|
|
|
|
2003-04-07 06:38:19 +02:00
|
|
|
return router;
|
2002-09-24 12:43:57 +02:00
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
err:
|
2002-09-24 12:43:57 +02:00
|
|
|
if(router->address)
|
|
|
|
free(router->address);
|
|
|
|
if(router->pkey)
|
|
|
|
crypto_free_pk_env(router->pkey);
|
2003-04-07 06:38:19 +02:00
|
|
|
router_free_exit_policy(router);
|
2002-09-24 12:43:57 +02:00
|
|
|
free(router);
|
|
|
|
return NULL;
|
2003-05-07 20:30:46 +02:00
|
|
|
#undef ARGS
|
|
|
|
#undef NEXT_TOKEN
|
2002-09-24 12:43:57 +02:00
|
|
|
}
|
|
|
|
|
2003-04-07 06:38:19 +02:00
|
|
|
static void router_free_exit_policy(routerinfo_t *router) {
|
|
|
|
struct exit_policy_t *tmpe;
|
|
|
|
|
|
|
|
while(router->exit_policy) {
|
|
|
|
tmpe = router->exit_policy;
|
|
|
|
router->exit_policy = tmpe->next;
|
|
|
|
free(tmpe->string);
|
|
|
|
free(tmpe->address);
|
|
|
|
free(tmpe->port);
|
|
|
|
free(tmpe);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-09-24 12:43:57 +02:00
|
|
|
#if 0
|
|
|
|
void test_write_pkey(crypto_pk_env_t *pkey) {
|
|
|
|
char *string;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
log(LOG_DEBUG,"Trying test write.");
|
|
|
|
if(crypto_pk_write_public_key_to_string(pkey,&string,&len)<0) {
|
|
|
|
log(LOG_DEBUG,"router_get_entry_from_string(): write pkey to string failed\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
log(LOG_DEBUG,"I did it: len %d, string '%s'.",len,string);
|
|
|
|
free(string);
|
2002-06-27 00:45:49 +02:00
|
|
|
}
|
2002-09-24 12:43:57 +02:00
|
|
|
#endif
|
2002-07-22 06:08:37 +02:00
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
static int router_add_exit_policy(routerinfo_t *router,
|
|
|
|
directory_token_t *tok) {
|
2003-04-07 06:38:19 +02:00
|
|
|
struct exit_policy_t *tmpe, *newe;
|
2003-05-07 20:30:46 +02:00
|
|
|
char *arg, *colon;
|
2003-04-07 06:38:19 +02:00
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
if (tok->val.cmd.n_args != 1)
|
|
|
|
return -1;
|
|
|
|
arg = tok->val.cmd.args[0];
|
2003-04-07 06:38:19 +02:00
|
|
|
|
|
|
|
newe = malloc(sizeof(struct exit_policy_t));
|
|
|
|
memset(newe,0,sizeof(struct exit_policy_t));
|
2003-05-07 20:30:46 +02:00
|
|
|
|
|
|
|
newe->string = malloc(8+strlen(arg));
|
|
|
|
if (tok->tp == K_REJECT) {
|
|
|
|
strcpy(newe->string, "reject ");
|
2003-04-07 06:38:19 +02:00
|
|
|
newe->policy_type = EXIT_POLICY_REJECT;
|
|
|
|
} else {
|
2003-05-07 20:30:46 +02:00
|
|
|
assert(tok->tp == K_ACCEPT);
|
|
|
|
strcpy(newe->string, "accept ");
|
|
|
|
newe->policy_type = EXIT_POLICY_ACCEPT;
|
2003-04-07 06:38:19 +02:00
|
|
|
}
|
2003-05-07 20:30:46 +02:00
|
|
|
strcat(newe->string, arg);
|
|
|
|
|
|
|
|
colon = strchr(arg,':');
|
|
|
|
if(!colon)
|
2003-04-07 06:38:19 +02:00
|
|
|
goto policy_read_failed;
|
2003-05-07 20:30:46 +02:00
|
|
|
*colon = 0;
|
|
|
|
newe->address = strdup(arg);
|
|
|
|
newe->port = strdup(colon+1);
|
2003-04-07 06:38:19 +02:00
|
|
|
|
|
|
|
log(LOG_DEBUG,"router_add_exit_policy(): type %d, address '%s', port '%s'.",
|
|
|
|
newe->policy_type, newe->address, newe->port);
|
|
|
|
|
|
|
|
/* now link newe onto the end of exit_policy */
|
|
|
|
|
|
|
|
if(!router->exit_policy) {
|
|
|
|
router->exit_policy = newe;
|
2003-05-07 20:30:46 +02:00
|
|
|
return 0;
|
2003-04-07 06:38:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for(tmpe=router->exit_policy; tmpe->next; tmpe=tmpe->next) ;
|
|
|
|
tmpe->next = newe;
|
|
|
|
|
2003-05-07 20:30:46 +02:00
|
|
|
return 0;
|
2003-04-07 06:38:19 +02:00
|
|
|
|
|
|
|
policy_read_failed:
|
|
|
|
assert(newe->string);
|
|
|
|
log(LOG_INFO,"router_add_exit_policy(): Couldn't parse line '%s'. Dropping", newe->string);
|
|
|
|
if(newe->string)
|
|
|
|
free(newe->string);
|
|
|
|
if(newe->address)
|
|
|
|
free(newe->address);
|
|
|
|
if(newe->port)
|
|
|
|
free(newe->port);
|
|
|
|
free(newe);
|
2003-05-07 20:30:46 +02:00
|
|
|
return -1;
|
2003-04-07 06:38:19 +02:00
|
|
|
}
|
|
|
|
|
2003-04-08 08:44:38 +02:00
|
|
|
/* Return 0 if my exit policy says to allow connection to conn.
|
|
|
|
* Else return -1.
|
|
|
|
*/
|
|
|
|
int router_compare_to_exit_policy(connection_t *conn) {
|
|
|
|
struct exit_policy_t *tmpe;
|
|
|
|
|
|
|
|
if(!my_routerinfo) {
|
|
|
|
log(LOG_WARNING, "router_compare_to_exit_policy(): my_routerinfo undefined! Rejected.");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for(tmpe=my_routerinfo->exit_policy; tmpe; tmpe=tmpe->next) {
|
|
|
|
assert(tmpe->address);
|
|
|
|
assert(tmpe->port);
|
|
|
|
|
|
|
|
/* Totally ignore the address field of the exit policy, for now. */
|
|
|
|
|
|
|
|
if(!strcmp(tmpe->port,"*") || atoi(tmpe->port) == conn->port) {
|
|
|
|
log(LOG_INFO,"router_compare_to_exit_policy(): Port '%s' matches '%d'. %s.",
|
|
|
|
tmpe->port, conn->port,
|
|
|
|
tmpe->policy_type == EXIT_POLICY_ACCEPT ? "Accepting" : "Rejecting");
|
|
|
|
if(tmpe->policy_type == EXIT_POLICY_ACCEPT)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0; /* accept all by default. */
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2003-04-07 04:12:02 +02:00
|
|
|
/*
|
|
|
|
Local Variables:
|
|
|
|
mode:c
|
|
|
|
indent-tabs-mode:nil
|
|
|
|
c-basic-offset:2
|
|
|
|
End:
|
|
|
|
*/
|
2003-04-07 06:38:19 +02:00
|
|
|
|