[or-cvs] r11654: Backend for descriptor annotations: parse annotations as key (in tor/trunk: . src/or)
nickm at seul.org
nickm at seul.org
Wed Sep 26 16:19:44 UTC 2007
Author: nickm
Date: 2007-09-26 12:19:44 -0400 (Wed, 26 Sep 2007)
New Revision: 11654
Modified:
tor/trunk/
tor/trunk/src/or/dirserv.c
tor/trunk/src/or/or.h
tor/trunk/src/or/router.c
tor/trunk/src/or/routerlist.c
tor/trunk/src/or/routerparse.c
tor/trunk/src/or/test.c
Log:
r15400 at catbus: nickm | 2007-09-26 12:13:12 -0400
Backend for descriptor annotations: parse annotations as keywords; only allow them to appear in the cache; do not serve them as part of the descriptor if we are a dirserver. Still need mechanism to set annotations. Still need to rename cache file.
Property changes on: tor/trunk
___________________________________________________________________
svk:merge ticket from /tor/trunk [r15400] on 8246c3cf-6607-4228-993b-4d95d33730f1
Modified: tor/trunk/src/or/dirserv.c
===================================================================
--- tor/trunk/src/or/dirserv.c 2007-09-26 14:52:10 UTC (rev 11653)
+++ tor/trunk/src/or/dirserv.c 2007-09-26 16:19:44 UTC (rev 11654)
@@ -536,7 +536,7 @@
s = desc;
list = smartlist_create();
- if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 0)) {
+ if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 0, 0)) {
SMARTLIST_FOREACH(list, routerinfo_t *, ri, {
msg_out = NULL;
@@ -561,7 +561,7 @@
smartlist_clear(list);
s = desc;
- if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 1)) {
+ if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 1, 0)) {
SMARTLIST_FOREACH(list, extrainfo_t *, ei, {
msg_out = NULL;
Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h 2007-09-26 14:52:10 UTC (rev 11653)
+++ tor/trunk/src/or/or.h 2007-09-26 16:19:44 UTC (rev 11654)
@@ -20,23 +20,15 @@
#define WIN32_LEAN_AND_MEAN
#endif
-// #include <stdio.h>
-// #include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-//#ifdef HAVE_STRING_H
-//#include <string.h>
-//#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
-//#ifdef HAVE_CTYPE_H
-//#include <ctype.h>
-//#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h> /* FreeBSD needs this to know what version it is */
#endif
@@ -53,21 +45,12 @@
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
-//#ifdef HAVE_SYS_SOCKET_H
-//#include <sys/socket.h>
-//#endif
#ifdef HAVE_SYS_UN_H
#include <sys/un.h>
#endif
-//#ifdef HAVE_SYS_TIME_H
-//#include <sys/time.h>
-//#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
-//#ifdef HAVE_NETINET_IN_H
-//#include <netinet/in.h>
-//#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
@@ -91,26 +74,7 @@
#define MAXCONNECTIONS 15000
#endif
-#if 0
#ifdef MS_WINDOWS
-/* No, we don't need to redefine FD_SETSIZE before including winsock:
- * we use libevent now, and libevent handles the select() stuff. Yes,
- * some documents imply that we need to redefine anyway if we're using
- * select() anywhere in our application or in anything it links to: these
- * documents are either the holy texts of a cargo cult of network
- * programmers, or more likely a simplification of what's going on for
- * people who haven't read winsock[2].h for themselves.
- */
-#if defined(_MSC_VER) && (_MSC_VER <= 1300)
-#include <winsock.h>
-#else
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#endif
-#endif
-#endif
-
-#ifdef MS_WINDOWS
#include <io.h>
#include <process.h>
#include <direct.h>
@@ -1118,9 +1082,12 @@
/** Information need to cache an onion router's descriptor. */
typedef struct signed_descriptor_t {
- /** Pointer to the raw server descriptor. Not necessarily NUL-terminated.
- * If saved_location is SAVED_IN_CACHE, this pointer is null. */
+ /** Pointer to the raw server descriptor, preceeded by annotatinos. Not
+ * necessarily NUL-terminated. If saved_location is SAVED_IN_CACHE, this
+ * pointer is null. */
char *signed_descriptor_body;
+ /** Length of the annotations preceeding the server descriptor. */
+ size_t annotations_len;
/** Length of the server descriptor. */
size_t signed_descriptor_len;
/** Digest of the server descriptor, computed as specified in dir-spec.txt */
@@ -1135,7 +1102,7 @@
* extrainfo. */
download_status_t ei_dl_status;
/** Where is the descriptor saved? */
- saved_location_t saved_location ;
+ saved_location_t saved_location;
/** If saved_location is SAVED_IN_CACHE or SAVED_IN_JOURNAL, the offset of
* this descriptor in the corresponding file. */
off_t saved_offset;
@@ -2894,10 +2861,6 @@
const char *identity);
int networkstatus_check_consensus_signature(networkstatus_vote_t *consensus,
int warn);
-#if 0
-int networkstatus_add_consensus_signatures(networkstatus_vote_t *target,
- networkstatus_vote_t *src);
-#endif
int networkstatus_add_detached_signatures(networkstatus_vote_t *target,
ns_detached_signatures_t *sigs);
char *networkstatus_get_detached_signatures(networkstatus_vote_t *consensus);
@@ -3639,7 +3602,8 @@
int router_parse_list_from_string(const char **s, const char *eos,
smartlist_t *dest,
saved_location_t saved_location,
- int is_extrainfo);
+ int is_extrainfo,
+ int allow_annotations);
int router_parse_routerlist_from_directory(const char *s,
routerlist_t **dest,
crypto_pk_env_t *pkey,
@@ -3648,7 +3612,8 @@
int router_parse_runningrouters(const char *str);
int router_parse_directory(const char *str);
routerinfo_t *router_parse_entry_from_string(const char *s, const char *end,
- int cache_copy);
+ int cache_copy,
+ int allow_annotations);
extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end,
int cache_copy, struct digest_ri_map_t *routermap);
addr_policy_t *router_parse_addr_policy_from_string(const char *s,
Modified: tor/trunk/src/or/router.c
===================================================================
--- tor/trunk/src/or/router.c 2007-09-26 14:52:10 UTC (rev 11653)
+++ tor/trunk/src/or/router.c 2007-09-26 16:19:44 UTC (rev 11654)
@@ -485,7 +485,7 @@
return -1;
}
if (mydesc) {
- ri = router_parse_entry_from_string(mydesc, NULL, 1);
+ ri = router_parse_entry_from_string(mydesc, NULL, 1, 0);
if (!ri) {
log_err(LD_GENERAL,"Generated a routerinfo we couldn't parse.");
return -1;
@@ -1632,7 +1632,7 @@
const char *cp;
routerinfo_t *ri_tmp;
cp = s_dup = tor_strdup(s);
- ri_tmp = router_parse_entry_from_string(cp, NULL, 1);
+ ri_tmp = router_parse_entry_from_string(cp, NULL, 1, 0);
if (!ri_tmp) {
log_err(LD_BUG,
"We just generated a router descriptor we can't parse.");
Modified: tor/trunk/src/or/routerlist.c
===================================================================
--- tor/trunk/src/or/routerlist.c 2007-09-26 14:52:10 UTC (rev 11653)
+++ tor/trunk/src/or/routerlist.c 2007-09-26 16:19:44 UTC (rev 11654)
@@ -43,6 +43,8 @@
int warn_if_unnamed);
static void update_router_have_minimum_dir_info(void);
static void router_dir_info_changed(void);
+static const char *signed_descriptor_get_body_impl(signed_descriptor_t *desc,
+ int with_annotations);
DECLARE_TYPED_DIGESTMAP_FNS(sdmap_, digest_sd_map_t, signed_descriptor_t)
DECLARE_TYPED_DIGESTMAP_FNS(rimap_, digest_ri_map_t, routerinfo_t)
@@ -522,8 +524,8 @@
or_options_t *options = get_options();
size_t fname_len = strlen(options->DataDirectory)+32;
char *fname;
- const char *body = signed_descriptor_get_body(desc);
- size_t len = desc->signed_descriptor_len;
+ const char *body = signed_descriptor_get_body_impl(desc,1);
+ size_t len = desc->signed_descriptor_len + desc->annotations_len;
if (purpose != ROUTER_PURPOSE_GENERAL &&
purpose != EXTRAINFO_PURPOSE_GENERAL) {
@@ -629,7 +631,7 @@
SMARTLIST_FOREACH(signed_descriptors, signed_descriptor_t *, sd,
{
sized_chunk_t *c;
- const char *body = signed_descriptor_get_body(sd);
+ const char *body = signed_descriptor_get_body_impl(sd, 1);
if (!body) {
log_warn(LD_BUG, "No descriptor available for router.");
goto done;
@@ -638,7 +640,7 @@
continue;
c = tor_malloc(sizeof(sized_chunk_t));
c->bytes = body;
- c->len = sd->signed_descriptor_len;
+ c->len = sd->signed_descriptor_len + sd->annotations_len;
smartlist_add(chunk_list, c);
});
@@ -1965,21 +1967,29 @@
/** Return a pointer to the signed textual representation of a descriptor.
* The returned string is not guaranteed to be NUL-terminated: the string's
* length will be in desc-\>signed_descriptor_len. */
-const char *
-signed_descriptor_get_body(signed_descriptor_t *desc)
+static const char *
+signed_descriptor_get_body_impl(signed_descriptor_t *desc,
+ int with_annotations)
{
const char *r = NULL;
size_t len = desc->signed_descriptor_len;
+ off_t offset = desc->saved_offset;
+ if (with_annotations)
+ len += desc->annotations_len;
+ else
+ offset += desc->annotations_len;
+
tor_assert(len > 32);
if (desc->saved_location == SAVED_IN_CACHE && routerlist) {
desc_store_t *store = desc_get_store(router_get_routerlist(), desc);
if (store && store->mmap) {
tor_assert(desc->saved_offset + len <= store->mmap->size);
- r = store->mmap->data + desc->saved_offset;
+ r = store->mmap->data + offset;
}
}
if (!r) /* no mmap, or not in cache. */
- r = desc->signed_descriptor_body;
+ r = desc->signed_descriptor_body +
+ (with_annotations ? 0 : desc->annotations_len);
tor_assert(r);
if (memcmp("router ", r, 7) && memcmp("extra-info ", r, 11)) {
@@ -1991,6 +2001,13 @@
return r;
}
+/** DOCDOC */
+const char *
+signed_descriptor_get_body(signed_descriptor_t *desc)
+{
+ return signed_descriptor_get_body_impl(desc, 0);
+}
+
/** Return the current list of all known routers. */
routerlist_t *
router_get_routerlist(void)
@@ -3089,7 +3106,7 @@
tor_assert(msg);
*msg = NULL;
- if (!(ri = router_parse_entry_from_string(s, NULL, 1))) {
+ if (!(ri = router_parse_entry_from_string(s, NULL, 1, 0))) {
log_warn(LD_DIR, "Error parsing router descriptor; dropping.");
*msg = "Couldn't parse router descriptor.";
return -1;
@@ -3147,8 +3164,10 @@
char fp[HEX_DIGEST_LEN+1];
const char *msg;
int from_cache = (saved_location != SAVED_NOWHERE);
+ int allow_annotations = (saved_location != SAVED_NOWHERE);
- router_parse_list_from_string(&s, eos, routers, saved_location, 0);
+ router_parse_list_from_string(&s, eos, routers, saved_location, 0,
+ allow_annotations);
routers_update_status_from_networkstatus(routers, !from_cache);
@@ -3209,7 +3228,7 @@
const char *msg;
int from_cache = (saved_location != SAVED_NOWHERE);
- router_parse_list_from_string(&s, eos, extrainfo_list, saved_location, 1);
+ router_parse_list_from_string(&s, eos, extrainfo_list, saved_location, 1, 0);
log_info(LD_DIR, "%d elements to add", smartlist_len(extrainfo_list));
Modified: tor/trunk/src/or/routerparse.c
===================================================================
--- tor/trunk/src/or/routerparse.c 2007-09-26 14:52:10 UTC (rev 11653)
+++ tor/trunk/src/or/routerparse.c 2007-09-26 16:19:44 UTC (rev 11654)
@@ -1,4 +1,4 @@
-/* oCpyright (c) 2001 Matej Pfajfar.
+/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2007, Roger Dingledine, Nick Mathewson. */
/* See LICENSE for licensing information */
@@ -15,11 +15,9 @@
/****************************************************************************/
-/** Enumeration of possible token types. The ones starting with K_
- * correspond to directory 'keywords'. _UNRECOGNIZED is for an
- * unrecognized keyword; _ERR is an error in the tokenizing process,
- * _EOF is an end-of-file marker, and _NIL is used to encode
- * not-a-token.
+/** Enumeration of possible token types. The ones starting with K_ correspond
+ * to directory 'keywords'. _ERR is an error in the tokenizing process, _EOF
+ * is an end-of-file marker, and _NIL is used to encode not-a-token.
*/
typedef enum {
K_ACCEPT = 0,
@@ -77,12 +75,18 @@
K_CONSENSUS_DIGEST,
K_CONSENSUS_METHODS,
+ A_PURPOSE,
+ _A_UNKNOWN,
+
_UNRECOGNIZED,
_ERR,
_EOF,
_NIL
} directory_keyword;
+#define MIN_ANNOTATION A_PURPOSE
+#define MAX_ANNOTATION _A_UNKNOWN
+
/** Structure to hold a single directory token.
*
* We parse a directory by breaking it into "tokens", each consisting
@@ -139,6 +143,8 @@
/** One or more of AT_START/AT_END to limit where the item may appear in a
* document. */
int pos;
+ /** DOCDOC */
+ int is_annotation;
} token_rule_t;
/*
@@ -149,21 +155,23 @@
*/
/** Appears to indicate the end of a table. */
-#define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0 }
+#define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
/** An item with no restrictions: used for obsolete document types */
-#define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0 }
+#define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
/** An item with no restrictions on multiplicity or location. */
-#define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0 }
+#define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
/** An item that must appear exactly once */
-#define T1(s,t,a,o) { s, t, a, o, 1, 1, 0 }
+#define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
/** An item that must appear exactly once, at the start of the document */
-#define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START }
+#define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
/** An item that must appear exactly once, at the end of the document */
-#define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END }
+#define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
/** An item that must appear one or more times */
-#define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0 }
+#define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
/** An item that must appear no more than once */
-#define T01(s,t,a,o) { s, t, a, o, 0, 1, 0 }
+#define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
+/** An annotation that must appear no more than once */
+#define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
/* Argument multiplicity: any number of arguments. */
#define ARGS 0,INT_MAX,0
@@ -200,6 +208,7 @@
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
+ A01("@purpose", A_PURPOSE, GE(1), NO_OBJ ),
END_OF_TABLE
};
@@ -365,7 +374,8 @@
directory_keyword keyword);
static int tokenize_string(const char *start, const char *end,
smartlist_t *out,
- token_rule_t *table);
+ token_rule_t *table,
+ int allow_annotations);
static directory_token_t *get_next_token(const char **s,
const char *eos,
token_rule_t *table);
@@ -614,7 +624,7 @@
}
++cp;
tokens = smartlist_create();
- if (tokenize_string(cp,strchr(cp,'\0'),tokens,dir_token_table)) {
+ if (tokenize_string(cp,strchr(cp,'\0'),tokens,dir_token_table,0)) {
log_warn(LD_DIR, "Error tokenizing directory signature"); goto err;
}
if (smartlist_len(tokens) != 1) {
@@ -643,7 +653,7 @@
}
tokens = smartlist_create();
- if (tokenize_string(str,end,tokens,dir_token_table)) {
+ if (tokenize_string(str,end,tokens,dir_token_table,0)) {
log_warn(LD_DIR, "Error tokenizing directory"); goto err;
}
@@ -692,7 +702,7 @@
goto err;
}
tokens = smartlist_create();
- if (tokenize_string(str,eos,tokens,dir_token_table)) {
+ if (tokenize_string(str,eos,tokens,dir_token_table,0)) {
log_warn(LD_DIR, "Error tokenizing running-routers"); goto err;
}
tok = smartlist_get(tokens,0);
@@ -858,7 +868,8 @@
router_parse_list_from_string(const char **s, const char *eos,
smartlist_t *dest,
saved_location_t saved_location,
- int want_extrainfo)
+ int want_extrainfo,
+ int allow_annotations)
{
routerinfo_t *router;
extrainfo_t *extrainfo;
@@ -923,7 +934,8 @@
}
} else if (!have_extrainfo && !want_extrainfo) {
router = router_parse_entry_from_string(*s, end,
- saved_location != SAVED_IN_CACHE);
+ saved_location != SAVED_IN_CACHE,
+ allow_annotations);
if (router) {
signed_desc = &router->cache_info;
elt = router;
@@ -977,13 +989,14 @@
*/
routerinfo_t *
router_parse_entry_from_string(const char *s, const char *end,
- int cache_copy)
+ int cache_copy, int allow_annotations)
{
routerinfo_t *router = NULL;
char digest[128];
smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
directory_token_t *tok;
struct in_addr in;
+ const char *start_of_annotations, *cp;
if (!end) {
end = s + strlen(s);
@@ -993,12 +1006,23 @@
while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
--end;
+ start_of_annotations = s;
+ cp = tor_memstr(s, end-s, "\nrouter ");
+ if (!cp) {
+ if (end-s < 7 || strcmpstart(s, "router ")) {
+ log_warn(LD_DIR, "No router keyword found.");
+ goto err;
+ }
+ } else {
+ s = cp+1;
+ }
+
if (router_get_router_hash(s, digest) < 0) {
log_warn(LD_DIR, "Couldn't compute router hash.");
return NULL;
}
tokens = smartlist_create();
- if (tokenize_string(s,end,tokens,routerdesc_token_table)) {
+ if (tokenize_string(s,end,tokens,routerdesc_token_table,allow_annotations)) {
log_warn(LD_DIR, "Error tokenizing router descriptor.");
goto err;
}
@@ -1019,6 +1043,7 @@
router->routerlist_index = -1;
if (cache_copy)
router->cache_info.signed_descriptor_body = tor_strndup(s, end-s);
+ router->cache_info.signed_descriptor_len = s-start_of_annotations;
router->cache_info.signed_descriptor_len = end-s;
memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
@@ -1218,13 +1243,13 @@
return NULL;
}
tokens = smartlist_create();
- if (tokenize_string(s,end,tokens,extrainfo_token_table)) {
- log_warn(LD_DIR, "Error tokenizing router descriptor.");
+ if (tokenize_string(s,end,tokens,extrainfo_token_table,0)) {
+ log_warn(LD_DIR, "Error tokenizing extra-info document.");
goto err;
}
if (smartlist_len(tokens) < 2) {
- log_warn(LD_DIR, "Impossibly short router descriptor.");
+ log_warn(LD_DIR, "Impossibly short extra-info document.");
goto err;
}
@@ -1328,7 +1353,7 @@
len = eos - s;
tokens = smartlist_create();
- if (tokenize_string(s, eos, tokens, dir_key_certificate_table) < 0) {
+ if (tokenize_string(s, eos, tokens, dir_key_certificate_table,0) < 0) {
log_warn(LD_DIR, "Error tokenizing key certificate");
goto err;
}
@@ -1468,7 +1493,7 @@
eos = find_start_of_next_routerstatus(*s);
- if (tokenize_string(*s, eos, tokens, rtrstatus_token_table)) {
+ if (tokenize_string(*s, eos, tokens, rtrstatus_token_table,0)) {
log_warn(LD_DIR, "Error tokenizing router status");
goto err;
}
@@ -1640,7 +1665,7 @@
}
eos = find_start_of_next_routerstatus(s);
- if (tokenize_string(s, eos, tokens, netstatus_token_table)) {
+ if (tokenize_string(s, eos, tokens, netstatus_token_table,0)) {
log_warn(LD_DIR, "Error tokenizing network-status header.");
goto err;
}
@@ -1752,7 +1777,7 @@
smartlist_uniq(ns->entries, _compare_routerstatus_entries,
_free_duplicate_routerstatus_entry);
- if (tokenize_string(s, NULL, footer_tokens, dir_footer_token_table)) {
+ if (tokenize_string(s, NULL, footer_tokens, dir_footer_token_table,0)) {
log_warn(LD_DIR, "Error tokenizing network-status footer.");
goto err;
}
@@ -1812,7 +1837,7 @@
end_of_header = find_start_of_next_routerstatus(s);
if (tokenize_string(s, end_of_header, tokens,
is_vote ? networkstatus_vote_token_table :
- networkstatus_consensus_token_table)) {
+ networkstatus_consensus_token_table, 0)) {
log_warn(LD_DIR, "Error tokenizing network-status vote header.");
goto err;
}
@@ -2032,7 +2057,7 @@
else
end_of_footer = s + strlen(s);
if (tokenize_string(s, end_of_footer, footer_tokens,
- networkstatus_vote_footer_token_table)) {
+ networkstatus_vote_footer_token_table, 0)) {
log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
goto err;
}
@@ -2143,7 +2168,7 @@
eos = s + strlen(s);
if (tokenize_string(s, eos, tokens,
- networkstatus_detached_signature_token_table)) {
+ networkstatus_detached_signature_token_table, 0)) {
log_warn(LD_DIR, "Error tokenizing detached networkstatus signatures");
goto err;
}
@@ -2569,8 +2594,12 @@
}
}
- if (tok->tp == _ERR) { /* No keyword matched; call it an "opt". */
- tok->tp = K_OPT;
+ if (tok->tp == _ERR) {
+ /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
+ if (**s == '@')
+ tok->tp = _A_UNKNOWN;
+ else
+ tok->tp = K_OPT;
tok->args = tor_malloc(sizeof(char*));
tok->args[0] = tor_strndup(*s, eol-*s);
tok->n_args = 1;
@@ -2637,12 +2666,13 @@
*/
static int
tokenize_string(const char *start, const char *end, smartlist_t *out,
- token_rule_t *table)
+ token_rule_t *table, int allow_annotations)
{
const char **s;
directory_token_t *tok = NULL;
int counts[_NIL];
int i;
+ int first_nonannotation;
s = &start;
if (!end)
@@ -2661,6 +2691,36 @@
*s = eat_whitespace_eos(*s, end);
}
+ if (allow_annotations) {
+ first_nonannotation = -1;
+ for (i = 0; i < smartlist_len(out); ++i) {
+ tok = smartlist_get(out, i);
+ if (tok->tp < MIN_ANNOTATION || tok->tp > MAX_ANNOTATION) {
+ first_nonannotation = i;
+ break;
+ }
+ }
+ if (first_nonannotation < 0) {
+ log_warn(LD_DIR, "parse error: item contains only annotations");
+ return -1;
+ }
+ for (i=first_nonannotation; i < smartlist_len(out); ++i) {
+ tok = smartlist_get(out, i);
+ if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
+ log_warn(LD_DIR, "parse error: Annotations mixed with keywords");
+ return -1;
+ }
+ }
+ } else {
+ for (i=0; i < smartlist_len(out); ++i) {
+ tok = smartlist_get(out, i);
+ if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
+ log_warn(LD_DIR, "parse error: no annotations allowed.");
+ return -1;
+ }
+ }
+ first_nonannotation = 0;
+ }
for (i = 0; table[i].t; ++i) {
if (counts[table[i].v] < table[i].min_cnt) {
log_warn(LD_DIR, "Parse error: missing %s element.", table[i].t);
@@ -2672,7 +2732,7 @@
}
if (table[i].pos & AT_START) {
if (smartlist_len(out) < 1 ||
- (tok = smartlist_get(out, 0))->tp != table[i].v) {
+ (tok = smartlist_get(out, first_nonannotation))->tp != table[i].v) {
log_warn(LD_DIR, "Parse error: first item is not %s.", table[i].t);
return -1;
}
Modified: tor/trunk/src/or/test.c
===================================================================
--- tor/trunk/src/or/test.c 2007-09-26 14:52:10 UTC (rev 11653)
+++ tor/trunk/src/or/test.c 2007-09-26 16:19:44 UTC (rev 11654)
@@ -2189,7 +2189,7 @@
test_assert(router_dump_router_to_string(buf, 2048, &r1, pk2)>0);
cp = buf;
- rp1 = router_parse_entry_from_string((const char*)cp,NULL,1);
+ rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0);
test_assert(rp1);
test_streq(rp1->address, r1.address);
test_eq(rp1->or_port, r1.or_port);
More information about the tor-commits
mailing list