Controllers should now specify cache=no or cache=yes when using

the +POSTDESCRIPTOR command.


svn:r11892
This commit is contained in:
Roger Dingledine 2007-10-12 07:57:29 +00:00
parent ad8757fbeb
commit 3977ccbc80
6 changed files with 66 additions and 45 deletions

View File

@ -9,6 +9,8 @@ Changes in version 0.2.0.8-alpha - 2007-10-12
- Use annotations to record the purpose of each descriptor.
- Disable the SETROUTERPURPOSE controller command: it is now
obsolete.
- Controllers should now specify cache=no or cache=yes when using
the +POSTDESCRIPTOR command.
- Bridge authorities now write bridge descriptors to disk, meaning
we can export them to other programs and begin distributing them
to blocked users.

View File

@ -635,12 +635,18 @@ $Id$
3.14. POSTDESCRIPTOR
Sent from the client to the server. The syntax is:
"+POSTDESCRIPTOR" [SP "purpose=" Purpose] CRLF Descriptor CRLF "." CRLF
"+POSTDESCRIPTOR" [SP "purpose=" Purpose] [SP "cache=" Cache]
CRLF Descriptor CRLF "." CRLF
This message informs the server about a new descriptor. If Purpose is
specified, it must be either "general" or "controller", else we
return a 552 error.
If Cache is specified, it must be either "no" or "yes", else we
return a 552 error. If Cache is not specified, Tor will decide for
itself whether it wants to cache the descriptor, and controllers
must not rely on its choice.
The descriptor, when parsed, must contain a number of well-specified
fields, including fields for its nickname and identity.

View File

