haproxy/src/quic_rules.c
Amaury Denoyelle 08515af9df MINOR: quic: implement send-retry quic-initial rules
Define a new quic-initial "send-retry" rule. This allows to force the
emission of a Retry packet on an initial without token instead of
instantiating a new QUIC connection.
2024-07-25 15:39:39 +02:00

155 lines
4.4 KiB
C

#include <haproxy/quic_rules.h>
#include <haproxy/acl.h>
#include <haproxy/action.h>
#include <haproxy/list.h>
#include <haproxy/listener.h>
#include <haproxy/obj_type.h>
#include <haproxy/proxy-t.h>
#include <haproxy/quic_sock-t.h>
#include <haproxy/sample-t.h>
#include <haproxy/session-t.h>
/* Execute registered quic-initial rules on proxy owning <li> listener after
* <dgram> reception.
*/
int quic_init_exec_rules(struct listener *li, struct quic_dgram *dgram)
{
static THREAD_LOCAL struct session rule_sess;
struct act_rule *rule;
enum acl_test_res ret;
struct proxy *px;
int result = 1;
px = li->bind_conf->frontend;
/* Initialize session elements specific to the current datagram. All
* others members are set to 0 thanks to static storage class.
*/
rule_sess.fe = px;
rule_sess.listener = li;
rule_sess.src = &dgram->saddr;
rule_sess.dst = &dgram->daddr;
rule_sess.origin = &dgram->obj_type;
list_for_each_entry(rule, &px->quic_init_rules, list) {
ret = ACL_TEST_PASS;
if (rule->cond) {
ret = acl_exec_cond(rule->cond, px, &rule_sess, NULL, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
ret = acl_pass(ret);
if (rule->cond->pol == ACL_COND_UNLESS)
ret = !ret;
}
if (ret) {
if (rule->action_ptr) {
switch (rule->action_ptr(rule, px, &rule_sess, NULL, 0)) {
case ACT_RET_CONT:
break;
case ACT_RET_DONE:
case ACT_RET_STOP:
goto end;
case ACT_RET_ABRT:
case ACT_RET_DENY:
case ACT_RET_ERR:
case ACT_RET_INV:
result = 0;
goto end;
default:
ABORT_NOW("not implemented");
}
}
else if (rule->action == ACT_ACTION_ALLOW) {
goto end;
}
else if (rule->action == ACT_ACTION_DENY) {
result = 0;
goto end;
}
}
}
end:
return result;
}
static enum act_parse_ret parse_accept(const char **args, int *orig_arg,
struct proxy *px,
struct act_rule *rule, char **err)
{
rule->action = ACT_ACTION_ALLOW;
rule->flags |= ACT_FLAG_FINAL;
return ACT_RET_PRS_OK;
}
static enum act_parse_ret parse_dgram_drop(const char **args, int *orig_arg,
struct proxy *px,
struct act_rule *rule, char **err)
{
rule->action = ACT_ACTION_DENY;
rule->flags |= ACT_FLAG_FINAL;
return ACT_RET_PRS_OK;
}
static enum act_return quic_init_action_reject(struct act_rule *rule, struct proxy *px,
struct session *sess, struct stream *s, int flags)
{
struct quic_dgram *dgram = __objt_dgram(sess->origin);
dgram->flags |= QUIC_DGRAM_FL_REJECT;
return ACT_RET_DONE;
}
static enum act_return quic_init_action_send_retry(struct act_rule *rule, struct proxy *px,
struct session *sess, struct stream *s, int flags)
{
struct quic_dgram *dgram = __objt_dgram(sess->origin);
dgram->flags |= QUIC_DGRAM_FL_SEND_RETRY;
return ACT_RET_DONE;
}
static enum act_parse_ret parse_reject(const char **args, int *orig_arg,
struct proxy *px,
struct act_rule *rule, char **err)
{
rule->action = ACT_CUSTOM;
rule->action_ptr = quic_init_action_reject;
return ACT_RET_PRS_OK;
}
static enum act_parse_ret parse_send_retry(const char **args, int *orig_arg,
struct proxy *px,
struct act_rule *rule, char **err)
{
rule->action = ACT_CUSTOM;
rule->action_ptr = quic_init_action_send_retry;
return ACT_RET_PRS_OK;
}
/* List head of all known action keywords for "quic-initial" */
struct action_kw_list quic_init_actions_list = {
.list = LIST_HEAD_INIT(quic_init_actions_list.list)
};
void quic_init_actions_register(struct action_kw_list *kw_list)
{
LIST_APPEND(&quic_init_actions_list.list, &kw_list->list);
}
/* Return the struct quic-initial action associated to a keyword. */
struct action_kw *action_quic_init_custom(const char *kw)
{
return action_lookup(&quic_init_actions_list.list, kw);
}
static struct action_kw_list quic_init_actions = { ILH, {
{ "accept", parse_accept, 0 },
{ "dgram-drop", parse_dgram_drop, 0 },
{ "reject", parse_reject, 0 },
{ "send-retry", parse_send_retry, 0 },
{ /* END */ },
}
};
INITCALL1(STG_REGISTER, quic_init_actions_register, &quic_init_actions);