]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: startup: load and parse configs from memory
authorValentine Krasnobaeva <vkrasnobaeva@haproxy.com>
Wed, 7 Aug 2024 14:53:50 +0000 (16:53 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 7 Aug 2024 16:41:41 +0000 (18:41 +0200)
Let's call load_cfg_in_ram() helper for each configuration file to load it's
content in some area in memory. Adapt readcfgfile() parser function
respectively. In order to limit changes in its scope we give as an argument a
cfgfile structure, already filled in init_args() and in load_cfg_in_ram() with
file metadata and content.

Parser function (readcfgfile()) uses now fgets_from_mem() instead of standard
fgets from libc implementations.

SPOE filter parses its own configuration file, pointed by 'config' keyword in
the configuration already loaded in memory. So, let's allocate and fill for
this a supplementary cfgfile structure, which is not referenced in cfg_cfgfiles
list. This structure and the memory with content of SPOE filter configuration
are freed immediately in parse_spoe_flt(), when readcfgfile() returns.

HAProxy OpenTracing filter also uses its own configuration file. So, let's
follow the same logic as we do for SPOE filter.

addons/ot/src/parser.c
include/haproxy/cfgparse.h
src/cfgparse.c
src/flt_spoe.c
src/haproxy.c

index f4f3e04a7b09f7507b5f924dd7f5a0f756ad3c74..74585b3f1e64987d881733cc04fea5c2712bce9c 100644 (file)
@@ -1074,8 +1074,9 @@ static int flt_ot_post_parse_cfg_scope(void)
  */
 static int flt_ot_parse_cfg(struct flt_ot_conf *conf, const char *flt_name, char **err)
 {
-       struct list backup_sections;
-       int         retval = ERR_ABORT | ERR_ALERT;
+       struct list    backup_sections;
+       struct cfgfile cfg_file = {0};
+       int            retval = ERR_ABORT | ERR_ALERT;
 
        FLT_OT_FUNC("%p, \"%s\", %p:%p", conf, flt_name, FLT_OT_DPTR_ARGS(err));
 
@@ -1094,8 +1095,16 @@ static int flt_ot_parse_cfg(struct flt_ot_conf *conf, const char *flt_name, char
                /* Do nothing. */;
        else if (access(conf->cfg_file, R_OK) == -1)
                FLT_OT_PARSE_ERR(err, "'%s' : %s", conf->cfg_file, strerror(errno));
-       else
-               retval = readcfgfile(conf->cfg_file);
+       else {
+               cfg_file.filename = conf->cfg_file;
+               cfg_file.size = load_cfg_in_mem(cfg_file.filename, &cfg_file.content);
+               if (cfg_file.size < 0) {
+                       ha_free(&cfg_file.content);
+                       FLT_OT_RETURN_INT(retval);
+               }
+               retval = readcfgfile(&cfg_file);
+               ha_free(&cfg_file.content);
+       }
 
        /* Unregister OT sections and restore previous sections. */
        cfg_unregister_sections();
index 6033b421e78d7ecfd64c9b8a445284b0a562383f..fb6eef261e5a85dbf7d60bc56d31624b50865920 100644 (file)
@@ -112,7 +112,7 @@ int cfg_parse_global(const char *file, int linenum, char **args, int inv);
 int cfg_parse_listen(const char *file, int linenum, char **args, int inv);
 int cfg_parse_track_sc_num(unsigned int *track_sc_num,
                            const char *arg, const char *end, char **err);
-int readcfgfile(const char *file);
+int readcfgfile(const struct cfgfile *cfg);
 void cfg_register_keywords(struct cfg_kw_list *kwl);
 void cfg_unregister_keywords(struct cfg_kw_list *kwl);
 int check_config_validity(void);
index a5dcf7aaf605ea326c884036bc1ee1da857b1858..4c3f76447137cc17cc1de220d61280fa68ad0274 100644 (file)
@@ -1816,8 +1816,8 @@ free_mem:
 }
 
 /*
- * This function reads and parses the configuration file given in the argument.
- * Returns the error code, 0 if OK, -1 if the config file couldn't be opened,
+ * This function parses the configuration file given in the argument.
+ * Returns the error code, 0 if OK, -1 if we are run out of memory,
  * or any combination of :
  *  - ERR_ABORT: must abort ASAP
  *  - ERR_FATAL: we can continue parsing but not start the service
@@ -1826,11 +1826,10 @@ free_mem:
  * Only the two first ones can stop processing, the two others are just
  * indicators.
  */
-int readcfgfile(const char *file)
+int readcfgfile(const struct cfgfile *cfg)
 {
        char *thisline = NULL;
        int linesize = LINESIZE;
-       FILE *f = NULL;
        int linenum = 0;
        int err_code = 0;
        struct cfg_section *cs = NULL, *pcs = NULL;
@@ -1844,6 +1843,8 @@ int readcfgfile(const char *file)
        int nested_cond_lvl = 0;
        enum nested_cond_state nested_conds[MAXNESTEDCONDS];
        char *errmsg = NULL;
+       const char *cur_position = cfg->content;
+       char *file = cfg->filename;
 
        global.cfg_curr_line = 0;
        global.cfg_curr_file = file;
@@ -1854,11 +1855,6 @@ int readcfgfile(const char *file)
                goto err;
        }
 
-       if ((f = fopen(file,"r")) == NULL) {
-               err_code = -1;
-               goto err;
-       }
-
        /* change to the new dir if required */
        if (!cfg_apply_default_path(file, NULL, &errmsg)) {
                ha_alert("parsing [%s:%d]: failed to apply default-path: %s.\n", file, linenum, errmsg);
@@ -1868,7 +1864,8 @@ int readcfgfile(const char *file)
        }
 
 next_line:
-       while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
+       while (fgets_from_mem(thisline + readbytes, linesize - readbytes,
+                             &cur_position, cfg->content + cfg->size)) {
                int arg, kwm = KWM_STD;
                char *end;
                char *args[MAX_LINE_ARGS + 1];
@@ -2617,9 +2614,6 @@ err:
        global.cfg_curr_line = 0;
        global.cfg_curr_file = NULL;
 
-       if (f)
-               fclose(f);
-
        return err_code;
 }
 
index f11d2068c081341a84a03ba1ccc6695fd5716569..9358283dac354280b55b28a0aa7860b7db5a0a47 100644 (file)
@@ -2199,6 +2199,7 @@ static int parse_spoe_flt(char **args, int *cur_arg, struct proxy *px,
        struct spoe_group           *grp, *grpback;
        struct spoe_placeholder     *ph, *phback;
        struct spoe_var_placeholder *vph, *vphback;
+       struct cfgfile              cfg_file = {0};
        struct logger               *logger, *loggerback;
        char                        *file = NULL, *engine = NULL;
        int                          ret, pos = *cur_arg + 1;
@@ -2260,7 +2261,19 @@ static int parse_spoe_flt(char **args, int *cur_arg, struct proxy *px,
        curengine = engine;
        curagent  = NULL;
        curmsg    = NULL;
-       ret = readcfgfile(file);
+
+       /* load the content of SPOE config file from cfg_file.filename into some
+        * area in .heap. readcfgfile() now parses the content of config files
+        * stored in RAM as separate chunks (see struct cfgfile in cfgparse.h),
+        * these chunks chained in cfg_cfgfiles global list.
+        */
+       cfg_file.filename = file;
+       cfg_file.size = load_cfg_in_mem(file, &cfg_file.content);
+       if (cfg_file.size < 0) {
+               goto error;
+       }
+       ret = readcfgfile(&cfg_file);
+       ha_free(&cfg_file.content);
 
        /* unregister SPOE sections and restore previous sections */
        cfg_unregister_sections();
@@ -2579,6 +2592,7 @@ static int parse_spoe_flt(char **args, int *cur_arg, struct proxy *px,
        return 0;
 
  error:
+       ha_free(&cfg_file.content);
        spoe_release_agent(curagent);
        list_for_each_entry_safe(ph, phback, &curmphs, list) {
                LIST_DELETE(&ph->list);
index 4ca3464c930ef1607010805ca05234af9b650ed3..a4341dac6ba178f25ce42199ea4cb5b9f8188618 100644 (file)
@@ -1174,7 +1174,7 @@ next_dir_entry:
 static int read_cfg(char *progname)
 {
        char *env_cfgfiles = NULL;
-       struct cfgfile *cfg;
+       struct cfgfile *cfg, *cfg_tmp;
        int err_code = 0;
 
        /* handle cfgfiles that are actually directories */
@@ -1191,9 +1191,13 @@ static int read_cfg(char *progname)
        setenv("HAPROXY_HTTPS_LOG_FMT", default_https_log_format, 1);
        setenv("HAPROXY_TCP_LOG_FMT", default_tcp_log_format, 1);
        setenv("HAPROXY_BRANCH", PRODUCT_BRANCH, 1);
-       list_for_each_entry(cfg, &cfg_cfgfiles, list) {
+       list_for_each_entry_safe(cfg, cfg_tmp, &cfg_cfgfiles, list) {
                int ret;
 
+               cfg->size = load_cfg_in_mem(cfg->filename, &cfg->content);
+               if (cfg->size < 0)
+                       goto err;
+
                if (!memprintf(&env_cfgfiles, "%s%s%s",
                               (env_cfgfiles ? env_cfgfiles : ""),
                               (env_cfgfiles ? ";" : ""), cfg->filename)) {
@@ -1202,7 +1206,7 @@ static int read_cfg(char *progname)
                        goto err;
                }
 
-               ret = readcfgfile(cfg->filename);
+               ret = readcfgfile(cfg);
                if (ret == -1)
                        goto err;