Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ZerXes
Tor
Commits
0e0169d6
Commit
0e0169d6
authored
Sep 27, 2003
by
Nick Mathewson
🐻
Browse files
Write necessary backends for online directory generation. I think.
svn:r503
parent
cb8212bf
Changes
8
Hide whitespace changes
Inline
Side-by-side
src/or/Makefile.am
View file @
0e0169d6
...
...
@@ -5,14 +5,14 @@ noinst_PROGRAMS = test
bin_PROGRAMS
=
tor
tor_SOURCES
=
buffers.c circuit.c command.c connection.c
\
connection_or.c config.c
\
connection_or.c config.c
dirserv.c
\
onion.c routers.c directory.c dns.c connection_edge.c
\
cpuworker.c main.c tor_main.c
tor_LDADD
=
../common/libor.a
test_SOURCES
=
buffers.c circuit.c command.c connection.c
\
connection_or.c config.c
\
connection_or.c config.c
dirserv.c
\
onion.c routers.c directory.c dns.c connection_edge.c
\
cpuworker.c main.c test.c
...
...
src/or/connection.c
View file @
0e0169d6
...
...
@@ -110,6 +110,8 @@ void connection_free(connection_t *conn) {
crypto_free_pk_env
(
conn
->
link_pkey
);
if
(
conn
->
identity_pkey
)
crypto_free_pk_env
(
conn
->
identity_pkey
);
if
(
conn
->
nickname
)
free
(
conn
->
nickname
);
if
(
conn
->
s
>
0
)
{
log_fn
(
LOG_INFO
,
"closing fd %d."
,
conn
->
s
);
...
...
src/or/connection_or.c
View file @
0e0169d6
...
...
@@ -81,6 +81,7 @@ void connection_or_init_conn_from_router(connection_t *conn, routerinfo_t *route
conn
->
onion_pkey
=
crypto_pk_dup_key
(
router
->
onion_pkey
);
conn
->
link_pkey
=
crypto_pk_dup_key
(
router
->
link_pkey
);
conn
->
identity_pkey
=
crypto_pk_dup_key
(
router
->
identity_pkey
);
conn
->
nickname
=
strdup
(
router
->
nickname
);
if
(
conn
->
address
)
free
(
conn
->
address
);
conn
->
address
=
strdup
(
router
->
address
);
...
...
src/or/directory.c
View file @
0e0169d6
...
...
@@ -4,22 +4,17 @@
#include
"or.h"
#define MAX_DIR_SIZE 50000
/* XXX, big enough? */
static
int
directory_send_command
(
connection_t
*
conn
,
int
command
);
static
void
directory_rebuild
(
void
);
static
int
directory_handle_command
(
connection_t
*
conn
);
/********* START VARIABLES **********/
extern
or_options_t
options
;
/* command-line and config-file options */
static
char
the_directory
[
MAX_DIR_SIZE
+
1
];
static
int
directorylen
=
0
;
static
int
directory_dirty
=
1
;
static
char
fetchstring
[]
=
"GET / HTTP/1.0
\r\n\r\n
"
;
static
char
answerstring
[]
=
"HTTP/1.0 200 OK
\r\n\r\n
"
;
static
char
the_directory
[
MAX_DIR_SIZE
+
1
];
static
int
directorylen
=
0
;
/********* END VARIABLES ************/
...
...
@@ -115,25 +110,6 @@ static int directory_send_command(connection_t *conn, int command) {
return
0
;
}
void
directory_set_dirty
(
void
)
{
directory_dirty
=
1
;
}
static
void
directory_rebuild
(
void
)
{
if
(
directory_dirty
)
{
if
(
dump_signed_directory_to_string
(
the_directory
,
MAX_DIR_SIZE
,
get_identity_key
()))
{
log
(
LOG_WARNING
,
"Error creating directory"
);
return
;
}
directorylen
=
strlen
(
the_directory
);
log
(
LOG_INFO
,
"New directory (size %d):
\n
%s"
,
directorylen
,
the_directory
);
directory_dirty
=
0
;
}
else
{
log
(
LOG_INFO
,
"Directory still clean, reusing."
);
}
}
int
connection_dir_process_inbuf
(
connection_t
*
conn
)
{
assert
(
conn
&&
conn
->
type
==
CONN_TYPE_DIR
);
...
...
@@ -191,6 +167,8 @@ int connection_dir_process_inbuf(connection_t *conn) {
static
int
directory_handle_command
(
connection_t
*
conn
)
{
char
headers
[
1024
];
char
body
[
50000
];
/* XXX */
size_t
dl
;
const
char
*
cp
;
assert
(
conn
&&
conn
->
type
==
CONN_TYPE_DIR
);
...
...
@@ -209,16 +187,16 @@ static int directory_handle_command(connection_t *conn) {
if
(
!
strncasecmp
(
headers
,
"GET"
,
3
))
{
/* XXX should check url and http version */
d
irectory_rebuild
();
/* rebuild it now, iff it's dirty */
d
l
=
dirserv_get_directory
(
&
cp
);
if
(
d
irectorylen
==
0
)
{
if
(
d
l
==
0
)
{
log_fn
(
LOG_WARNING
,
"My directory is empty. Closing."
);
return
-
1
;
}
log_fn
(
LOG_DEBUG
,
"Dumping directory to client."
);
if
((
connection_write_to_buf
(
answerstring
,
strlen
(
answerstring
),
conn
)
<
0
)
||
(
connection_write_to_buf
(
the_directory
,
directorylen
,
conn
)
<
0
))
{
(
connection_write_to_buf
(
cp
,
dl
,
conn
)
<
0
))
{
log_fn
(
LOG_WARNING
,
"Failed to write answerstring+directory to outbuf."
);
return
-
1
;
}
...
...
src/or/dirserv.c
0 → 100644
View file @
0e0169d6
/* Copyright 2001,2002,2003 Roger Dingledine, Matej Pfajfar. */
/* See LICENSE for licensing information */
/* $Id$ */
#include
"or.h"
static
int
the_directory_is_dirty
=
1
;
static
char
*
the_directory
=
NULL
;
static
int
the_directory_len
=
-
1
;
/*
* Fingerprint handling code.
*/
typedef
struct
fingerprint_entry_t
{
char
*
nickname
;
char
*
fingerprint
;
}
fingerprint_entry_t
;
static
fingerprint_entry_t
fingerprint_list
[
MAX_ROUTERS_IN_DIR
];
static
int
n_fingerprints
=
0
;
/* return 0 on success, -1 on failure */
int
dirserv_parse_fingerprint_file
(
const
char
*
fname
)
{
FILE
*
file
;
#define BUF_LEN (FINGERPRINT_LEN+MAX_NICKNAME_LEN+20)
char
buf
[
BUF_LEN
+
1
];
char
*
cp
,
*
nickname
,
*
fingerprint
;
fingerprint_entry_t
fingerprint_list_tmp
[
MAX_ROUTERS_IN_DIR
];
int
n_fingerprints_tmp
=
0
;
int
lineno
=
0
;
int
i
;
if
(
!
(
file
=
fopen
(
fname
,
"r"
)))
{
log
(
LOG_WARNING
,
"Cannot open fingerprint file %s"
,
fname
);
goto
err
;
}
while
(
1
)
{
cp
=
fgets
(
buf
,
BUF_LEN
,
file
);
++
lineno
;
if
(
!
cp
)
{
if
(
feof
(
file
))
break
;
else
{
log
(
LOG_WARNING
,
"Error reading from fingerprint file"
);
goto
err
;
}
}
buf
[
BUF_LEN
]
=
'\0'
;
cp
=
buf
;
while
(
isspace
(
*
cp
))
++
cp
;
if
(
*
cp
==
'#'
||
*
cp
==
'\0'
)
continue
;
nickname
=
cp
;
cp
=
strchr
(
cp
,
' '
);
if
(
!
cp
)
{
log
(
LOG_WARNING
,
"Bad line %d of fingerprint file"
,
lineno
);
goto
err
;
}
*
cp
++
=
'\0'
;
while
(
isspace
(
*
cp
))
++
cp
;
if
(
strlen
(
cp
)
<
FINGERPRINT_LEN
)
{
log
(
LOG_WARNING
,
"Bad line %d of fingerprint file"
,
lineno
);
goto
err
;
}
fingerprint
=
cp
;
cp
[
FINGERPRINT_LEN
]
=
'\0'
;
if
(
strlen
(
nickname
)
>
MAX_NICKNAME_LEN
)
{
log
(
LOG_WARNING
,
"Nickname too long on line %d of fingerprint file"
,
lineno
);
goto
err
;
}
if
(
!
crypto_pk_check_fingerprint_syntax
(
fingerprint
))
{
log
(
LOG_WARNING
,
"Invalid fingerprint on line %d of fingerprint file"
,
lineno
);
goto
err
;
}
for
(
i
=
0
;
i
<
n_fingerprints_tmp
;
++
i
)
{
if
(
0
==
strcasecmp
(
fingerprint_list_tmp
[
i
].
nickname
,
nickname
))
{
log
(
LOG_WARNING
,
"Duplicate nickname on line %d of fingerprint file"
,
lineno
);
goto
err
;
}
}
fingerprint_list_tmp
[
n_fingerprints_tmp
].
nickname
=
strdup
(
nickname
);
fingerprint_list_tmp
[
n_fingerprints_tmp
].
fingerprint
=
strdup
(
fingerprint
);
++
n_fingerprints_tmp
;
}
/* replace the global fingerprints list. */
dirserv_free_fingerprint_list
();
memcpy
(
fingerprint_list
,
fingerprint_list_tmp
,
sizeof
(
fingerprint_entry_t
)
*
n_fingerprints_tmp
);
n_fingerprints
=
n_fingerprints_tmp
;
return
0
;
err:
for
(
i
=
0
;
i
<
n_fingerprints_tmp
;
++
i
)
{
free
(
fingerprint_list_tmp
[
i
].
nickname
);
free
(
fingerprint_list_tmp
[
i
].
fingerprint
);
}
return
-
1
;
#undef BUF_LEN
}
/* return 1 if router's identity and nickname match. */
int
dirserv_router_fingerprint_is_known
(
const
routerinfo_t
*
router
)
{
int
i
;
fingerprint_entry_t
*
ent
=
NULL
;
char
fp
[
FINGERPRINT_LEN
+
1
];
for
(
i
=
0
;
i
<
n_fingerprints
;
++
i
)
{
if
(
!
strcasecmp
(
router
->
nickname
,
fingerprint_list
[
i
].
nickname
))
{
ent
=
&
fingerprint_list
[
i
];
break
;
}
}
if
(
!
ent
)
{
/* No such server known */
return
0
;
}
if
(
crypto_pk_get_fingerprint
(
router
->
identity_pkey
,
fp
))
{
/* XXX Error computing fingerprint: log */
return
0
;
}
if
(
0
==
strcasecmp
(
ent
->
fingerprint
,
fp
))
{
/* Right fingerprint. */
return
1
;
}
else
{
/* Wrong fingerprint. */
return
0
;
}
}
void
dirserv_free_fingerprint_list
()
{
int
i
;
for
(
i
=
0
;
i
<
n_fingerprints
;
++
i
)
{
free
(
fingerprint_list
[
i
].
nickname
);
free
(
fingerprint_list
[
i
].
fingerprint
);
}
n_fingerprints
=
0
;
}
/*
* Descriptor list
*/
typedef
struct
descriptor_entry_t
{
char
*
nickname
;
time_t
published
;
size_t
desc_len
;
char
*
descriptor
;
}
descriptor_entry_t
;
static
descriptor_entry_t
*
descriptor_list
[
MAX_ROUTERS_IN_DIR
];
static
int
n_descriptors
=
0
;
static
void
free_descriptor_entry
(
descriptor_entry_t
*
desc
)
{
if
(
desc
->
descriptor
)
free
(
desc
->
descriptor
);
if
(
desc
->
nickname
)
free
(
desc
->
nickname
);
free
(
desc
);
}
void
dirserv_free_descriptors
()
{
int
i
;
for
(
i
=
0
;
i
<
n_descriptors
;
++
i
)
{
free_descriptor_entry
(
descriptor_list
[
i
]);
}
n_descriptors
=
0
;
}
/* Return 0 if descriptor added; -1 if descriptor rejected. Updates *desc
* to point after the descriptor if the descriptor is OK.
*/
int
dirserv_add_descriptor
(
const
char
**
desc
)
{
descriptor_entry_t
**
desc_ent_ptr
;
routerinfo_t
*
ri
=
NULL
;
int
i
;
char
*
start
,
*
end
;
char
*
desc_tmp
=
NULL
;
size_t
desc_len
;
start
=
strstr
(
*
desc
,
"router "
);
if
(
!
start
)
{
log
(
LOG_WARNING
,
"no descriptor found."
);
goto
err
;
}
end
=
strstr
(
start
+
6
,
"
\n
router "
);
if
(
end
)
{
++
end
;
/* Include NL. */
}
else
{
end
=
start
+
strlen
(
start
);
}
desc_len
=
end
-
start
;
desc_tmp
=
tor_malloc
(
desc_len
+
1
);
strncpy
(
desc_tmp
,
start
,
desc_len
);
desc_tmp
[
desc_len
]
=
'\0'
;
/* Check: is the descriptor syntactically valid? */
ri
=
router_get_entry_from_string
(
&
desc_tmp
);
if
(
!
ri
)
{
log
(
LOG_WARNING
,
"Couldn't parse descriptor"
);
goto
err
;
}
free
(
desc_tmp
);
desc_tmp
=
NULL
;
/* Okay. Now check whether the fingerprint is recognized. */
if
(
!
dirserv_router_fingerprint_is_known
(
ri
))
{
log
(
LOG_WARNING
,
"Identity is unrecognized for descriptor"
);
goto
err
;
}
/* Do we already have an entry for this router? */
desc_ent_ptr
=
NULL
;
for
(
i
=
0
;
i
<
n_descriptors
;
++
i
)
{
if
(
!
strcasecmp
(
ri
->
nickname
,
descriptor_list
[
i
]
->
nickname
))
{
desc_ent_ptr
=
&
descriptor_list
[
i
];
break
;
}
}
if
(
desc_ent_ptr
)
{
/* if so, decide whether to update it. */
if
((
*
desc_ent_ptr
)
->
published
>
ri
->
published_on
)
{
/* We already have a newer descriptor */
goto
err
;
}
/* We don't have a newer one; we'll update this one. */
free_descriptor_entry
(
*
desc_ent_ptr
);
}
else
{
/* Add this at the end. */
desc_ent_ptr
=
&
descriptor_list
[
n_descriptors
++
];
}
(
*
desc_ent_ptr
)
=
tor_malloc
(
sizeof
(
descriptor_entry_t
));
(
*
desc_ent_ptr
)
->
nickname
=
ri
->
nickname
;
(
*
desc_ent_ptr
)
->
published
=
ri
->
published_on
;
(
*
desc_ent_ptr
)
->
desc_len
=
desc_len
;
(
*
desc_ent_ptr
)
->
descriptor
=
tor_malloc
(
desc_len
+
1
);
strncpy
((
*
desc_ent_ptr
)
->
descriptor
,
start
,
desc_len
);
(
*
desc_ent_ptr
)
->
descriptor
[
desc_len
]
=
'\0'
;
*
desc
=
end
;
the_directory_is_dirty
=
1
;
routerinfo_free
(
ri
);
return
0
;
err:
if
(
desc_tmp
)
free
(
desc_tmp
);
if
(
ri
)
routerinfo_free
(
ri
);
return
-
1
;
}
void
directory_set_dirty
()
{
the_directory_is_dirty
=
1
;
}
int
dirserv_init_from_directory_string
(
const
char
*
dir
)
{
const
char
*
cp
=
dir
;
while
(
1
)
{
cp
=
strstr
(
cp
,
"
\n
router "
);
if
(
!
cp
)
break
;
++
cp
;
if
(
dirserv_add_descriptor
(
&
cp
))
{
return
-
1
;
}
--
cp
;
/*Back up to newline.*/
}
return
0
;
}
int
dirserv_dump_directory_to_string
(
char
*
s
,
int
maxlen
,
crypto_pk_env_t
*
private_key
)
{
char
*
cp
,
*
eos
;
char
digest
[
20
];
char
signature
[
128
];
char
published
[
33
];
time_t
published_on
;
int
i
;
eos
=
s
+
maxlen
;
if
(
list_running_servers
(
&
cp
))
return
-
1
;
published_on
=
time
(
NULL
);
strftime
(
published
,
32
,
"%Y-%m-%d %H:%M:%S"
,
gmtime
(
&
published_on
));
snprintf
(
s
,
maxlen
,
"signed-directory
\n
"
"published %s
\n
"
"recommended-software "
RECOMMENDED_SOFTWARE_VERSIONS
"
\n
"
"running-routers %s
\n
"
,
published
,
cp
);
free
(
cp
);
i
=
strlen
(
s
);
cp
=
s
+
i
;
for
(
i
=
0
;
i
<
n_descriptors
;
++
i
)
{
strncat
(
cp
,
descriptor_list
[
i
]
->
descriptor
,
descriptor_list
[
i
]
->
desc_len
);
cp
+=
descriptor_list
[
i
]
->
desc_len
;
assert
(
!
cp
);
}
/* These multiple strlen calls are inefficient, but dwarfed by the RSA
signature.
*/
i
=
strlen
(
s
);
strncat
(
s
,
"directory-signature
\n
"
,
maxlen
-
i
);
i
=
strlen
(
s
);
cp
=
s
+
i
;
if
(
crypto_SHA_digest
(
s
,
i
,
digest
))
{
log_fn
(
LOG_WARNING
,
"couldn't compute digest"
);
return
-
1
;
}
if
(
crypto_pk_private_sign
(
private_key
,
digest
,
20
,
signature
)
<
0
)
{
log_fn
(
LOG_WARNING
,
"couldn't sign digest"
);
return
-
1
;
}
strncpy
(
cp
,
"-----BEGIN SIGNATURE-----
\n
"
,
maxlen
-
i
);
i
=
strlen
(
s
);
cp
=
s
+
i
;
if
(
base64_encode
(
cp
,
maxlen
-
i
,
signature
,
128
)
<
0
)
{
log_fn
(
LOG_WARNING
,
" couldn't base64-encode signature"
);
return
-
1
;
}
i
=
strlen
(
s
);
cp
=
s
+
i
;
strncat
(
cp
,
"-----END SIGNATURE-----
\n
"
,
maxlen
-
i
);
i
=
strlen
(
s
);
if
(
i
==
maxlen
)
{
log_fn
(
LOG_WARNING
,
"tried to exceed string length."
);
return
-
1
;
}
return
0
;
}
size_t
dirserv_get_directory
(
const
char
**
directory
)
{
char
*
new_directory
;
if
(
the_directory_is_dirty
)
{
new_directory
=
tor_malloc
(
MAX_DIR_SIZE
);
if
(
dirserv_dump_directory_to_string
(
new_directory
,
MAX_DIR_SIZE
,
get_identity_key
()))
{
log
(
LOG_WARNING
,
"Error creating directory."
);
free
(
new_directory
);
return
0
;
}
if
(
the_directory
)
free
(
the_directory
);
the_directory
=
new_directory
;
the_directory_len
=
strlen
(
the_directory
);
log_fn
(
LOG_INFO
,
"New directory (size %d):
\n
%s"
,
the_directory_len
,
the_directory
);
the_directory_is_dirty
=
0
;
/* Now read the directory we just made in order to update our own
* router lists. This does more signature checking than is strictly
* necessary, but safe is better than sorry. */
new_directory
=
strdup
(
*
directory
);
if
(
router_get_dir_from_string
(
new_directory
,
get_identity_key
()))
{
log_fn
(
LOG_ERR
,
"We just generated a directory we can't parse. Dying."
);
exit
(
0
);
}
free
(
new_directory
);
}
else
{
log
(
LOG_INFO
,
"Directory still clean, reusing."
);
}
*
directory
=
the_directory
;
return
the_directory_len
;
}
src/or/main.c
View file @
0e0169d6
...
...
@@ -741,11 +741,12 @@ int dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
strftime
(
published
,
32
,
"%Y-%m-%d %H:%M:%S"
,
gmtime
(
&
router
->
published_on
));
result
=
snprintf
(
s
,
maxlen
,
"router %s %d %d %d %d
\n
"
"router %s
%s
%d %d %d %d
\n
"
"published %s
\n
"
"onion-key
\n
%s"
"link-key
\n
%s"
"signing-key
\n
%s"
,
router
->
nickname
,
router
->
address
,
router
->
or_port
,
router
->
ap_port
,
...
...
@@ -805,126 +806,36 @@ int dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
return
written
+
1
;
}
static
int
build_directory
(
directory_t
*
dir
)
{
routerinfo_t
**
routers
=
NULL
;
int
list_running_servers
(
char
**
nicknames_out
)
{
char
*
nickname_lst
[
MAX_ROUTERS_IN_DIR
];
connection_t
*
conn
;
routerinfo_t
*
router
;
int
i
,
n
=
0
;
routers
=
(
routerinfo_t
**
)
tor_malloc
(
sizeof
(
routerinfo_t
*
)
*
(
nfds
+
1
));
if
(
my_routerinfo
)
{
log
(
LOG_INFO
,
"build_directory(): adding self (%s:%d)"
,
my_routerinfo
->
address
,
my_routerinfo
->
or_port
);
routers
[
n
++
]
=
my_routerinfo
;
}
for
(
i
=
0
;
i
<
nfds
;
++
i
)
{
char
*
cp
;
int
n
=
0
,
i
;
int
length
;
*
nicknames_out
=
NULL
;
if
(
my_routerinfo
)
nickname_lst
[
n
++
]
=
my_routerinfo
->
nickname
;
for
(
i
=
0
;
i
<
nfds
;
++
i
)
{
conn
=
connection_array
[
i
];
if
(
conn
->
type
!=
CONN_TYPE_OR
)
continue
;
/* we only want to list ORs */
if
(
conn
->
state
!=
OR_CONN_STATE_OPEN
)
continue
;
/* we only want to list ones that successfully handshaked */
router
=
router_get_by_addr_port
(
conn
->
addr
,
conn
->
port
);
if
(
!
router
)
{
/* XXX this legitimately happens when conn is an OP. How to detect this? */
log
(
LOG_INFO
,
"build_directory(): couldn't find router %d:%d!"
,
conn
->
addr
,
conn
->
port
);
continue
;
}
log
(
LOG_INFO
,
"build_directory(): adding router (%s:%d)"
,
router
->
address
,
router
->
or_port
);
routers
[
n
++
]
=
router
;
if
(
conn
->
type
!=
CONN_TYPE_OR
||
conn
->
state
!=
OR_CONN_STATE_OPEN
)
continue
;
/* only list successfully handshaked OR's. */
nickname_lst
[
n
++
]
=
conn
->
nickname
;
}
length
=
n
+
1
;
/* spaces + EOS + 1. */
for
(
i
=
0
;
i
<
n
;
++
i
)
{
length
+=
strlen
(
nickname_lst
[
i
]);
}
*
nicknames_out
=
tor_malloc
(
length
);
cp
=
*
nicknames_out
;
for
(
i
=
0
;
i
<
n
;
++
i
)
{
if
(
i
)
strcat
(
cp
,
" "
);
strcat
(
cp
,
nickname_lst
[
i
]);
while
(
*
cp
)
++
cp
;
}
dir
->
routers
=
routers
;
dir
->
n_routers
=
n
;
return
0
;
}
int
dump_signed_directory_to_string
(
char
*
s
,
int
maxlen
,
crypto_pk_env_t
*
private_key
)
{
directory_t
dir
;
if
(
build_directory
(
&
dir
))
{
log
(
LOG_WARNING
,
"dump_signed_directory_to_string(): build_directory failed."
);
return
-
1
;
}
return
dump_signed_directory_to_string_impl
(
s
,
maxlen
,
&
dir
,
private_key
);
}
int
dump_signed_directory_to_string_impl
(
char
*
s
,
int
maxlen
,
directory_t
*
dir
,
crypto_pk_env_t
*
private_key
)
{
char
*
cp
,
*
eos
;
char
digest
[
20
];
char
signature
[
128
];
int
i
,
written
;
routerinfo_t
*
router
;
eos
=
s
+
maxlen
;
strncpy
(
s
,
"signed-directory
\n
"
"recommended-software "
RECOMMENDED_SOFTWARE_VERSIONS
"
\n
"
,
maxlen
);
i
=
strlen
(
s
);
cp
=
s
+
i
;
for
(
i
=
0
;
i
<
dir
->
n_routers
;
++
i
)
{
router
=
dir
->
routers
[
i
];
/* XXX This is wrong; we shouldn't sign routers, but rather propagate
* XXX the original router blocks, unaltered.
*/
written
=
dump_router_to_string
(
cp
,
eos
-
cp
,
router
,
private_key
);
if
(
written
<
0
)
{
log
(
LOG_WARNING
,
"dump_signed_directory_to_string(): tried to exceed string length."
);