From: Frederic Lecaille Date: Wed, 10 Dec 2025 17:37:01 +0000 (+0100) Subject: MINOR: ha-inject: Move some mux h1 parsing functions to cfgparse-mux_h1.c X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2F20251209-ha-inject;p=thirdparty%2Fhaproxy.git MINOR: ha-inject: Move some mux h1 parsing functions to cfgparse-mux_h1.c Add cfgparse-mux_h1.c new C file to avoid compiling such code for ha-inject. Move mux_h1.c parsing functions to this new file. --- diff --git a/Makefile b/Makefile index 63cf006da..c38198b58 100644 --- a/Makefile +++ b/Makefile @@ -1005,7 +1005,8 @@ OBJS_COMMON += src/mux_h2.o src/mux_h1.o src/mux_fcgi.o \ src/version.o src/ncbmbuf.o src/ech.o \ OBJS += $(OBJS_COMMON) src/acl.o src/cfgdiag.o src/cfgparse.o \ - src/cfgparse-global.o src/cfgparse-listen.o src/cfgparse-mux_h2.o \ + src/cfgparse-global.o src/cfgparse-listen.o src/cfgparse-mux_h1.o \ + src/cfgparse-mux_h2.o \ src/cfgparse-tcp.o src/cfgparse-thread.o \ src/cfgparse-unix.o src/check.o src/dns.o src/dns_ring.o src/event_hdl.o \ src/extcheck.o src/filters.o src/flt_bwlim.o src/flt_http_comp.o \ diff --git a/include/haproxy/mux_h1-t.h b/include/haproxy/mux_h1-t.h index a886d364c..18a0701cd 100644 --- a/include/haproxy/mux_h1-t.h +++ b/include/haproxy/mux_h1-t.h @@ -22,6 +22,8 @@ #ifndef _HAPROXY_MUX_H1_T_H #define _HAPROXY_MUX_H1_T_H +#include + #include #include @@ -112,6 +114,21 @@ static forceinline char *h1c_show_flags(char *buf, size_t len, const char *delim #define H1S_F_BODYLESS_REQ 0x00040000 /* Bodyless request message */ #define H1S_F_BODYLESS_RESP 0x00080000 /* Bodyless response message */ +/* An entry in a headers map */ +struct h1_hdr_entry { + struct ist name; + struct ebpt_node node; +}; + +/* Map of headers used to convert outgoing headers */ +struct h1_hdrs_map { + char *name; + struct eb_root map; +}; + +extern struct h1_hdrs_map hdrs_map; +extern int accept_payload_with_any_method; + /* This function is used to report flags in debugging tools. Please reflect * below any single-bit flag addition above in the same order via the * __APPEND_FLAG macro. The new end of the buffer is returned. diff --git a/src/cfgparse-mux_h1.c b/src/cfgparse-mux_h1.c new file mode 100644 index 000000000..0db05ea27 --- /dev/null +++ b/src/cfgparse-mux_h1.c @@ -0,0 +1,254 @@ +#include + +#include + +#include +#include +#include +#include +#include + +/* Add an entry in the headers map. Returns -1 on error and 0 on success. */ +static int add_hdr_case_adjust(const char *from, const char *to, char **err) +{ + struct h1_hdr_entry *entry; + + /* Be sure there is a non-empty */ + if (!strlen(to)) { + memprintf(err, "expect "); + return -1; + } + + /* Be sure only the case differs between and */ + if (strcasecmp(from, to) != 0) { + memprintf(err, " and must not differ except the case"); + return -1; + } + + /* Be sure does not already existsin the tree */ + if (ebis_lookup(&hdrs_map.map, from)) { + memprintf(err, "duplicate entry '%s'", from); + return -1; + } + + /* Create the entry and insert it in the tree */ + entry = malloc(sizeof(*entry)); + if (!entry) { + memprintf(err, "out of memory"); + return -1; + } + + entry->node.key = strdup(from); + entry->name = ist(strdup(to)); + if (!entry->node.key || !isttest(entry->name)) { + free(entry->node.key); + istfree(&entry->name); + free(entry); + memprintf(err, "out of memory"); + return -1; + } + ebis_insert(&hdrs_map.map, &entry->node); + return 0; +} + +static void h1_hdeaders_case_adjust_deinit() +{ + struct ebpt_node *node, *next; + struct h1_hdr_entry *entry; + + node = ebpt_first(&hdrs_map.map); + while (node) { + next = ebpt_next(node); + ebpt_delete(node); + entry = container_of(node, struct h1_hdr_entry, node); + free(entry->node.key); + istfree(&entry->name); + free(entry); + node = next; + } + free(hdrs_map.name); +} + +static int cfg_h1_headers_case_adjust_postparser() +{ + FILE *file = NULL; + char *c, *key_beg, *key_end, *value_beg, *value_end; + char *err; + int rc, line = 0, err_code = 0; + + if (!hdrs_map.name) + goto end; + + file = fopen(hdrs_map.name, "r"); + if (!file) { + ha_alert("h1-headers-case-adjust-file '%s': failed to open file.\n", + hdrs_map.name); + err_code |= ERR_ALERT | ERR_FATAL; + goto end; + } + + /* now parse all lines. The file may contain only two header name per + * line, separated by spaces. All heading and trailing spaces will be + * ignored. Lines starting with a # are ignored. + */ + while (fgets(trash.area, trash.size, file) != NULL) { + line++; + c = trash.area; + + /* strip leading spaces and tabs */ + while (*c == ' ' || *c == '\t') + c++; + + /* ignore emptu lines, or lines beginning with a dash */ + if (*c == '#' || *c == '\0' || *c == '\r' || *c == '\n') + continue; + + /* look for the end of the key */ + key_beg = c; + while (*c != '\0' && *c != ' ' && *c != '\t' && *c != '\n' && *c != '\r') + c++; + key_end = c; + + /* strip middle spaces and tabs */ + while (*c == ' ' || *c == '\t') + c++; + + /* look for the end of the value, it is the end of the line */ + value_beg = c; + while (*c && *c != '\n' && *c != '\r') + c++; + value_end = c; + + /* trim possibly trailing spaces and tabs */ + while (value_end > value_beg && (value_end[-1] == ' ' || value_end[-1] == '\t')) + value_end--; + + /* set final \0 and check entries */ + *key_end = '\0'; + *value_end = '\0'; + + err = NULL; + rc = add_hdr_case_adjust(key_beg, value_beg, &err); + if (rc < 0) { + ha_alert("h1-headers-case-adjust-file '%s' : %s at line %d.\n", + hdrs_map.name, err, line); + err_code |= ERR_ALERT | ERR_FATAL; + free(err); + goto end; + } + if (rc > 0) { + ha_warning("h1-headers-case-adjust-file '%s' : %s at line %d.\n", + hdrs_map.name, err, line); + err_code |= ERR_WARN; + free(err); + } + } + + end: + if (file) + fclose(file); + hap_register_post_deinit(h1_hdeaders_case_adjust_deinit); + return err_code; +} + +/* config parser for global "h1-accept-payload_=-with-any-method" */ +static int cfg_parse_h1_accept_payload_with_any_method(char **args, int section_type, struct proxy *curpx, + const struct proxy *defpx, const char *file, int line, + char **err) +{ + if (too_many_args(0, args, err, NULL)) + return -1; + + accept_payload_with_any_method = 1; + return 0; +} + + +/* config parser for global "h1-header-case-adjust" */ +static int cfg_parse_h1_header_case_adjust(char **args, int section_type, struct proxy *curpx, + const struct proxy *defpx, const char *file, int line, + char **err) +{ + if (too_many_args(2, args, err, NULL)) + return -1; + if (!*(args[1]) || !*(args[2])) { + memprintf(err, "'%s' expects and as argument.", args[0]); + return -1; + } + return add_hdr_case_adjust(args[1], args[2], err); +} + +/* config parser for global "h1-headers-case-adjust-file" */ +static int cfg_parse_h1_headers_case_adjust_file(char **args, int section_type, struct proxy *curpx, + const struct proxy *defpx, const char *file, int line, + char **err) +{ + if (too_many_args(1, args, err, NULL)) + return -1; + if (!*(args[1])) { + memprintf(err, "'%s' expects as argument.", args[0]); + return -1; + } + free(hdrs_map.name); + hdrs_map.name = strdup(args[1]); + if (!hdrs_map.name) { + memprintf(err, "'%s %s' : out of memory", args[0], args[1]); + return -1; + } + return 0; +} + +/* config parser for global "tune.h1.zero-copy-fwd-recv" */ +static int cfg_parse_h1_zero_copy_fwd_rcv(char **args, int section_type, struct proxy *curpx, + const struct proxy *defpx, const char *file, int line, + char **err) +{ + if (too_many_args(1, args, err, NULL)) + return -1; + + if (strcmp(args[1], "on") == 0) + global.tune.no_zero_copy_fwd &= ~NO_ZERO_COPY_FWD_H1_RCV; + else if (strcmp(args[1], "off") == 0) + global.tune.no_zero_copy_fwd |= NO_ZERO_COPY_FWD_H1_RCV; + else { + memprintf(err, "'%s' expects 'on' or 'off'.", args[0]); + return -1; + } + return 0; +} + +/* config parser for global "tune.h1.zero-copy-fwd-send" */ +static int cfg_parse_h1_zero_copy_fwd_snd(char **args, int section_type, struct proxy *curpx, + const struct proxy *defpx, const char *file, int line, + char **err) +{ + if (too_many_args(1, args, err, NULL)) + return -1; + + if (strcmp(args[1], "on") == 0) + global.tune.no_zero_copy_fwd &= ~NO_ZERO_COPY_FWD_H1_SND; + else if (strcmp(args[1], "off") == 0) + global.tune.no_zero_copy_fwd |= NO_ZERO_COPY_FWD_H1_SND; + else { + memprintf(err, "'%s' expects 'on' or 'off'.", args[0]); + return -1; + } + return 0; +} + +/* config keyword parsers */ +static struct cfg_kw_list cfg_kws = {{ }, { + { CFG_GLOBAL, "h1-accept-payload-with-any-method", cfg_parse_h1_accept_payload_with_any_method }, + { CFG_GLOBAL, "h1-case-adjust", cfg_parse_h1_header_case_adjust }, + { CFG_GLOBAL, "h1-case-adjust-file", cfg_parse_h1_headers_case_adjust_file }, + { CFG_GLOBAL, "tune.h1.zero-copy-fwd-recv", cfg_parse_h1_zero_copy_fwd_rcv }, + { CFG_GLOBAL, "tune.h1.zero-copy-fwd-send", cfg_parse_h1_zero_copy_fwd_snd }, + { 0, NULL, NULL }, + } +}; + +INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws); +REGISTER_CONFIG_POSTPARSER("h1-headers-map", cfg_h1_headers_case_adjust_postparser); + + + diff --git a/src/mux_h1.c b/src/mux_h1.c index 7b9cddf8d..3cdb6ad10 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -79,21 +79,9 @@ struct h1s { char ws_key[25]; /* websocket handshake key */ }; -/* Map of headers used to convert outgoing headers */ -struct h1_hdrs_map { - char *name; - struct eb_root map; -}; - -/* An entry in a headers map */ -struct h1_hdr_entry { - struct ist name; - struct ebpt_node node; -}; - /* Declare the headers map */ -static struct h1_hdrs_map hdrs_map = { .name = NULL, .map = EB_ROOT }; -static int accept_payload_with_any_method = 0; +struct h1_hdrs_map hdrs_map = { .name = NULL, .map = EB_ROOT }; +int accept_payload_with_any_method = 0; /* trace source and events */ static void h1_trace(enum trace_level level, uint64_t mask, @@ -5589,49 +5577,6 @@ static int h1_show_sd(struct buffer *msg, struct sedesc *sd, const char *pfx) } -/* Add an entry in the headers map. Returns -1 on error and 0 on success. */ -static int add_hdr_case_adjust(const char *from, const char *to, char **err) -{ - struct h1_hdr_entry *entry; - - /* Be sure there is a non-empty */ - if (!strlen(to)) { - memprintf(err, "expect "); - return -1; - } - - /* Be sure only the case differs between and */ - if (strcasecmp(from, to) != 0) { - memprintf(err, " and must not differ except the case"); - return -1; - } - - /* Be sure does not already existsin the tree */ - if (ebis_lookup(&hdrs_map.map, from)) { - memprintf(err, "duplicate entry '%s'", from); - return -1; - } - - /* Create the entry and insert it in the tree */ - entry = malloc(sizeof(*entry)); - if (!entry) { - memprintf(err, "out of memory"); - return -1; - } - - entry->node.key = strdup(from); - entry->name = ist(strdup(to)); - if (!entry->node.key || !isttest(entry->name)) { - free(entry->node.key); - istfree(&entry->name); - free(entry); - memprintf(err, "out of memory"); - return -1; - } - ebis_insert(&hdrs_map.map, &entry->node); - return 0; -} - /* Migrate the the connection to the current thread. * Return 0 if successful, non-zero otherwise. * Expected to be called with the old thread lock held. @@ -5724,206 +5669,6 @@ static int h1_takeover(struct connection *conn, int orig_tid, int release) return -1; } - -static void h1_hdeaders_case_adjust_deinit() -{ - struct ebpt_node *node, *next; - struct h1_hdr_entry *entry; - - node = ebpt_first(&hdrs_map.map); - while (node) { - next = ebpt_next(node); - ebpt_delete(node); - entry = container_of(node, struct h1_hdr_entry, node); - free(entry->node.key); - istfree(&entry->name); - free(entry); - node = next; - } - free(hdrs_map.name); -} - -static int cfg_h1_headers_case_adjust_postparser() -{ - FILE *file = NULL; - char *c, *key_beg, *key_end, *value_beg, *value_end; - char *err; - int rc, line = 0, err_code = 0; - - if (!hdrs_map.name) - goto end; - - file = fopen(hdrs_map.name, "r"); - if (!file) { - ha_alert("h1-headers-case-adjust-file '%s': failed to open file.\n", - hdrs_map.name); - err_code |= ERR_ALERT | ERR_FATAL; - goto end; - } - - /* now parse all lines. The file may contain only two header name per - * line, separated by spaces. All heading and trailing spaces will be - * ignored. Lines starting with a # are ignored. - */ - while (fgets(trash.area, trash.size, file) != NULL) { - line++; - c = trash.area; - - /* strip leading spaces and tabs */ - while (*c == ' ' || *c == '\t') - c++; - - /* ignore emptu lines, or lines beginning with a dash */ - if (*c == '#' || *c == '\0' || *c == '\r' || *c == '\n') - continue; - - /* look for the end of the key */ - key_beg = c; - while (*c != '\0' && *c != ' ' && *c != '\t' && *c != '\n' && *c != '\r') - c++; - key_end = c; - - /* strip middle spaces and tabs */ - while (*c == ' ' || *c == '\t') - c++; - - /* look for the end of the value, it is the end of the line */ - value_beg = c; - while (*c && *c != '\n' && *c != '\r') - c++; - value_end = c; - - /* trim possibly trailing spaces and tabs */ - while (value_end > value_beg && (value_end[-1] == ' ' || value_end[-1] == '\t')) - value_end--; - - /* set final \0 and check entries */ - *key_end = '\0'; - *value_end = '\0'; - - err = NULL; - rc = add_hdr_case_adjust(key_beg, value_beg, &err); - if (rc < 0) { - ha_alert("h1-headers-case-adjust-file '%s' : %s at line %d.\n", - hdrs_map.name, err, line); - err_code |= ERR_ALERT | ERR_FATAL; - free(err); - goto end; - } - if (rc > 0) { - ha_warning("h1-headers-case-adjust-file '%s' : %s at line %d.\n", - hdrs_map.name, err, line); - err_code |= ERR_WARN; - free(err); - } - } - - end: - if (file) - fclose(file); - hap_register_post_deinit(h1_hdeaders_case_adjust_deinit); - return err_code; -} - -/* config parser for global "h1-accept-payload_=-with-any-method" */ -static int cfg_parse_h1_accept_payload_with_any_method(char **args, int section_type, struct proxy *curpx, - const struct proxy *defpx, const char *file, int line, - char **err) -{ - if (too_many_args(0, args, err, NULL)) - return -1; - accept_payload_with_any_method = 1; - return 0; -} - - -/* config parser for global "h1-header-case-adjust" */ -static int cfg_parse_h1_header_case_adjust(char **args, int section_type, struct proxy *curpx, - const struct proxy *defpx, const char *file, int line, - char **err) -{ - if (too_many_args(2, args, err, NULL)) - return -1; - if (!*(args[1]) || !*(args[2])) { - memprintf(err, "'%s' expects and as argument.", args[0]); - return -1; - } - return add_hdr_case_adjust(args[1], args[2], err); -} - -/* config parser for global "h1-headers-case-adjust-file" */ -static int cfg_parse_h1_headers_case_adjust_file(char **args, int section_type, struct proxy *curpx, - const struct proxy *defpx, const char *file, int line, - char **err) -{ - if (too_many_args(1, args, err, NULL)) - return -1; - if (!*(args[1])) { - memprintf(err, "'%s' expects as argument.", args[0]); - return -1; - } - free(hdrs_map.name); - hdrs_map.name = strdup(args[1]); - if (!hdrs_map.name) { - memprintf(err, "'%s %s' : out of memory", args[0], args[1]); - return -1; - } - return 0; -} - -/* config parser for global "tune.h1.zero-copy-fwd-recv" */ -static int cfg_parse_h1_zero_copy_fwd_rcv(char **args, int section_type, struct proxy *curpx, - const struct proxy *defpx, const char *file, int line, - char **err) -{ - if (too_many_args(1, args, err, NULL)) - return -1; - - if (strcmp(args[1], "on") == 0) - global.tune.no_zero_copy_fwd &= ~NO_ZERO_COPY_FWD_H1_RCV; - else if (strcmp(args[1], "off") == 0) - global.tune.no_zero_copy_fwd |= NO_ZERO_COPY_FWD_H1_RCV; - else { - memprintf(err, "'%s' expects 'on' or 'off'.", args[0]); - return -1; - } - return 0; -} - -/* config parser for global "tune.h1.zero-copy-fwd-send" */ -static int cfg_parse_h1_zero_copy_fwd_snd(char **args, int section_type, struct proxy *curpx, - const struct proxy *defpx, const char *file, int line, - char **err) -{ - if (too_many_args(1, args, err, NULL)) - return -1; - - if (strcmp(args[1], "on") == 0) - global.tune.no_zero_copy_fwd &= ~NO_ZERO_COPY_FWD_H1_SND; - else if (strcmp(args[1], "off") == 0) - global.tune.no_zero_copy_fwd |= NO_ZERO_COPY_FWD_H1_SND; - else { - memprintf(err, "'%s' expects 'on' or 'off'.", args[0]); - return -1; - } - return 0; -} - -/* config keyword parsers */ -static struct cfg_kw_list cfg_kws = {{ }, { - { CFG_GLOBAL, "h1-accept-payload-with-any-method", cfg_parse_h1_accept_payload_with_any_method }, - { CFG_GLOBAL, "h1-case-adjust", cfg_parse_h1_header_case_adjust }, - { CFG_GLOBAL, "h1-case-adjust-file", cfg_parse_h1_headers_case_adjust_file }, - { CFG_GLOBAL, "tune.h1.zero-copy-fwd-recv", cfg_parse_h1_zero_copy_fwd_rcv }, - { CFG_GLOBAL, "tune.h1.zero-copy-fwd-send", cfg_parse_h1_zero_copy_fwd_snd }, - { 0, NULL, NULL }, - } -}; - -INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws); -REGISTER_CONFIG_POSTPARSER("h1-headers-map", cfg_h1_headers_case_adjust_postparser); - - /****************************************/ /* MUX initialization and instantiation */ /****************************************/