From d0f8857438476b456690bc7608b472a2569b697d Mon Sep 17 00:00:00 2001
From: "Alexander V. Chernikov" <melifaro@ipfw.ru>
Date: Thu, 12 Feb 2015 02:13:54 +0300
Subject: [PATCH 5/8] * Limit scope of new_config and cfg_mem variables:
 new_config is not exported anymore, direct cfg_mem usage signifficantly
 reduced. * Be more accurate in global variables assignment: use
 config_start_edit() along with config_stop_edit() to set/clear new_config and
 cfg_mem.

---
 conf/cf-lex.l     | 71 ++++++++++++++++++++++++++++---------------------------
 conf/conf.c       | 65 +++++++++++++++++++++++++++++++++-----------------
 conf/conf.h       | 18 +++++++++-----
 conf/confbase.Y   |  4 ++--
 filter/config.Y   | 24 +++++++++----------
 filter/filter.c   |  4 ++--
 filter/filter.h   |  6 +++--
 filter/tree.c     |  4 ++--
 nest/config.Y     | 15 +++++++-----
 nest/proto.c      | 17 ++++++-------
 nest/protocol.h   |  2 +-
 nest/route.h      |  6 ++---
 nest/rt-roa.c     | 14 +++++------
 nest/rt-table.c   | 16 ++++++-------
 sysdep/unix/krt.Y |  4 ++--
 sysdep/unix/krt.c |  8 +++----
 sysdep/unix/krt.h |  4 ++--
 17 files changed, 158 insertions(+), 124 deletions(-)

diff --git a/conf/cf-lex.l b/conf/cf-lex.l
index 57e0bfa..b995e10 100644
--- a/conf/cf-lex.l
+++ b/conf/cf-lex.l
@@ -70,9 +70,7 @@ struct sym_scope {
 static struct sym_scope *conf_this_scope;
 
 static int cf_hash(byte *c);
-static struct symbol *cf_find_sym(byte *c, unsigned int h0);
-
-linpool *cfg_mem;
+static struct symbol *cf_find_sym(struct config *c, byte *str, unsigned int h0);
 
 int (*cf_read_hook)(byte *buf, unsigned int max, int fd);
 struct include_file_stack *ifs;
@@ -192,7 +190,7 @@ else: {
 	}
       k=k->next;
     }
-  cf_lval.s = cf_find_sym(yytext, h);
+  cf_lval.s = cf_find_sym(config_get_ptr_new(), yytext, h);
   return SYM;
 }
 
