Loading src/or/config.c +144 −37 Original line number Diff line number Diff line Loading @@ -23,6 +23,11 @@ typedef enum config_type_t { CONFIG_TYPE_CSV, /**< A list of strings, separated by commas and optional * whitespace. */ CONFIG_TYPE_LINELIST, /**< Uninterpreted config lines */ CONFIG_TYPE_LINELIST_S, /**< Uninterpreted, context-sensitive config lines, * mixed with other keywords. */ CONFIG_TYPE_LINELIST_V, /**< Catch-all "virtual" option to summarize * context-sensitive config lines when fetching. */ CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */ } config_type_t; Loading Loading @@ -106,14 +111,16 @@ static config_var_t config_vars[] = { VAR("Group", STRING, Group, NULL), VAR("HashedControlPassword",STRING, HashedControlPassword, NULL), VAR("HttpProxy", STRING, HttpProxy, NULL), VAR("HiddenServiceDir", LINELIST, RendConfigLines, NULL), VAR("HiddenServicePort", LINELIST, RendConfigLines, NULL), VAR("HiddenServiceNodes", LINELIST, RendConfigLines, NULL), VAR("HiddenServiceExcludeNodes", LINELIST, RendConfigLines,NULL), VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines, NULL), VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServicePort", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceNodes", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceExcludeNodes", LINELIST_S, RendConfigLines, NULL), VAR("IgnoreVersion", BOOL, IgnoreVersion, "0"), VAR("KeepalivePeriod", UINT, KeepalivePeriod, "300"), VAR("LogLevel", LINELIST, LogOptions, NULL), VAR("LogFile", LINELIST, LogOptions, NULL), VAR("LogOptions", LINELIST_V, LogOptions, NULL), VAR("LogLevel", LINELIST_S, LogOptions, NULL), VAR("LogFile", LINELIST_S, LogOptions, NULL), OBSOLETE("LinkPadding"), VAR("MaxConn", UINT, MaxConn, "1024"), VAR("MaxOnionsPending", UINT, MaxOnionsPending, "100"), Loading @@ -137,7 +144,7 @@ static config_var_t config_vars[] = { VAR("SocksPort", UINT, SocksPort, "9050"), VAR("SocksBindAddress", LINELIST, SocksBindAddress, NULL), VAR("SocksPolicy", LINELIST, SocksPolicy, NULL), VAR("SysLog", LINELIST, LogOptions, NULL), VAR("SysLog", LINELIST_S, LogOptions, NULL), OBSOLETE("TrafficShaping"), VAR("User", STRING, User, NULL), { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL } Loading @@ -151,13 +158,16 @@ static config_var_t config_vars[] = { static struct config_line_t *config_get_commandlines(int argc, char **argv); static int config_get_lines(FILE *f, struct config_line_t **result); static void config_free_lines(struct config_line_t *front); static int config_assign_line(or_options_t *options, struct config_line_t *c); static int config_assign(or_options_t *options, struct config_line_t *list); static int config_assign_line(or_options_t *options, struct config_line_t *c, int reset); static int config_assign(or_options_t *options, struct config_line_t *list, int reset); static int parse_dir_server_line(const char *line); static int parse_redirect_line(or_options_t *options, struct config_line_t *line); static const char *expand_abbrev(const char *option, int commandline_only); static config_var_t *config_find_option(const char *key); static void reset_option(or_options_t *options, config_var_t *var); /** If <b>option</b> is an official abbreviation for a longer option, * return the longer option. Otherwise return <b>option</b>. Loading Loading @@ -216,7 +226,7 @@ config_get_commandlines(int argc, char **argv) /** Helper: allocate a new configuration option mapping 'key' to 'val', * prepend it to 'front', and return the newly allocated config_line_t */ static struct config_line_t * struct config_line_t * config_line_prepend(struct config_line_t *front, const char *key, const char *val) Loading Loading @@ -298,9 +308,13 @@ static config_var_t *config_find_option(const char *key) } /** If <b>c</b> is a syntactically valid configuration line, update * <b>options</b> with its value and return 0. Otherwise return -1. */ * <b>options</b> with its value and return 0. Otherwise return -1. * * If 'reset' is set, and we get a line containing no value, restore the * option to its default value. */ static int config_assign_line(or_options_t *options, struct config_line_t *c) config_assign_line(or_options_t *options, struct config_line_t *c, int reset) { int i, ok; config_var_t *var; Loading @@ -311,13 +325,17 @@ config_assign_line(or_options_t *options, struct config_line_t *c) log_fn(LOG_WARN, "Unknown option '%s'. Failing.", c->key); return -1; } /* Put keyword into canonical case. */ if (strcmp(var->name, c->key)) { tor_free(c->key); c->key = tor_strdup(var->name); } if (reset && !strlen(c->value)) { reset_option(options, var); return 0; } lvalue = ((char*)options) + var->var_offset; switch(var->type) { Loading Loading @@ -357,7 +375,9 @@ config_assign_line(or_options_t *options, struct config_line_t *c) SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); break; case CONFIG_TYPE_LINELIST: case CONFIG_TYPE_LINELIST_S: /* Note: this reverses the order that the lines appear in. That's * just fine, since we build up the list of lines reversed in the * first place. */ Loading @@ -368,11 +388,30 @@ config_assign_line(or_options_t *options, struct config_line_t *c) case CONFIG_TYPE_OBSOLETE: log_fn(LOG_WARN, "Skipping obsolete configuration option '%s'", c->key); break; case CONFIG_TYPE_LINELIST_V: log_fn(LOG_WARN, "Can't provide value for virtual option '%s'", c->key); return -1; default: tor_assert(0); break; } return 0; } /** restore the option named <b>key</b> in options to its default value. */ static void config_reset_line(or_options_t *options, const char *key) { config_var_t *var; var = config_find_option(key); if (!var) return; /* give error on next pass. */ reset_option(options, var); } /** Return a canonicalized list of the options assigned for key. */ struct config_line_t * Loading @@ -387,10 +426,14 @@ config_get_assigned_option(or_options_t *options, const char *key) if (!var) { log_fn(LOG_WARN, "Unknown option '%s'. Failing.", key); return NULL; } else if (var->type == CONFIG_TYPE_LINELIST_S) { log_fn(LOG_WARN, "Can't return context-sensitive '%s' on its own", key); return NULL; } value = ((char*)options) + var->var_offset; if (var->type == CONFIG_TYPE_LINELIST) { if (var->type == CONFIG_TYPE_LINELIST || var->type == CONFIG_TYPE_LINELIST_V) { /* Linelist requires special handling: we just copy and return it. */ const struct config_line_t *next_in = value; struct config_line_t **next_out = &result; Loading Loading @@ -442,18 +485,36 @@ config_get_assigned_option(or_options_t *options, const char *key) /** Iterate through the linked list of requested options <b>list</b>. * For each item, convert as appropriate and assign to <b>options</b>. * If an item is unrecognized, return -1 immediately, * else return 0 for success. */ * else return 0 for success. * * If <b>reset</b>, then interpret empty lines as meaning "restore to * default value", and interpret LINELIST* options as replacing (not * extending) their previous values. */ static int config_assign(or_options_t *options, struct config_line_t *list) config_assign(or_options_t *options, struct config_line_t *list, int reset) { while (list) { const char *full = expand_abbrev(list->key, 0); if (strcmp(full,list->key)) { tor_free(list->key); list->key = tor_strdup(full); struct config_line_t *p; /* pass 1: normalize keys */ for (p = list; p; p = p->next) { const char *full = expand_abbrev(p->key, 0); if (strcmp(full,p->key)) { tor_free(p->key); p->key = tor_strdup(full); } } /* pass 2: if we're reading from a resetting souurce, clear all mentioned * linelists. */ if (reset) { for (p = list; p; p = p->next) config_reset_line(options, p->key); } if (config_assign_line(options, list)) /* pass 3: assign. */ while (list) { if (config_assign_line(options, list, reset)) return -1; list = list->next; } Loading Loading @@ -604,6 +665,7 @@ free_options(or_options_t *options) tor_free(*(char **)lvalue); break; case CONFIG_TYPE_LINELIST: case CONFIG_TYPE_LINELIST_V: config_free_lines(*(struct config_line_t**)lvalue); *(struct config_line_t**)lvalue = NULL; break; Loading @@ -614,6 +676,9 @@ free_options(or_options_t *options) *(smartlist_t**)lvalue = NULL; } break; case CONFIG_TYPE_LINELIST_S: /* will be freed by corresponding LINELIST_V. */ break; } } /* XXX this last part is an exception. can we make it not needed? */ Loading @@ -625,13 +690,59 @@ free_options(or_options_t *options) } } /** Replace the option indexed by <b>var</b> in <b>options</b> with its * default value. */ static void reset_option(or_options_t *options, config_var_t *var) { struct config_line_t *c; void *lvalue; lvalue = ((char*)options) + var->var_offset; switch (var->type) { case CONFIG_TYPE_STRING: tor_free(*(char**)lvalue); break; case CONFIG_TYPE_DOUBLE: *(double*)lvalue = 0.0; break; case CONFIG_TYPE_UINT: case CONFIG_TYPE_BOOL: *(int*)lvalue = 0; break; case CONFIG_TYPE_CSV: if (*(smartlist_t**)lvalue) { SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp)); smartlist_free(*(smartlist_t **)lvalue); *(smartlist_t **)lvalue = NULL; } break; case CONFIG_TYPE_LINELIST: case CONFIG_TYPE_LINELIST_S: config_free_lines(*(struct config_line_t **)lvalue); *(struct config_line_t **)lvalue = NULL; break; case CONFIG_TYPE_LINELIST_V: /* handled by linelist_s. */ break; case CONFIG_TYPE_OBSOLETE: break; } if (var->initvalue) { c = tor_malloc(sizeof(struct config_line_t)); c->key = tor_strdup(var->name); c->value = tor_strdup(var->initvalue); config_assign_line(options,c,0); config_free_lines(c); } } /** Set <b>options</b> to hold reasonable defaults for most options. * Each option defaults to zero. */ static void init_options(or_options_t *options) { int i; struct config_line_t *c; config_var_t *var; memset(options,0,sizeof(or_options_t)); Loading @@ -639,11 +750,7 @@ init_options(or_options_t *options) var = &config_vars[i]; if(!var->initvalue) continue; /* defaults to NULL or 0 */ c = tor_malloc(sizeof(struct config_line_t)); c->key = tor_strdup(var->name); c->value = tor_strdup(var->initvalue); config_assign_line(options,c); config_free_lines(c); reset_option(options, var); } } Loading Loading @@ -1048,7 +1155,7 @@ getconfig(int argc, char **argv, or_options_t *options) tor_free(fname); if (config_get_lines(cf, &cl)<0) return -1; if (config_assign(options,cl) < 0) if (config_assign(options,cl, 0) < 0) return -1; config_free_lines(cl); fclose(cf); Loading @@ -1056,7 +1163,7 @@ getconfig(int argc, char **argv, or_options_t *options) /* go through command-line variables too */ cl = config_get_commandlines(argc,argv); if (config_assign(options,cl) < 0) if (config_assign(options,cl,0) < 0) return -1; config_free_lines(cl); Loading src/or/control.c +47 −23 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ static void send_control_error(connection_t *conn, uint16_t error, const char *message); static void send_control_event(uint16_t event, uint16_t len, const char *body); static int handle_control_setconf(connection_t *conn, uint16_t len, const char *body); char *body); static int handle_control_getconf(connection_t *conn, uint16_t len, const char *body); static int handle_control_setevents(connection_t *conn, uint16_t len, Loading Loading @@ -139,58 +139,81 @@ send_control_event(uint16_t event, uint16_t len, const char *body) static int handle_control_setconf(connection_t *conn, uint16_t len, const char *body) char *body) { char *k, *v; struct config_line_t *lines = NULL; /* XXXX009 move this logic into config.c someplace. */ do { body = parse_line_from_str(body, &k, &v); if (!body) { goto err; } if (k && v) lines = config_line_prepend(lines, k, v); } while (*body); /* XXXX009 NM */ return 0; err: send_control_error(conn, ERR_UNSPECIFIED, "Couldn't parse configuration"); /* config_free_lines(lines); */ return 0; } static int handle_control_getconf(connection_t *conn, uint16_t body_len, static int handle_control_getconf(connection_t *conn, uint16_t body_len, const char *body) { smartlist_t *answer_elements = NULL; smartlist_t *questions = NULL; smartlist_t *answers = NULL; char *msg = NULL; size_t msg_len; if (body[body_len-1] != '\0') { send_control_error(conn, ERR_UNSPECIFIED, "getconf message body not nul-terminated."); return 0; } /* Now we can be sure that body will end in a nul-terminated string. */ answer_elements = smartlist_create(); while (body_len) { size_t question_len = strlen(body); struct config_line_t *answer = config_get_assigned_option(&options,body); questions = smartlist_create(); smartlist_split_string(questions, body, "\n", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); answers = smartlist_create(); SMARTLIST_FOREACH(questions, const char *, q, { struct config_line_t *answer = config_get_assigned_option(&options,q); if (!answer) { send_control_error(conn, ERR_UNRECOGNIZED_CONFIG_KEY, body); goto done; } else { while (answer) { struct config_line_t *next; smartlist_add(answer_elements, answer->key); smartlist_add(answer_elements, answer->value); size_t alen = strlen(answer->key)+strlen(answer->value)+2; char *astr = tor_malloc(alen); tor_snprintf(astr, alen, "%s %s\n", answer->key, answer->value); smartlist_add(answers, astr); next = answer->next; tor_free(answer->key); tor_free(answer->value); tor_free(answer); answer = next; } } body += question_len+1; body_len -= question_len+1; } }); msg = smartlist_join_strings2(answer_elements, "\0", 1, 0, &msg_len); msg = smartlist_join_strings(answers, "", 0, &msg_len); send_control_message(conn, CONTROL_CMD_CONFVALUE, (uint16_t)msg_len, msg); done: SMARTLIST_FOREACH(answer_elements, char *, cp, tor_free(cp)); smartlist_free(answer_elements); if (answers) SMARTLIST_FOREACH(answers, char *, cp, tor_free(cp)); if (questions) SMARTLIST_FOREACH(questions, char *, cp, tor_free(cp)); smartlist_free(answers); smartlist_free(questions); tor_free(msg); return 0; } static int handle_control_setevents(connection_t *conn, uint16_t len, const char *body) { Loading Loading @@ -218,6 +241,7 @@ static int handle_control_setevents(connection_t *conn, uint16_t len, send_control_done(conn); return 0; } static int handle_control_authenticate(connection_t *conn, uint16_t len, const char *body) { Loading Loading
src/or/config.c +144 −37 Original line number Diff line number Diff line Loading @@ -23,6 +23,11 @@ typedef enum config_type_t { CONFIG_TYPE_CSV, /**< A list of strings, separated by commas and optional * whitespace. */ CONFIG_TYPE_LINELIST, /**< Uninterpreted config lines */ CONFIG_TYPE_LINELIST_S, /**< Uninterpreted, context-sensitive config lines, * mixed with other keywords. */ CONFIG_TYPE_LINELIST_V, /**< Catch-all "virtual" option to summarize * context-sensitive config lines when fetching. */ CONFIG_TYPE_OBSOLETE, /**< Obsolete (ignored) option. */ } config_type_t; Loading Loading @@ -106,14 +111,16 @@ static config_var_t config_vars[] = { VAR("Group", STRING, Group, NULL), VAR("HashedControlPassword",STRING, HashedControlPassword, NULL), VAR("HttpProxy", STRING, HttpProxy, NULL), VAR("HiddenServiceDir", LINELIST, RendConfigLines, NULL), VAR("HiddenServicePort", LINELIST, RendConfigLines, NULL), VAR("HiddenServiceNodes", LINELIST, RendConfigLines, NULL), VAR("HiddenServiceExcludeNodes", LINELIST, RendConfigLines,NULL), VAR("HiddenServiceOptions",LINELIST_V, RendConfigLines, NULL), VAR("HiddenServiceDir", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServicePort", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceNodes", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceExcludeNodes", LINELIST_S, RendConfigLines, NULL), VAR("IgnoreVersion", BOOL, IgnoreVersion, "0"), VAR("KeepalivePeriod", UINT, KeepalivePeriod, "300"), VAR("LogLevel", LINELIST, LogOptions, NULL), VAR("LogFile", LINELIST, LogOptions, NULL), VAR("LogOptions", LINELIST_V, LogOptions, NULL), VAR("LogLevel", LINELIST_S, LogOptions, NULL), VAR("LogFile", LINELIST_S, LogOptions, NULL), OBSOLETE("LinkPadding"), VAR("MaxConn", UINT, MaxConn, "1024"), VAR("MaxOnionsPending", UINT, MaxOnionsPending, "100"), Loading @@ -137,7 +144,7 @@ static config_var_t config_vars[] = { VAR("SocksPort", UINT, SocksPort, "9050"), VAR("SocksBindAddress", LINELIST, SocksBindAddress, NULL), VAR("SocksPolicy", LINELIST, SocksPolicy, NULL), VAR("SysLog", LINELIST, LogOptions, NULL), VAR("SysLog", LINELIST_S, LogOptions, NULL), OBSOLETE("TrafficShaping"), VAR("User", STRING, User, NULL), { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL } Loading @@ -151,13 +158,16 @@ static config_var_t config_vars[] = { static struct config_line_t *config_get_commandlines(int argc, char **argv); static int config_get_lines(FILE *f, struct config_line_t **result); static void config_free_lines(struct config_line_t *front); static int config_assign_line(or_options_t *options, struct config_line_t *c); static int config_assign(or_options_t *options, struct config_line_t *list); static int config_assign_line(or_options_t *options, struct config_line_t *c, int reset); static int config_assign(or_options_t *options, struct config_line_t *list, int reset); static int parse_dir_server_line(const char *line); static int parse_redirect_line(or_options_t *options, struct config_line_t *line); static const char *expand_abbrev(const char *option, int commandline_only); static config_var_t *config_find_option(const char *key); static void reset_option(or_options_t *options, config_var_t *var); /** If <b>option</b> is an official abbreviation for a longer option, * return the longer option. Otherwise return <b>option</b>. Loading Loading @@ -216,7 +226,7 @@ config_get_commandlines(int argc, char **argv) /** Helper: allocate a new configuration option mapping 'key' to 'val', * prepend it to 'front', and return the newly allocated config_line_t */ static struct config_line_t * struct config_line_t * config_line_prepend(struct config_line_t *front, const char *key, const char *val) Loading Loading @@ -298,9 +308,13 @@ static config_var_t *config_find_option(const char *key) } /** If <b>c</b> is a syntactically valid configuration line, update * <b>options</b> with its value and return 0. Otherwise return -1. */ * <b>options</b> with its value and return 0. Otherwise return -1. * * If 'reset' is set, and we get a line containing no value, restore the * option to its default value. */ static int config_assign_line(or_options_t *options, struct config_line_t *c) config_assign_line(or_options_t *options, struct config_line_t *c, int reset) { int i, ok; config_var_t *var; Loading @@ -311,13 +325,17 @@ config_assign_line(or_options_t *options, struct config_line_t *c) log_fn(LOG_WARN, "Unknown option '%s'. Failing.", c->key); return -1; } /* Put keyword into canonical case. */ if (strcmp(var->name, c->key)) { tor_free(c->key); c->key = tor_strdup(var->name); } if (reset && !strlen(c->value)) { reset_option(options, var); return 0; } lvalue = ((char*)options) + var->var_offset; switch(var->type) { Loading Loading @@ -357,7 +375,9 @@ config_assign_line(or_options_t *options, struct config_line_t *c) SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); break; case CONFIG_TYPE_LINELIST: case CONFIG_TYPE_LINELIST_S: /* Note: this reverses the order that the lines appear in. That's * just fine, since we build up the list of lines reversed in the * first place. */ Loading @@ -368,11 +388,30 @@ config_assign_line(or_options_t *options, struct config_line_t *c) case CONFIG_TYPE_OBSOLETE: log_fn(LOG_WARN, "Skipping obsolete configuration option '%s'", c->key); break; case CONFIG_TYPE_LINELIST_V: log_fn(LOG_WARN, "Can't provide value for virtual option '%s'", c->key); return -1; default: tor_assert(0); break; } return 0; } /** restore the option named <b>key</b> in options to its default value. */ static void config_reset_line(or_options_t *options, const char *key) { config_var_t *var; var = config_find_option(key); if (!var) return; /* give error on next pass. */ reset_option(options, var); } /** Return a canonicalized list of the options assigned for key. */ struct config_line_t * Loading @@ -387,10 +426,14 @@ config_get_assigned_option(or_options_t *options, const char *key) if (!var) { log_fn(LOG_WARN, "Unknown option '%s'. Failing.", key); return NULL; } else if (var->type == CONFIG_TYPE_LINELIST_S) { log_fn(LOG_WARN, "Can't return context-sensitive '%s' on its own", key); return NULL; } value = ((char*)options) + var->var_offset; if (var->type == CONFIG_TYPE_LINELIST) { if (var->type == CONFIG_TYPE_LINELIST || var->type == CONFIG_TYPE_LINELIST_V) { /* Linelist requires special handling: we just copy and return it. */ const struct config_line_t *next_in = value; struct config_line_t **next_out = &result; Loading Loading @@ -442,18 +485,36 @@ config_get_assigned_option(or_options_t *options, const char *key) /** Iterate through the linked list of requested options <b>list</b>. * For each item, convert as appropriate and assign to <b>options</b>. * If an item is unrecognized, return -1 immediately, * else return 0 for success. */ * else return 0 for success. * * If <b>reset</b>, then interpret empty lines as meaning "restore to * default value", and interpret LINELIST* options as replacing (not * extending) their previous values. */ static int config_assign(or_options_t *options, struct config_line_t *list) config_assign(or_options_t *options, struct config_line_t *list, int reset) { while (list) { const char *full = expand_abbrev(list->key, 0); if (strcmp(full,list->key)) { tor_free(list->key); list->key = tor_strdup(full); struct config_line_t *p; /* pass 1: normalize keys */ for (p = list; p; p = p->next) { const char *full = expand_abbrev(p->key, 0); if (strcmp(full,p->key)) { tor_free(p->key); p->key = tor_strdup(full); } } /* pass 2: if we're reading from a resetting souurce, clear all mentioned * linelists. */ if (reset) { for (p = list; p; p = p->next) config_reset_line(options, p->key); } if (config_assign_line(options, list)) /* pass 3: assign. */ while (list) { if (config_assign_line(options, list, reset)) return -1; list = list->next; } Loading Loading @@ -604,6 +665,7 @@ free_options(or_options_t *options) tor_free(*(char **)lvalue); break; case CONFIG_TYPE_LINELIST: case CONFIG_TYPE_LINELIST_V: config_free_lines(*(struct config_line_t**)lvalue); *(struct config_line_t**)lvalue = NULL; break; Loading @@ -614,6 +676,9 @@ free_options(or_options_t *options) *(smartlist_t**)lvalue = NULL; } break; case CONFIG_TYPE_LINELIST_S: /* will be freed by corresponding LINELIST_V. */ break; } } /* XXX this last part is an exception. can we make it not needed? */ Loading @@ -625,13 +690,59 @@ free_options(or_options_t *options) } } /** Replace the option indexed by <b>var</b> in <b>options</b> with its * default value. */ static void reset_option(or_options_t *options, config_var_t *var) { struct config_line_t *c; void *lvalue; lvalue = ((char*)options) + var->var_offset; switch (var->type) { case CONFIG_TYPE_STRING: tor_free(*(char**)lvalue); break; case CONFIG_TYPE_DOUBLE: *(double*)lvalue = 0.0; break; case CONFIG_TYPE_UINT: case CONFIG_TYPE_BOOL: *(int*)lvalue = 0; break; case CONFIG_TYPE_CSV: if (*(smartlist_t**)lvalue) { SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp)); smartlist_free(*(smartlist_t **)lvalue); *(smartlist_t **)lvalue = NULL; } break; case CONFIG_TYPE_LINELIST: case CONFIG_TYPE_LINELIST_S: config_free_lines(*(struct config_line_t **)lvalue); *(struct config_line_t **)lvalue = NULL; break; case CONFIG_TYPE_LINELIST_V: /* handled by linelist_s. */ break; case CONFIG_TYPE_OBSOLETE: break; } if (var->initvalue) { c = tor_malloc(sizeof(struct config_line_t)); c->key = tor_strdup(var->name); c->value = tor_strdup(var->initvalue); config_assign_line(options,c,0); config_free_lines(c); } } /** Set <b>options</b> to hold reasonable defaults for most options. * Each option defaults to zero. */ static void init_options(or_options_t *options) { int i; struct config_line_t *c; config_var_t *var; memset(options,0,sizeof(or_options_t)); Loading @@ -639,11 +750,7 @@ init_options(or_options_t *options) var = &config_vars[i]; if(!var->initvalue) continue; /* defaults to NULL or 0 */ c = tor_malloc(sizeof(struct config_line_t)); c->key = tor_strdup(var->name); c->value = tor_strdup(var->initvalue); config_assign_line(options,c); config_free_lines(c); reset_option(options, var); } } Loading Loading @@ -1048,7 +1155,7 @@ getconfig(int argc, char **argv, or_options_t *options) tor_free(fname); if (config_get_lines(cf, &cl)<0) return -1; if (config_assign(options,cl) < 0) if (config_assign(options,cl, 0) < 0) return -1; config_free_lines(cl); fclose(cf); Loading @@ -1056,7 +1163,7 @@ getconfig(int argc, char **argv, or_options_t *options) /* go through command-line variables too */ cl = config_get_commandlines(argc,argv); if (config_assign(options,cl) < 0) if (config_assign(options,cl,0) < 0) return -1; config_free_lines(cl); Loading
src/or/control.c +47 −23 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ static void send_control_error(connection_t *conn, uint16_t error, const char *message); static void send_control_event(uint16_t event, uint16_t len, const char *body); static int handle_control_setconf(connection_t *conn, uint16_t len, const char *body); char *body); static int handle_control_getconf(connection_t *conn, uint16_t len, const char *body); static int handle_control_setevents(connection_t *conn, uint16_t len, Loading Loading @@ -139,58 +139,81 @@ send_control_event(uint16_t event, uint16_t len, const char *body) static int handle_control_setconf(connection_t *conn, uint16_t len, const char *body) char *body) { char *k, *v; struct config_line_t *lines = NULL; /* XXXX009 move this logic into config.c someplace. */ do { body = parse_line_from_str(body, &k, &v); if (!body) { goto err; } if (k && v) lines = config_line_prepend(lines, k, v); } while (*body); /* XXXX009 NM */ return 0; err: send_control_error(conn, ERR_UNSPECIFIED, "Couldn't parse configuration"); /* config_free_lines(lines); */ return 0; } static int handle_control_getconf(connection_t *conn, uint16_t body_len, static int handle_control_getconf(connection_t *conn, uint16_t body_len, const char *body) { smartlist_t *answer_elements = NULL; smartlist_t *questions = NULL; smartlist_t *answers = NULL; char *msg = NULL; size_t msg_len; if (body[body_len-1] != '\0') { send_control_error(conn, ERR_UNSPECIFIED, "getconf message body not nul-terminated."); return 0; } /* Now we can be sure that body will end in a nul-terminated string. */ answer_elements = smartlist_create(); while (body_len) { size_t question_len = strlen(body); struct config_line_t *answer = config_get_assigned_option(&options,body); questions = smartlist_create(); smartlist_split_string(questions, body, "\n", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); answers = smartlist_create(); SMARTLIST_FOREACH(questions, const char *, q, { struct config_line_t *answer = config_get_assigned_option(&options,q); if (!answer) { send_control_error(conn, ERR_UNRECOGNIZED_CONFIG_KEY, body); goto done; } else { while (answer) { struct config_line_t *next; smartlist_add(answer_elements, answer->key); smartlist_add(answer_elements, answer->value); size_t alen = strlen(answer->key)+strlen(answer->value)+2; char *astr = tor_malloc(alen); tor_snprintf(astr, alen, "%s %s\n", answer->key, answer->value); smartlist_add(answers, astr); next = answer->next; tor_free(answer->key); tor_free(answer->value); tor_free(answer); answer = next; } } body += question_len+1; body_len -= question_len+1; } }); msg = smartlist_join_strings2(answer_elements, "\0", 1, 0, &msg_len); msg = smartlist_join_strings(answers, "", 0, &msg_len); send_control_message(conn, CONTROL_CMD_CONFVALUE, (uint16_t)msg_len, msg); done: SMARTLIST_FOREACH(answer_elements, char *, cp, tor_free(cp)); smartlist_free(answer_elements); if (answers) SMARTLIST_FOREACH(answers, char *, cp, tor_free(cp)); if (questions) SMARTLIST_FOREACH(questions, char *, cp, tor_free(cp)); smartlist_free(answers); smartlist_free(questions); tor_free(msg); return 0; } static int handle_control_setevents(connection_t *conn, uint16_t len, const char *body) { Loading Loading @@ -218,6 +241,7 @@ static int handle_control_setevents(connection_t *conn, uint16_t len, send_control_done(conn); return 0; } static int handle_control_authenticate(connection_t *conn, uint16_t len, const char *body) { Loading