static enum act_parse_ret parse_set_priority_offset(const char **args, int *arg, struct proxy *px, struct act_rule *rule, char **err) { unsigned int where = 0; rule->arg.expr = sample_parse_expr((char **)args, arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args); if (!rule->arg.expr) return ACT_RET_PRS_ERR; if (px->cap & PR_CAP_FE) where |= SMP_VAL_FE_HRQ_HDR; if (px->cap & PR_CAP_BE) where |= SMP_VAL_BE_HRQ_HDR; if (!(rule->arg.expr->fetch->val & where)) { memprintf(err, "fetch method '%s' extracts information from '%s', none of which is available here", args[0], sample_src_names(rule->arg.expr->fetch->use)); free(rule->arg.expr); return ACT_RET_PRS_ERR; } rule->action = ACT_CUSTOM; rule->action_ptr = action_set_priority_offset; return ACT_RET_PRS_OK; }
/* * Parse the sample fetch expression <text> and add a node to <list_format> upon * success. At the moment, sample converters are not yet supported but fetch arguments * should work. The curpx->conf.args.ctx must be set by the caller. */ void add_sample_to_logformat_list(char *text, char *arg, int arg_len, struct proxy *curpx, struct list *list_format, int options, int cap, const char *file, int line) { char *cmd[2]; struct sample_expr *expr; struct logformat_node *node; int cmd_arg; char *errmsg = NULL; cmd[0] = text; cmd[1] = ""; cmd_arg = 0; expr = sample_parse_expr(cmd, &cmd_arg, file, line, &errmsg, &curpx->conf.args); if (!expr) { Warning("parsing [%s:%d] : '%s' : sample fetch <%s> failed with : %s\n", curpx->conf.args.file, curpx->conf.args.line, fmt_directive(curpx), text, errmsg); return; } node = calloc(1, sizeof(struct logformat_node)); node->type = LOG_FMT_EXPR; node->expr = expr; node->options = options; if (arg_len) { node->arg = my_strndup(arg, arg_len); parse_logformat_var_args(node->arg, node); } if (expr->fetch->val & cap & SMP_VAL_REQUEST) node->options |= LOG_OPT_REQ_CAP; /* fetch method is request-compatible */ if (expr->fetch->val & cap & SMP_VAL_RESPONSE) node->options |= LOG_OPT_RES_CAP; /* fetch method is response-compatible */ if (!(expr->fetch->val & cap)) Warning("parsing [%s:%d] : '%s' : sample fetch <%s> may not be reliably used here because it needs '%s' which is not available here.\n", curpx->conf.args.file, curpx->conf.args.line, fmt_directive(curpx), text, sample_src_names(expr->fetch->use)); /* check if we need to allocate an hdr_idx struct for HTTP parsing */ /* Note, we may also need to set curpx->to_log with certain fetches */ curpx->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY); /* FIXME: temporary workaround for missing LW_XPRT and LW_REQ flags * needed with some sample fetches (eg: ssl*). We always set it for * now on, but this will leave with sample capabilities soon. */ curpx->to_log |= LW_XPRT; curpx->to_log |= LW_REQ; LIST_ADDQ(list_format, &node->list); }
/* * Parse the sample fetch expression <text> and add a node to <list_format> upon * success. At the moment, sample converters are not yet supported but fetch arguments * should work. */ void add_sample_to_logformat_list(char *text, char *arg, int arg_len, struct proxy *curpx, struct list *list_format, int options) { char *cmd[2]; struct sample_expr *expr; struct logformat_node *node; int cmd_arg; cmd[0] = text; cmd[1] = ""; cmd_arg = 0; expr = sample_parse_expr(cmd, &cmd_arg, trash.str, trash.size); if (!expr) { Warning("log-format: sample fetch <%s> failed with : %s\n", text, trash.str); return; } node = calloc(1, sizeof(struct logformat_node)); node->type = LOG_FMT_EXPR; node->expr = expr; node->options = options; if (arg_len) { node->arg = my_strndup(arg, arg_len); parse_logformat_var_args(node->arg, node); } if (expr->fetch->cap & SMP_CAP_REQ) node->options |= LOG_OPT_REQ_CAP; /* fetch method is request-compatible */ if (expr->fetch->cap & SMP_CAP_RES) node->options |= LOG_OPT_RES_CAP; /* fetch method is response-compatible */ /* check if we need to allocate an hdr_idx struct for HTTP parsing */ /* Note, we may also need to set curpx->to_log with certain fetches */ if (expr->fetch->cap & SMP_CAP_L7) curpx->acl_requires |= ACL_USE_L7_ANY; /* FIXME: temporary workaround for missing LW_XPRT flag needed with some * sample fetches (eg: ssl*). We always set it for now on, but this will * leave with sample capabilities soon. */ curpx->to_log |= LW_XPRT; LIST_ADDQ(list_format, &node->list); }
/* parse an "http-response capture" action. It takes a single argument which is * a sample fetch expression. It stores the expression into arg->act.p[0] and * the allocated hdr_cap struct od the preallocated id into arg->act.p[1]. * It returns ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error. */ static enum act_parse_ret parse_http_res_capture(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err) { struct sample_expr *expr; int cur_arg; int id; char *error; for (cur_arg = *orig_arg; cur_arg < *orig_arg + 3 && *args[cur_arg]; cur_arg++) if (strcmp(args[cur_arg], "if") == 0 || strcmp(args[cur_arg], "unless") == 0) break; if (cur_arg < *orig_arg + 3) { memprintf(err, "expects <expression> id <idx>"); return ACT_RET_PRS_ERR; } cur_arg = *orig_arg; expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args); if (!expr) return ACT_RET_PRS_ERR; if (!(expr->fetch->val & SMP_VAL_FE_HRS_HDR)) { memprintf(err, "fetch method '%s' extracts information from '%s', none of which is available here", args[cur_arg-1], sample_src_names(expr->fetch->use)); free(expr); return ACT_RET_PRS_ERR; } if (!args[cur_arg] || !*args[cur_arg]) { memprintf(err, "expects 'id'"); free(expr); return ACT_RET_PRS_ERR; } if (strcmp(args[cur_arg], "id") != 0) { memprintf(err, "expects 'id', found '%s'", args[cur_arg]); free(expr); return ACT_RET_PRS_ERR; } cur_arg++; if (!args[cur_arg]) { memprintf(err, "missing id value"); free(expr); return ACT_RET_PRS_ERR; } id = strtol(args[cur_arg], &error, 10); if (*error != '\0') { memprintf(err, "cannot parse id '%s'", args[cur_arg]); free(expr); return ACT_RET_PRS_ERR; } cur_arg++; px->conf.args.ctx = ARGC_CAP; rule->action = ACT_CUSTOM; rule->action_ptr = http_action_res_capture_by_id; rule->check_ptr = check_http_res_capture; rule->arg.capid.expr = expr; rule->arg.capid.idx = id; *orig_arg = cur_arg; return ACT_RET_PRS_OK; }
/* parse an "http-request capture" action. It takes a single argument which is * a sample fetch expression. It stores the expression into arg->act.p[0] and * the allocated hdr_cap struct or the preallocated "id" into arg->act.p[1]. * It returns ACT_RET_PRS_OK on success, ACT_RET_PRS_ERR on error. */ static enum act_parse_ret parse_http_req_capture(const char **args, int *orig_arg, struct proxy *px, struct act_rule *rule, char **err) { struct sample_expr *expr; struct cap_hdr *hdr; int cur_arg; int len = 0; for (cur_arg = *orig_arg; cur_arg < *orig_arg + 3 && *args[cur_arg]; cur_arg++) if (strcmp(args[cur_arg], "if") == 0 || strcmp(args[cur_arg], "unless") == 0) break; if (cur_arg < *orig_arg + 3) { memprintf(err, "expects <expression> [ 'len' <length> | id <idx> ]"); return ACT_RET_PRS_ERR; } cur_arg = *orig_arg; expr = sample_parse_expr((char **)args, &cur_arg, px->conf.args.file, px->conf.args.line, err, &px->conf.args); if (!expr) return ACT_RET_PRS_ERR; if (!(expr->fetch->val & SMP_VAL_FE_HRQ_HDR)) { memprintf(err, "fetch method '%s' extracts information from '%s', none of which is available here", args[cur_arg-1], sample_src_names(expr->fetch->use)); free(expr); return ACT_RET_PRS_ERR; } if (!args[cur_arg] || !*args[cur_arg]) { memprintf(err, "expects 'len or 'id'"); free(expr); return ACT_RET_PRS_ERR; } if (strcmp(args[cur_arg], "len") == 0) { cur_arg++; if (!(px->cap & PR_CAP_FE)) { memprintf(err, "proxy '%s' has no frontend capability", px->id); return ACT_RET_PRS_ERR; } px->conf.args.ctx = ARGC_CAP; if (!args[cur_arg]) { memprintf(err, "missing length value"); free(expr); return ACT_RET_PRS_ERR; } /* we copy the table name for now, it will be resolved later */ len = atoi(args[cur_arg]); if (len <= 0) { memprintf(err, "length must be > 0"); free(expr); return ACT_RET_PRS_ERR; } cur_arg++; hdr = calloc(1, sizeof(*hdr)); hdr->next = px->req_cap; hdr->name = NULL; /* not a header capture */ hdr->namelen = 0; hdr->len = len; hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED); hdr->index = px->nb_req_cap++; px->req_cap = hdr; px->to_log |= LW_REQHDR; rule->action = ACT_CUSTOM; rule->action_ptr = http_action_req_capture; rule->arg.cap.expr = expr; rule->arg.cap.hdr = hdr; } else if (strcmp(args[cur_arg], "id") == 0) { int id; char *error; cur_arg++; if (!args[cur_arg]) { memprintf(err, "missing id value"); free(expr); return ACT_RET_PRS_ERR; } id = strtol(args[cur_arg], &error, 10); if (*error != '\0') { memprintf(err, "cannot parse id '%s'", args[cur_arg]); free(expr); return ACT_RET_PRS_ERR; } cur_arg++; px->conf.args.ctx = ARGC_CAP; rule->action = ACT_CUSTOM; rule->action_ptr = http_action_req_capture_by_id; rule->check_ptr = check_http_req_capture; rule->arg.capid.expr = expr; rule->arg.capid.idx = id; } else { memprintf(err, "expects 'len' or 'id', found '%s'", args[cur_arg]); free(expr); return ACT_RET_PRS_ERR; } *orig_arg = cur_arg; return ACT_RET_PRS_OK; }