@@ -211,7 +209,7 @@ else: {
 
 ["][^"\n]*["] {
   yytext[yyleng-1] = 0;
-  cf_lval.t = cfg_strdup(yytext+1);
+  cf_lval.t = cfg_strdup(config_get_ptr_new(), yytext+1);
   return TEXT;
 }
 
@@ -277,10 +275,10 @@ cf_hash(byte *c)
  */
 
 static struct include_file_stack *
-push_ifs(struct include_file_stack *old)
+push_ifs(struct config *c, struct include_file_stack *old)
 {
   struct include_file_stack *ret;
-  ret = cfg_allocz(sizeof(struct include_file_stack));
+  ret = cfl_allocz(c, sizeof(struct include_file_stack));
   ret->lino = 1;
   ret->prev = old;
   return ret;
@@ -341,8 +339,11 @@ cf_include(char *arg, int alen)
   struct include_file_stack *base_ifs = ifs;
   int new_depth, rv, i;
   char *patt;
+  struct config *new;
   glob_t g = {};
 
+  new = config_get_ptr_new();
+
   new_depth = ifs->depth + 1;
   if (new_depth > MAX_INCLUDE_DEPTH)
     cf_error("Max include depth reached");
@@ -363,8 +364,8 @@ cf_include(char *arg, int alen)
      response when the included config file is missing */
   if (!strpbrk(arg, "?*["))
     {
-      ifs = push_ifs(ifs);
-      ifs->file_name = cfg_strdup(patt);
+      ifs = push_ifs(new, ifs);
+      ifs->file_name = cfg_strdup(new, patt);
       ifs->depth = new_depth;
       ifs->up = base_ifs;
       enter_ifs(ifs);
@@ -398,8 +399,8 @@ cf_include(char *arg, int alen)
         continue;
 
       /* Prepare new stack item */
-      ifs = push_ifs(ifs);
-      ifs->file_name = cfg_strdup(fname);
+      ifs = push_ifs(new, ifs);
+      ifs->file_name = cfg_strdup(new, fname);
       ifs->depth = new_depth;
       ifs->up = base_ifs;
     }
@@ -424,48 +425,48 @@ check_eof(void)
 }
 
 static struct symbol *
-cf_new_sym(byte *c, unsigned int h)
+cf_new_sym(struct config *c, byte *str, unsigned int h)
 {
   struct symbol *s, **ht;
   int l;
 
-  if (!new_config->sym_hash)
-    new_config->sym_hash = cfg_allocz(SYM_HASH_SIZE * sizeof(struct keyword *));
-  ht = new_config->sym_hash;
-  l = strlen(c);
+  if (!c->sym_hash)
+    c->sym_hash = cfl_allocz(c, SYM_HASH_SIZE * sizeof(struct keyword *));
+  ht = c->sym_hash;
+  l = strlen(str);
   if (l > SYM_MAX_LEN)
     cf_error("Symbol too long");
-  s = cfg_alloc(sizeof(struct symbol) + l);
+  s = cfl_alloc(c, sizeof(struct symbol) + l);
   s->next = ht[h];
   ht[h] = s;
   s->scope = conf_this_scope;
   s->class = SYM_VOID;
   s->def = NULL;
   s->aux = 0;
-  strcpy(s->name, c);
+  strcpy(s->name, str);
   return s;
 }
 
 static struct symbol *
-cf_find_sym(byte *c, unsigned int h0)
+cf_find_sym(struct config *c, byte *str, unsigned int h0)
 {
   unsigned int h = h0 & (SYM_HASH_SIZE-1);
   struct symbol *s, **ht;
 
-  if (ht = new_config->sym_hash)
+  if (ht = c->sym_hash)
     {
       for(s = ht[h]; s; s=s->next)
-	if (!strcmp(s->name, c) && s->scope->active)
+	if (!strcmp(s->name, str) && s->scope->active)
 	  return s;
     }
-  if (new_config->sym_fallback)
+  if (c->sym_fallback)
     {
       /* We know only top-level scope is active */
-      for(s = new_config->sym_fallback[h]; s; s=s->next)
-	if (!strcmp(s->name, c) && s->scope->active)
+      for(s = c->sym_fallback[h]; s; s=s->next)
+	if (!strcmp(s->name, str) && s->scope->active)
 	  return s;
     }
-  return cf_new_sym(c, h);
+  return cf_new_sym(c, str, h);
 }
 
 /**
@@ -479,13 +480,13 @@ cf_find_sym(byte *c, unsigned int h0)
  * and returns %NULL to signify no match.
  */
 struct symbol *
-cf_find_symbol(byte *c)
+cf_find_symbol(struct config *c, byte *str)
 {
-  return cf_find_sym(c, cf_hash(c));
+  return cf_find_sym(c, str, cf_hash(str));
 }
 
 struct symbol *
-cf_default_name(char *template, int *counter)
+cf_default_name(struct config *c, char *template, int *counter)
 {
   char buf[32];
   struct symbol *s;
@@ -494,7 +495,7 @@ cf_default_name(char *template, int *counter)
   for(;;)
     {
       bsprintf(buf, template, ++(*counter));
-      s = cf_find_sym(buf, cf_hash(buf));
+      s = cf_find_sym(c, buf, cf_hash(buf));
       if (!s)
 	break;
       if (s->class == SYM_VOID)
@@ -521,13 +522,13 @@ cf_default_name(char *template, int *counter)
  * scope, it's the same @sym as passed to the function.
  */
 struct symbol *
-cf_define_symbol(struct symbol *sym, int type, void *def)
+cf_define_symbol(struct config *c, struct symbol *sym, int type, void *def)
 {
   if (sym->class)
     {
       if (sym->scope == conf_this_scope)
 	cf_error("Symbol already defined");
-      sym = cf_new_sym(sym->name, cf_hash(sym->name) & (SYM_HASH_SIZE-1));
+      sym = cf_new_sym(c, sym->name, cf_hash(sym->name) & (SYM_HASH_SIZE-1));
     }
   sym->class = type;
   sym->def = def;
@@ -561,7 +562,7 @@ cf_lex_init(int is_cli, struct config *c)
   if (!kw_hash_inited)
     cf_lex_init_kh();
 
-  ifs_head = ifs = push_ifs(NULL);
+  ifs_head = ifs = push_ifs(c, NULL);
   if (!is_cli) 
     {
       ifs->file_name = c->file_name;
@@ -577,7 +578,7 @@ cf_lex_init(int is_cli, struct config *c)
   else
     BEGIN(INITIAL);
 
-  conf_this_scope = cfg_allocz(sizeof(struct sym_scope));
+  conf_this_scope = cfl_allocz(c, sizeof(struct sym_scope));
   conf_this_scope->active = 1;
 }
 
@@ -592,9 +593,9 @@ cf_lex_init(int is_cli, struct config *c)
  * in all scopes stored on the stack.
  */
 void
-cf_push_scope(struct symbol *sym)
+cf_push_scope(struct config *c, struct symbol *sym)
 {
-  struct sym_scope *s = cfg_alloc(sizeof(struct sym_scope));
+  struct sym_scope *s = cfl_alloc(c, sizeof(struct sym_scope));
 
   s->next = conf_this_scope;
   conf_this_scope = s;
diff --git a/conf/conf.c b/conf/conf.c
index a907402..9f93813 100644
--- a/conf/conf.c
+++ b/conf/conf.c
@@ -59,6 +59,7 @@
 static jmp_buf conf_jmpbuf;
 
 struct config *config, *new_config;
+linpool *cfg_mem;
 
 static struct config *old_config;	/* Old configuration */
 static struct config *future_config;	/* New config held here if recon requested during recon */
@@ -93,8 +94,8 @@ config_alloc(byte *name)
 
   c->mrtdump_file = -1; /* Hack, this should be sysdep-specific */
   c->pool = p;
-  cfg_mem = c->mem = l;
-  c->file_name = cfg_strdup(name);
+  c->mem = l;
+  c->file_name = cfg_strdup(c, name);
   c->load_time = now;
   c->tf_route = c->tf_proto = (struct timeformat){"%T", "%F", 20*3600};
   c->tf_base = c->tf_log = (struct timeformat){"%F %T", NULL, 0};
@@ -120,10 +121,12 @@ int
 config_parse(struct config *c)
 {
   DBG("Parsing configuration file `%s'\n", c->file_name);
-  new_config = c;
-  cfg_mem = c->mem;
+  config_start_edit(c);
   if (setjmp(conf_jmpbuf))
-    return 0;
+    {
+      config_stop_edit();
+      return 0;
+    }
   cf_lex_init(0, c);
   sysdep_preconfig(c);
   protos_preconfig(c);
@@ -137,6 +140,7 @@ config_parse(struct config *c)
   if (!c->router_id)
     cf_error("Router ID must be configured manually on IPv6 routers");
 #endif
+  config_stop_edit();
   return 1;
 }
 
@@ -150,13 +154,16 @@ config_parse(struct config *c)
 int
 cli_parse(struct config *c)
 {
-  new_config = c;
+  config_start_edit(c);
   c->sym_fallback = config->sym_hash;
-  cfg_mem = c->mem;
   if (setjmp(conf_jmpbuf))
-    return 0;
+    {
+      config_stop_edit();
+      return 0;
+    }
   cf_lex_init(1, c);
   cf_parse();
+  config_stop_edit();
   return 1;
 }
 
@@ -237,10 +244,6 @@ config_do_commit(struct config *c, int type)
   if (old_config && !config->shutdown)
     log(L_INFO "Reconfiguring");
 
-  /* This should not be necessary, but it seems there are some
-     functions that access new_config instead of config */
-  new_config = config;
-
   if (old_config)
     old_config->obstacle_count++;
 
@@ -254,9 +257,6 @@ config_do_commit(struct config *c, int type)
   DBG("protos_commit\n");
   protos_commit(c, old_config, force_restart, type);
 
-  /* Just to be sure nobody uses that now */
-  new_config = NULL;
-
   int obs = 0;
   if (old_config)
     obs = --old_config->obstacle_count;
@@ -288,6 +288,26 @@ config_done(void *unused UNUSED)
     }
 }
 
+void
+config_start_edit(struct config *c)
+{
+  new_config = c;
+  cfg_mem = c->mem;
+}
+
+void
+config_stop_edit()
+{
+  new_config = NULL;
+  cfg_mem = NULL;
+}
+
+struct config *
+config_get_ptr_new(void)
+{
+  return new_config;
+}
+
 /**
  * config_commit - commit a configuration
  * @c: new configuration
@@ -499,7 +519,7 @@ cf_error(char *msg, ...)
   va_start(args, msg);
   if (bvsnprintf(buf, sizeof(buf), msg, args) < 0)
     strcpy(buf, "<bug: error message too long>");
-  new_config->err_msg = cfg_strdup(buf);
+  new_config->err_msg = cfg_strdup(new_config, buf);
   new_config->err_lino = ifs->lino;
   new_config->err_file_name = ifs->file_name;
   cf_lex_unwind();
@@ -508,19 +528,20 @@ cf_error(char *msg, ...)
 
 /**
  * cfg_strdup - copy a string to config memory
- * @c: string to copy
+ * @c: pointer to config
+ * @str: string to copy
  *
  * cfg_strdup() creates a new copy of the string in the memory
- * pool associated with the configuration being currently parsed.
+ * pool @c.
  * It's often used when a string literal occurs in the configuration
  * and we want to preserve it for further use.
  */
 char *
-cfg_strdup(char *c)
+cfg_strdup(struct config *c, char *str)
 {
-  int l = strlen(c) + 1;
-  char *z = cfg_allocu(l);
-  memcpy(z, c, l);
+  int l = strlen(str) + 1;
+  char *z = cfl_allocu(c, l);
+  memcpy(z, str, l);
   return z;
 }
 
diff --git a/conf/conf.h b/conf/conf.h
index 3e641ce..eb8acb5 100644
--- a/conf/conf.h
+++ b/conf/conf.h
@@ -55,7 +55,6 @@ struct config {
 
 /* Please don't use these variables in protocols. Use proto_config->global instead. */
 extern struct config *config;		/* Currently active configuration */
-extern struct config *new_config;	/* Configuration being parsed */
 
 struct config *config_alloc(byte *name);
 int config_parse(struct config *);
@@ -64,6 +63,8 @@ void config_free(struct config *);
 int config_commit(struct config *, int type, int timeout);
 int config_confirm(void);
 int config_undo(void);
+void config_start_edit(struct config *);
+void config_stop_edit(void);
 void config_init(void);
 void cf_error(char *msg, ...) NORET;
 void config_add_obstacle(struct config *);
@@ -91,8 +92,13 @@ extern linpool *cfg_mem;
 #define cfg_alloc(size) lp_alloc(cfg_mem, size)
 #define cfg_allocu(size) lp_allocu(cfg_mem, size)
 #define cfg_allocz(size) lp_allocz(cfg_mem, size)
-char *cfg_strdup(char *c);
+char *cfg_strdup(struct config *c, char *str);
 void cfg_copy_list(list *dest, list *src, unsigned node_size);
+struct config * config_get_ptr_new(void);
+
+#define cfl_alloc(c, size) lp_alloc((c)->mem, size)
+#define cfl_allocz(c, size) lp_allocz((c)->mem, size)
+#define cfl_allocu(c, size) lp_allocu((c)->mem, size)
 
 /* Lexer */
 
@@ -143,10 +149,10 @@ int cf_lex(void);
 void cf_lex_init(int is_cli, struct config *c);
 void cf_lex_unwind(void);
 
-struct symbol *cf_find_symbol(byte *c);
-struct symbol *cf_default_name(char *template, int *counter);
-struct symbol *cf_define_symbol(struct symbol *symbol, int type, void *def);
-void cf_push_scope(struct symbol *);
+struct symbol *cf_find_symbol(struct config *c, byte *str);
+struct symbol *cf_default_name(struct config *c, char *template, int *counter);
+struct symbol *cf_define_symbol(struct config *c, struct symbol *symbol, int type, void *def);
+void cf_push_scope(struct config *c, struct symbol *);
 void cf_pop_scope(void);
 struct symbol *cf_walk_symbols(struct config *cf, struct symbol *sym, int *pos);
 char *cf_symbol_class_name(struct symbol *sym);
diff --git a/conf/confbase.Y b/conf/confbase.Y
index 49831b1..5f209a0 100644
--- a/conf/confbase.Y
+++ b/conf/confbase.Y
@@ -114,13 +114,13 @@ definition:
      struct f_val *val = cfg_alloc(sizeof(struct f_val));
      *val = f_eval($4, cfg_mem);
      if (val->type == T_RETURN) cf_error("Runtime error");
-     cf_define_symbol($2, SYM_CONSTANT | val->type, val);
+     cf_define_symbol(new_config, $2, SYM_CONSTANT | val->type, val);
    }
  ;
 
 expr:
    NUM
- | '(' term ')' { $$ = f_eval_int($2); }
+ | '(' term ')' { $$ = f_eval_int($2, cfg_mem); }
  | SYM {
      if ($1->class != (SYM_CONSTANT | T_INT)) cf_error("Number expected");
      $$ = SYM_VAL($1).i; }
diff --git a/filter/config.Y b/filter/config.Y
index 7eb2c0a..0a338e5 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -46,7 +46,7 @@ f_valid_set_type(int type)
 static inline struct f_tree *
 f_new_item(struct f_val from, struct f_val to)
 {
-  struct f_tree *t = f_new_tree();
+  struct f_tree *t = f_new_tree(new_config);
   t->right = t;
   t->from = from;
   t->to = to;
@@ -66,7 +66,7 @@ f_merge_items(struct f_tree *a, struct f_tree *b)
 static inline struct f_tree *
 f_new_pair_item(int fa, int ta, int fb, int tb)
 {
-  struct f_tree *t = f_new_tree();
+  struct f_tree *t = f_new_tree(new_config);
   t->right = t;
   t->from.type = t->to.type = T_PAIR;
   t->from.val.i = pair(fa, fb);
@@ -124,7 +124,7 @@ f_new_ec_item(u32 kind, u32 ipv4_used, u32 key, u32 vf, u32 vt)
     to = ec_as4(kind, key, vt);
   }
 
-  struct f_tree *t = f_new_tree();
+  struct f_tree *t = f_new_tree(new_config);
   t->right = t;
   t->from.type = t->to.type = T_EC;
   t->from.val.ec = fm;
@@ -305,7 +305,7 @@ CF_GRAMMAR
 
 CF_ADDTO(conf, filter_def)
 filter_def:
-   FILTER SYM { $2 = cf_define_symbol($2, SYM_FILTER, NULL); cf_push_scope( $2 ); }
+   FILTER SYM { $2 = cf_define_symbol(new_config, $2, SYM_FILTER, NULL); cf_push_scope( new_config, $2 ); }
      filter_body {
      $2->def = $4;
      $4->name = $2->name;
@@ -316,7 +316,7 @@ filter_def:
 
 CF_ADDTO(conf, filter_eval)
 filter_eval:
-   EVAL term { f_eval_int($2); }
+   EVAL term { f_eval_int($2, cfg_mem); }
  ;
 
 type:
@@ -356,7 +356,7 @@ one_decl:
    type SYM {
      struct f_val * val = cfg_alloc(sizeof(struct f_val));
      val->type = T_VOID;
-     $2 = cf_define_symbol($2, SYM_VARIABLE | $1, val);
+     $2 = cf_define_symbol(new_config, $2, SYM_VARIABLE | $1, val);
      DBG( "New variable %s type %x\n", $2->name, $1 );
      $2->aux2 = NULL;
      $$=$2;
@@ -441,8 +441,8 @@ function_body:
 CF_ADDTO(conf, function_def)
 function_def:
    FUNCTION SYM { DBG( "Beginning of function %s\n", $2->name );
-     $2 = cf_define_symbol($2, SYM_FUNCTION, NULL);
-     cf_push_scope($2);
+     $2 = cf_define_symbol(new_config, $2, SYM_FUNCTION, NULL);
+     cf_push_scope(new_config, $2);
    } function_params function_body {
      $2->def = $5;
      $2->aux2 = $4;
@@ -507,14 +507,14 @@ set_atom:
 
 switch_atom:
    NUM   { $$.type = T_INT; $$.val.i = $1; }
- | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int($2); }
+ | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int($2, cfg_mem); }
  | RTRID { $$.type = T_QUAD; $$.val.i = $1; }
  | fipa  { $$ = $1; }
  | ENUM  { $$.type = pair_a($1); $$.val.i = pair_b($1); }
  ;
 
 pair_expr:
-   term { $$ = f_eval_int($1); check_u16($$); }
+   term { $$ = f_eval_int($1, cfg_mem); check_u16($$); }
 
 pair_atom:
    pair_expr { $$ = pair($1, $1); }
@@ -535,7 +535,7 @@ pair_item:
  ;
 
 ec_expr:
-   term { $$ = f_eval_int($1); }
+   term { $$ = f_eval_int($1, cfg_mem); }
 
 ec_kind:
    RT { $$ = EC_RT; }
@@ -605,7 +605,7 @@ switch_body: /* EMPTY */ { $$ = NULL; }
      $$ = f_merge_items($1, $2);
    }
  | switch_body ELSECOL cmds { 
-     struct f_tree *t = f_new_tree();
+     struct f_tree *t = f_new_tree(new_config);
      t->from.type = t->to.type = T_VOID;
      t->right = t;
      t->data = $3;
diff --git a/filter/filter.c b/filter/filter.c
index 63c2cd8..ac256f3 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -1513,10 +1513,10 @@ f_eval(struct f_inst *expr, struct linpool *tmp_pool)
 }
 
 uint
-f_eval_int(struct f_inst *expr)
+f_eval_int(struct f_inst *expr, struct linpool *tmp_pool)
 {
   /* Called independently in parse-time to eval expressions */
-  struct f_val res = f_eval(expr, cfg_mem);
+  struct f_val res = f_eval(expr, tmp_pool);
 
   if (res.type != T_INT)
     cf_error("Integer expression expected");
diff --git a/filter/filter.h b/filter/filter.h
index 522af9f..23385cf 100644
--- a/filter/filter.h
+++ b/filter/filter.h
@@ -68,9 +68,11 @@ struct filter {
   struct f_inst *root;
 };
 
+struct config;
+
 struct f_inst *f_new_inst(void);
 struct f_inst *f_new_dynamic_attr(int type, int f_type, int code);	/* Type as core knows it, type as filters know it, and code of dynamic attribute */
-struct f_tree *f_new_tree(void);
+struct f_tree *f_new_tree(struct config *);
 struct f_inst *f_generate_complex(int operation, int operation_aux, struct f_inst *dyn, struct f_inst *argument);
 struct f_inst *f_generate_roa_check(struct symbol *sym, struct f_inst *prefix, struct f_inst *asn);
 
@@ -110,7 +112,7 @@ struct rte;
 
 int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags);
 struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool);
-uint f_eval_int(struct f_inst *expr);
+uint f_eval_int(struct f_inst *expr, struct linpool *tmp_pool);
 u32 f_eval_asn(struct f_inst *expr);
 
 char *filter_name(struct filter *filter);
diff --git a/filter/tree.c b/filter/tree.c
index ee9f448..5910398 100644
--- a/filter/tree.c
+++ b/filter/tree.c
@@ -100,10 +100,10 @@ build_tree(struct f_tree *from)
 }
 
 struct f_tree *
-f_new_tree(void)
+f_new_tree(struct config *c)
 {
   struct f_tree * ret;
-  ret = cfg_alloc(sizeof(struct f_tree));
+  ret = cfl_alloc(c, sizeof(struct f_tree));
   ret->left = ret->right = NULL;
   ret->from.type = ret->to.type = T_VOID;
   ret->from.val.i = ret->to.val.i = 0;
diff --git a/nest/config.Y b/nest/config.Y
index 8b69729..481d9f5 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -16,6 +16,9 @@ CF_HDR
 
 CF_DEFINES
 
+extern struct config *new_config; /* Configuration being parsed */
+#define proto_config_new(pr, cl)	proto_create_config(new_config, pr, cl)
+
 static struct proto_config *this_proto;
 static struct iface_patt *this_ipatt;
 static struct iface_patt_node *this_ipn;
@@ -138,7 +141,7 @@ CF_ADDTO(conf, newtab)
 
 newtab: TABLE SYM tab_sorted {
    struct rtable_config *cf;
-   cf = rt_new_table($2);
+   cf = rt_new_table(new_config, $2);
    cf->sorted = $3;
    }
  ;
@@ -146,13 +149,13 @@ newtab: TABLE SYM tab_sorted {
 CF_ADDTO(conf, roa_table)
 
 roa_table_start: ROA TABLE SYM {
-  this_roa_table = roa_new_table_config($3);
+  this_roa_table = roa_new_table_config(new_config, $3);
 };
 
 roa_table_opts:
    /* empty */
  | roa_table_opts ROA prefix MAX NUM AS NUM ';' {
-     roa_add_item_config(this_roa_table, $3.addr, $3.len, $5, $7);
+     roa_add_item_config(new_config, this_roa_table, $3.addr, $3.len, $5, $7);
    }
  ;
 
@@ -172,19 +175,19 @@ proto_start:
 
 proto_name:
    /* EMPTY */ {
-     struct symbol *s = cf_default_name(this_proto->protocol->template, &this_proto->protocol->name_counter);
+     struct symbol *s = cf_default_name(new_config, this_proto->protocol->template, &this_proto->protocol->name_counter);
      s->class = this_proto->class;
      s->def = this_proto;
      this_proto->name = s->name;
      }
  | SYM {
-     cf_define_symbol($1, this_proto->class, this_proto);
+     cf_define_symbol(new_config, $1, this_proto->class, this_proto);
      this_proto->name = $1->name;
    }
  | SYM FROM SYM {
      if (($3->class != SYM_TEMPLATE) && ($3->class != SYM_PROTO)) cf_error("Template or protocol name expected");
 
-     cf_define_symbol($1, this_proto->class, this_proto);
+     cf_define_symbol(new_config, $1, this_proto->class, this_proto);
      this_proto->name = $1->name;
 
      proto_copy_config(this_proto, $3->def);
diff --git a/nest/proto.c b/nest/proto.c
index 1166573..846d172 100644
--- a/nest/proto.c
+++ b/nest/proto.c
@@ -243,7 +243,8 @@ proto_free_ahooks(struct proto *p)
 
 
 /**
- * proto_config_new - create a new protocol configuration
+ * proto_create_config - create a new protocol configuration
+ * @new: new config instance
  * @pr: protocol the configuration will belong to
  * @class: SYM_PROTO or SYM_TEMPLATE
  *
@@ -261,21 +262,21 @@ proto_free_ahooks(struct proto *p)
  * initialized during protos_commit()).
  */
 void *
-proto_config_new(struct protocol *pr, int class)
+proto_create_config(struct config *new, struct protocol *pr, int class)
 {
-  struct proto_config *c = cfg_allocz(pr->proto_size);
+  struct proto_config *c = cfl_allocz(new, pr->proto_size);
 
   if (class == SYM_PROTO)
-    add_tail(&new_config->protos, &c->n);
-  c->global = new_config;
+    add_tail(&new->protos, &c->n);
+  c->global = new;
   c->protocol = pr;
   c->name = pr->name;
   c->preference = pr->preference;
   c->class = class;
   c->out_filter = FILTER_REJECT;
   c->table = c->global->master_rtc;
-  c->debug = new_config->proto_default_debug;
-  c->mrtdump = new_config->proto_default_mrtdump;
+  c->debug = new->proto_default_debug;
+  c->mrtdump = new->proto_default_mrtdump;
   return c;
 }
 
@@ -521,7 +522,7 @@ protos_commit(struct config *new, struct config *old, int force_reconfig, int ty
       WALK_LIST(oc, old->protos)
 	{
 	  p = oc->proto;
-	  sym = cf_find_symbol(oc->name);
+	  sym = cf_find_symbol(new, oc->name);
 	  if (sym && sym->class == SYM_PROTO && !new->shutdown)
 	    {
 	      /* Found match, let's check if we can smoothly switch to new configuration */
diff --git a/nest/protocol.h b/nest/protocol.h
index 233ffa6..a20b053 100644
--- a/nest/protocol.h
+++ b/nest/protocol.h
@@ -240,7 +240,7 @@ struct proto_spec {
 
 
 void *proto_new(struct proto_config *, unsigned size);
-void *proto_config_new(struct protocol *, int class);
+void *proto_create_config(struct config *, struct protocol *, int class);
 void proto_copy_config(struct proto_config *dest, struct proto_config *src);
 void proto_request_feeding(struct proto *p);
 
diff --git a/nest/route.h b/nest/route.h
index 5ee04a3..c38df41 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -274,7 +274,7 @@ void rt_dump_all(void);
 int rt_feed_baby(struct proto *p);
 void rt_feed_baby_abort(struct proto *p);
 int rt_prune_loop(void);
-struct rtable_config *rt_new_table(struct symbol *s);
+struct rtable_config *rt_new_table(struct config *c, struct symbol *s);
 
 static inline void
 rt_mark_for_prune(rtable *tab)
@@ -591,8 +591,8 @@ void roa_add_item(struct roa_table *t, ip_addr prefix, byte pxlen, byte maxlen,
 void roa_delete_item(struct roa_table *t, ip_addr prefix, byte pxlen, byte maxlen, u32 asn, byte src);
 void roa_flush(struct roa_table *t, byte src);
 byte roa_check(struct roa_table *t, ip_addr prefix, byte pxlen, u32 asn);
-struct roa_table_config * roa_new_table_config(struct symbol *s);
-void roa_add_item_config(struct roa_table_config *rtc, ip_addr prefix, byte pxlen, byte maxlen, u32 asn);
+struct roa_table_config * roa_new_table_config(struct config *c, struct symbol *s);
+void roa_add_item_config(struct config *c, struct roa_table_config *rtc, ip_addr prefix, byte pxlen, byte maxlen, u32 asn);
 void roa_init(void);
 void roa_preconfig(struct config *c);
 void roa_commit(struct config *new, struct config *old);
diff --git a/nest/rt-roa.c b/nest/rt-roa.c
index aa453f1..1c28bdd 100644
--- a/nest/rt-roa.c
+++ b/nest/rt-roa.c
@@ -240,13 +240,13 @@ roa_new_table(struct roa_table_config *cf)
 }
 
 struct roa_table_config *
-roa_new_table_config(struct symbol *s)
+roa_new_table_config(struct config *c, struct symbol *s)
 {
-  struct roa_table_config *rtc = cfg_allocz(sizeof(struct roa_table_config));
+  struct roa_table_config *rtc = cfl_allocz(c, sizeof(struct roa_table_config));
 
-  cf_define_symbol(s, SYM_ROA, rtc);
+  cf_define_symbol(c, s, SYM_ROA, rtc);
   rtc->name = s->name;
-  add_tail(&new_config->roa_tables, &rtc->n);
+  add_tail(&c->roa_tables, &rtc->n);
   return rtc;
 }
 
@@ -257,9 +257,9 @@ roa_new_table_config(struct symbol *s)
  * are specifying the ROA entry.
  */
 void
-roa_add_item_config(struct roa_table_config *rtc, ip_addr prefix, byte pxlen, byte maxlen, u32 asn)
+roa_add_item_config(struct config *c, struct roa_table_config *rtc, ip_addr prefix, byte pxlen, byte maxlen, u32 asn)
 {
-  struct roa_item_config *ric = cfg_allocz(sizeof(struct roa_item_config));
+  struct roa_item_config *ric = cfl_allocz(c, sizeof(struct roa_item_config));
 
   ric->prefix = prefix;
   ric->pxlen = pxlen;
@@ -311,7 +311,7 @@ roa_commit(struct config *new, struct config *old)
   if (old)
     WALK_LIST(t, roa_table_list)
       {
-	struct symbol *sym = cf_find_symbol(t->name);
+	struct symbol *sym = cf_find_symbol(new, t->name);
 	if (sym && sym->class == SYM_ROA)
 	  {
 	    /* Found old table in new config */
diff --git a/nest/rt-table.c b/nest/rt-table.c
index dbe0c50..17ca98e 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -1491,10 +1491,10 @@ rt_prune_loop(void)
 void
 rt_preconfig(struct config *c)
 {
-  struct symbol *s = cf_find_symbol("master");
+  struct symbol *s = cf_find_symbol(c, "master");
 
   init_list(&c->tables);
-  c->master_rtc = rt_new_table(s);
+  c->master_rtc = rt_new_table(c, s);
 }
 
 
@@ -1648,17 +1648,17 @@ rt_next_hop_update(rtable *tab)
 
 
 struct rtable_config *
-rt_new_table(struct symbol *s)
+rt_new_table(struct config *new, struct symbol *s)
 {
   /* Hack that allows to 'redefine' the master table */
-  if ((s->class == SYM_TABLE) && (s->def == new_config->master_rtc))
+  if ((s->class == SYM_TABLE) && (s->def == new->master_rtc))
     return s->def;
 
-  struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config));
+  struct rtable_config *c = cfl_allocz(new, sizeof(struct rtable_config));
 
-  cf_define_symbol(s, SYM_TABLE, c);
+  cf_define_symbol(new, s, SYM_TABLE, c);
   c->name = s->name;
-  add_tail(&new_config->tables, &c->n);
+  add_tail(&new->tables, &c->n);
   c->gc_max_ops = 1000;
   c->gc_min_time = 5;
   return c;
@@ -1728,7 +1728,7 @@ rt_commit(struct config *new, struct config *old)
 	  rtable *ot = o->table;
 	  if (!ot->deleted)
 	    {
-	      struct symbol *sym = cf_find_symbol(o->name);
+	      struct symbol *sym = cf_find_symbol(new, o->name);
 	      if (sym && sym->class == SYM_TABLE && !new->shutdown)
 		{
 		  DBG("\t%s: same\n", o->name);
diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y
index 630cda3..d1bacb6 100644
--- a/sysdep/unix/krt.Y
+++ b/sysdep/unix/krt.Y
@@ -25,7 +25,7 @@ CF_GRAMMAR
 
 CF_ADDTO(proto, kern_proto '}')
 
-kern_proto_start: proto_start KERNEL { this_proto = krt_init_config($1); }
+kern_proto_start: proto_start KERNEL { this_proto = krt_init_config(new_config, $1); }
  ;
 
 CF_ADDTO(kern_proto, kern_proto_start proto_name '{')
@@ -53,7 +53,7 @@ kern_item:
 
 CF_ADDTO(proto, kif_proto '}')
 
-kif_proto_start: proto_start DEVICE { this_proto = kif_init_config($1); }
+kif_proto_start: proto_start DEVICE { this_proto = kif_init_config(new_config, $1); }
  ;
 
 CF_ADDTO(kif_proto, kif_proto_start proto_name '{')
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 6aa264f..d342f7b 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -246,12 +246,12 @@ kif_preconfig(struct protocol *P UNUSED, struct config *c)
 }
 
 struct proto_config *
-kif_init_config(int class)
+kif_init_config(struct config *c, int class)
 {
   if (kif_cf)
     cf_error("Kernel device protocol already defined");
 
-  kif_cf = (struct kif_config *) proto_config_new(&proto_unix_iface, class);
+  kif_cf = (struct kif_config *) proto_create_config(c, &proto_unix_iface, class);
   kif_cf->scan_time = 60;
   init_list(&kif_cf->primary);
 
@@ -1144,14 +1144,14 @@ krt_postconfig(struct proto_config *C)
 }
 
 struct proto_config *
-krt_init_config(int class)
+krt_init_config(struct config *c, int class)
 {
 #ifndef CONFIG_MULTIPLE_TABLES
   if (krt_cf)
     cf_error("Kernel protocol already defined");
 #endif
 
-  krt_cf = (struct krt_config *) proto_config_new(&proto_unix_kernel, class);
+  krt_cf = (struct krt_config *) proto_create_config(c, &proto_unix_kernel, class);
   krt_cf->scan_time = 60;
 
   krt_sys_init_config(krt_cf);
diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h
index 2cd2316..fa4d25a 100644
--- a/sysdep/unix/krt.h
+++ b/sysdep/unix/krt.h
@@ -77,7 +77,7 @@ extern pool *krt_pool;
   if (pr->p.debug & fl)				\
     { log(L_TRACE "%s: " msg, pr->p.name , ## args); } } while(0)
 
-struct proto_config * kif_init_config(int class);
+struct proto_config * kif_init_config(struct config *, int class);
 void kif_request_scan(void);
 void krt_got_route(struct krt_proto *p, struct rte *e);
 void krt_got_route_async(struct krt_proto *p, struct rte *e, int new);
@@ -112,7 +112,7 @@ struct kif_proto {
 
 #define KIF_CF ((struct kif_config *)p->p.cf)
 
-struct proto_config * krt_init_config(int class);
+struct proto_config * krt_init_config(struct config *, int class);
 
 
 /* krt sysdep */
-- 
2.1.2