@ -1878,35 +1878,19 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len,
return 0;
}
/** If *<b>string</b> contains a recognized purpose (for
* circuits if <b>for_circuits</b> is 1, else for routers),
* possibly prefaced with the string "purpose=", then assign it
* and return 0. Otherwise return -1.
*
* If it's prefaced with "purpose=", then set *<b>string</b> to
* the remainder of the string. */
static int
get_purpose(char **string, int for_circuits, uint8_t *purpose)
/** Given a string, convert it to a circuit purpose. */
static uint8_t
circuit_purpose_from_string(const char *string)
{
if (!strcmpstart(*string, "purpose="))
*string += strlen("purpose=");
if (!strcmpstart(string, "purpose="))
string += strlen("purpose=");
if (!for_circuits) {
int r = router_purpose_from_string(*string);
if (r == ROUTER_PURPOSE_UNKNOWN)
return -1;
*purpose = r;
return 0;
}
if (!strcmp(*string, "general"))
*purpose = CIRCUIT_PURPOSE_C_GENERAL;
else if (!strcmp(*string, "controller"))
*purpose = CIRCUIT_PURPOSE_CONTROLLER;
else { /* not a recognized purpose */
return -1;
}
return 0;
if (!strcmp(string, "general"))
return CIRCUIT_PURPOSE_C_GENERAL;
else if (!strcmp(string, "controller"))
return CIRCUIT_PURPOSE_CONTROLLER;
else
return CIRCUIT_PURPOSE_UNKNOWN;
}
/** Return a newly allocated smartlist containing the arguments to the command
@ -1963,7 +1947,8 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
if (zero_circ && smartlist_len(args)>2) {
char *purp = smartlist_get(args,2);
if (get_purpose(&purp, 1, &intended_purpose) < 0) {
intended_purpose = circuit_purpose_from_string(purp);
if (intended_purpose == CIRCUIT_PURPOSE_UNKNOWN) {
connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
@ -2061,7 +2046,8 @@ handle_control_setcircuitpurpose(control_connection_t *conn,
{
char *purp = smartlist_get(args,1);
if (get_purpose(&purp, 1, &new_purpose) < 0) {
new_purpose = circuit_purpose_from_string(purp);
if (new_purpose == CIRCUIT_PURPOSE_UNKNOWN) {
connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
goto done;
}
@ -2178,6 +2164,7 @@ handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
char *desc;
const char *msg=NULL;
uint8_t purpose = ROUTER_PURPOSE_GENERAL;
int cache = 0; /* eventually, we may switch this to 1 */
char *cp = memchr(body, '\n', len);
smartlist_t *args = smartlist_create();
@ -2186,21 +2173,37 @@ handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
smartlist_split_string(args, body, " ",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
if (smartlist_len(args)) {
char *purp = smartlist_get(args,0);
if (get_purpose(&purp, 0, &purpose) < 0) {
connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n",
purp);
SMARTLIST_FOREACH(args, char *, arg, tor_free(arg));
smartlist_free(args);
return 0;
SMARTLIST_FOREACH(args, char *, option,
{
if (!strcasecmpstart(option, "purpose=")) {
option += strlen("purpose=");
purpose = router_purpose_from_string(option);
if (purpose == ROUTER_PURPOSE_UNKNOWN) {
connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n",
option);
goto done;
}
} else if (!strcasecmpstart(option, "cache=")) {
option += strlen("cache=");
if (!strcmp(option, "no"))
cache = 0;
else if (!strcmp(option, "yes"))
cache = 1;
else {
connection_printf_to_buf(conn, "552 Unknown cache request \"%s\"\r\n",
option);
goto done;
}
} else { /* unrecognized argument? */
connection_printf_to_buf(conn,
"512 Unexpected argument \"%s\" to postdescriptor\r\n", option);
goto done;
}
}
SMARTLIST_FOREACH(args, char *, arg, tor_free(arg));
smartlist_free(args);
});
read_escaped_data(cp, len-(cp-body), &desc);
switch (router_load_single_router(desc, purpose, &msg)) {
switch (router_load_single_router(desc, purpose, cache, &msg)) {
case -1:
if (!msg) msg = "Could not parse descriptor";
connection_printf_to_buf(conn, "554 %s\r\n", msg);
@ -2215,6 +2218,9 @@ handle_control_postdescriptor(control_connection_t *conn, uint32_t len,
}
tor_free(desc);
done:
SMARTLIST_FOREACH(args, char *, arg, tor_free(arg));
smartlist_free(args);
return 0;
}

View File

@ -451,6 +451,9 @@ typedef enum {
/** A controller made this circuit and Tor should not use it. */
#define CIRCUIT_PURPOSE_CONTROLLER 18
#define _CIRCUIT_PURPOSE_MAX 18
/** A catch-all for unrecognized purposes. Currently we don't expect
* to make or see any circuits with this purpose. */
#define CIRCUIT_PURPOSE_UNKNOWN 255
/** True iff the circuit purpose <b>p</b> is for a circuit that
* originated at this node. */
@ -3600,7 +3603,7 @@ int router_add_to_routerlist(routerinfo_t *router, const char **msg,
void router_add_extrainfo_to_routerlist(extrainfo_t *ei, const char **msg,
int from_cache, int from_fetch);
void routerlist_remove_old_routers(void);
int router_load_single_router(const char *s, uint8_t purpose,
int router_load_single_router(const char *s, uint8_t purpose, int cache,
const char **msg);
void router_load_routers_from_string(const char *s, const char *eos,
saved_location_t saved_location,

View File

@ -1803,7 +1803,7 @@ router_purpose_to_string(uint8_t p)
return NULL;
}
/** Given a string, convert it to a router purpose. */
/** Given a string, convert it to a router purpose. */
uint8_t
router_purpose_from_string(const char *s)
{

View File

@ -2991,7 +2991,8 @@ routerlist_descriptors_added(smartlist_t *sl)
* This is used only by the controller.
*/
int
router_load_single_router(const char *s, uint8_t purpose, const char **msg)
router_load_single_router(const char *s, uint8_t purpose, int cache,
const char **msg)
{
routerinfo_t *ri;
int r;
@ -3017,6 +3018,9 @@ router_load_single_router(const char *s, uint8_t purpose, const char **msg)
return 0;
}
if (!cache) /* obey the preference of the controller */
ri->cache_info.do_not_cache = 1;
lst = smartlist_create();
smartlist_add(lst, ri);
routers_update_status_from_networkstatus(lst, 0);