diff options
Diffstat (limited to 'examples/ipsec-secgw/sp4.c')
-rw-r--r-- | examples/ipsec-secgw/sp4.c | 538 |
1 files changed, 313 insertions, 225 deletions
diff --git a/examples/ipsec-secgw/sp4.c b/examples/ipsec-secgw/sp4.c index 9c4b256b..38c72a92 100644 --- a/examples/ipsec-secgw/sp4.c +++ b/examples/ipsec-secgw/sp4.c @@ -42,8 +42,9 @@ #include <rte_ip.h> #include "ipsec.h" +#include "parser.h" -#define MAX_ACL_RULE_NUM 1000 +#define MAX_ACL_RULE_NUM 1024 /* * Rule and trace formats definitions. @@ -113,211 +114,306 @@ struct rte_acl_field_def ip4_defs[NUM_FIELDS_IPV4] = { RTE_ACL_RULE_DEF(acl4_rules, RTE_DIM(ip4_defs)); -const struct acl4_rules acl4_rules_out[] = { - { - .data = {.userdata = PROTECT(5), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 105, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(6), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 106, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(10), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 175, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(11), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 176, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(15), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 200, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(16), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 201, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(25), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 55, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(26), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 56, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = BYPASS, .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 240, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = BYPASS, .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 241, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} +struct acl4_rules acl4_rules_out[MAX_ACL_RULE_NUM]; +uint32_t nb_acl4_rules_out; + +struct acl4_rules acl4_rules_in[MAX_ACL_RULE_NUM]; +uint32_t nb_acl4_rules_in; + +void +parse_sp4_tokens(char **tokens, uint32_t n_tokens, + struct parse_status *status) +{ + struct acl4_rules *rule_ipv4 = NULL; + + uint32_t *ri = NULL; /* rule index */ + uint32_t ti = 0; /* token index */ + + uint32_t esp_p = 0; + uint32_t protect_p = 0; + uint32_t bypass_p = 0; + uint32_t discard_p = 0; + uint32_t pri_p = 0; + uint32_t src_p = 0; + uint32_t dst_p = 0; + uint32_t proto_p = 0; + uint32_t sport_p = 0; + uint32_t dport_p = 0; + + if (strcmp(tokens[1], "in") == 0) { + ri = &nb_acl4_rules_in; + + APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, + "too many sp rules, abort insertion\n"); + if (status->status < 0) + return; + + rule_ipv4 = &acl4_rules_in[*ri]; + + } else if (strcmp(tokens[1], "out") == 0) { + ri = &nb_acl4_rules_out; + + APP_CHECK(*ri <= MAX_ACL_RULE_NUM - 1, status, + "too many sp rules, abort insertion\n"); + if (status->status < 0) + return; + + rule_ipv4 = &acl4_rules_out[*ri]; + } else { + APP_CHECK(0, status, "unrecognized input \"%s\", expect" + " \"in\" or \"out\"\n", tokens[ti]); + return; } -}; -const struct acl4_rules acl4_rules_in[] = { - { - .data = {.userdata = PROTECT(105), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 115, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(106), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 116, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(110), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 185, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(111), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 186, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(115), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 210, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(116), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 211, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(125), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 65, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = PROTECT(126), .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 66, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = BYPASS, .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 245, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} - }, - { - .data = {.userdata = BYPASS, .category_mask = 1, .priority = 1}, - /* destination IPv4 */ - .field[2] = {.value.u32 = IPv4(192, 168, 246, 0), - .mask_range.u32 = 24,}, - /* source port */ - .field[3] = {.value.u16 = 0, .mask_range.u16 = 0xffff,}, - /* destination port */ - .field[4] = {.value.u16 = 0, .mask_range.u16 = 0xffff,} + rule_ipv4->data.category_mask = 1; + + for (ti = 2; ti < n_tokens; ti++) { + if (strcmp(tokens[ti], "esp") == 0) { + /* currently do nothing */ + APP_CHECK_PRESENCE(esp_p, tokens[ti], status); + if (status->status < 0) + return; + esp_p = 1; + continue; + } + + if (strcmp(tokens[ti], "protect") == 0) { + APP_CHECK_PRESENCE(protect_p, tokens[ti], status); + if (status->status < 0) + return; + APP_CHECK(bypass_p == 0, status, "conflict item " + "between \"%s\" and \"%s\"", tokens[ti], + "bypass"); + if (status->status < 0) + return; + APP_CHECK(discard_p == 0, status, "conflict item " + "between \"%s\" and \"%s\"", tokens[ti], + "discard"); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); + if (status->status < 0) + return; + + rule_ipv4->data.userdata = + PROTECT(atoi(tokens[ti])); + + protect_p = 1; + continue; + } + + if (strcmp(tokens[ti], "bypass") == 0) { + APP_CHECK_PRESENCE(bypass_p, tokens[ti], status); + if (status->status < 0) + return; + APP_CHECK(protect_p == 0, status, "conflict item " + "between \"%s\" and \"%s\"", tokens[ti], + "protect"); + if (status->status < 0) + return; + APP_CHECK(discard_p == 0, status, "conflict item " + "between \"%s\" and \"%s\"", tokens[ti], + "discard"); + if (status->status < 0) + return; + + rule_ipv4->data.userdata = BYPASS; + + bypass_p = 1; + continue; + } + + if (strcmp(tokens[ti], "discard") == 0) { + APP_CHECK_PRESENCE(discard_p, tokens[ti], status); + if (status->status < 0) + return; + APP_CHECK(protect_p == 0, status, "conflict item " + "between \"%s\" and \"%s\"", tokens[ti], + "protect"); + if (status->status < 0) + return; + APP_CHECK(bypass_p == 0, status, "conflict item " + "between \"%s\" and \"%s\"", tokens[ti], + "discard"); + if (status->status < 0) + return; + + rule_ipv4->data.userdata = DISCARD; + + discard_p = 1; + continue; + } + + if (strcmp(tokens[ti], "pri") == 0) { + APP_CHECK_PRESENCE(pri_p, tokens[ti], status); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); + if (status->status < 0) + return; + + rule_ipv4->data.priority = atoi(tokens[ti]); + + pri_p = 1; + continue; + } + + if (strcmp(tokens[ti], "src") == 0) { + struct in_addr ip; + uint32_t depth; + + APP_CHECK_PRESENCE(src_p, tokens[ti], status); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + + APP_CHECK(parse_ipv4_addr(tokens[ti], &ip, + &depth) == 0, status, "unrecognized " + "input \"%s\", expect valid ipv4 addr", + tokens[ti]); + if (status->status < 0) + return; + + rule_ipv4->field[1].value.u32 = + rte_bswap32(ip.s_addr); + rule_ipv4->field[1].mask_range.u32 = + depth; + + src_p = 1; + continue; + } + + if (strcmp(tokens[ti], "dst") == 0) { + struct in_addr ip; + uint32_t depth; + + APP_CHECK_PRESENCE(dst_p, tokens[ti], status); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + APP_CHECK(parse_ipv4_addr(tokens[ti], &ip, + &depth) == 0, status, "unrecognized " + "input \"%s\", expect valid ipv4 addr", + tokens[ti]); + if (status->status < 0) + return; + + rule_ipv4->field[2].value.u32 = + rte_bswap32(ip.s_addr); + rule_ipv4->field[2].mask_range.u32 = + depth; + + dst_p = 1; + continue; + } + + if (strcmp(tokens[ti], "proto") == 0) { + uint16_t low, high; + + APP_CHECK_PRESENCE(proto_p, tokens[ti], status); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + + APP_CHECK(parse_range(tokens[ti], &low, &high) + == 0, status, "unrecognized input \"%s\"" + ", expect \"from:to\"", tokens[ti]); + if (status->status < 0) + return; + APP_CHECK(low <= 0xff, status, "proto low " + "over-limit"); + if (status->status < 0) + return; + APP_CHECK(high <= 0xff, status, "proto high " + "over-limit"); + if (status->status < 0) + return; + + rule_ipv4->field[0].value.u8 = (uint8_t)low; + rule_ipv4->field[0].mask_range.u8 = (uint8_t)high; + + proto_p = 1; + continue; + } + + if (strcmp(tokens[ti], "sport") == 0) { + uint16_t port_low, port_high; + + APP_CHECK_PRESENCE(sport_p, tokens[ti], status); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + + APP_CHECK(parse_range(tokens[ti], &port_low, + &port_high) == 0, status, "unrecognized " + "input \"%s\", expect \"port_from:" + "port_to\"", tokens[ti]); + if (status->status < 0) + return; + + rule_ipv4->field[3].value.u16 = port_low; + rule_ipv4->field[3].mask_range.u16 = port_high; + + sport_p = 1; + continue; + } + + if (strcmp(tokens[ti], "dport") == 0) { + uint16_t port_low, port_high; + + APP_CHECK_PRESENCE(dport_p, tokens[ti], status); + if (status->status < 0) + return; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + + APP_CHECK(parse_range(tokens[ti], &port_low, + &port_high) == 0, status, "unrecognized " + "input \"%s\", expect \"port_from:" + "port_to\"", tokens[ti]); + if (status->status < 0) + return; + + rule_ipv4->field[4].value.u16 = port_low; + rule_ipv4->field[4].mask_range.u16 = port_high; + + dport_p = 1; + continue; + } + + /* unrecognizeable input */ + APP_CHECK(0, status, "unrecognized input \"%s\"", + tokens[ti]); + return; } -}; + + /* check if argument(s) are missing */ + APP_CHECK(esp_p == 1, status, "missing argument \"esp\""); + if (status->status < 0) + return; + + APP_CHECK(protect_p | bypass_p | discard_p, status, "missing " + "argument \"protect\", \"bypass\", or \"discard\""); + if (status->status < 0) + return; + + *ri = *ri + 1; +} static void print_one_ip4_rule(const struct acl4_rules *rule, int32_t extra) @@ -406,11 +502,9 @@ acl4_init(const char *name, int32_t socketid, const struct acl4_rules *rules, } void -sp4_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep) +sp4_init(struct socket_ctx *ctx, int32_t socket_id) { const char *name; - const struct acl4_rules *rules_out, *rules_in; - uint32_t nb_out_rules, nb_in_rules; if (ctx == NULL) rte_exit(EXIT_FAILURE, "NULL context.\n"); @@ -423,25 +517,19 @@ sp4_init(struct socket_ctx *ctx, int32_t socket_id, uint32_t ep) rte_exit(EXIT_FAILURE, "Outbound SP DB for socket %u already " "initialized\n", socket_id); - if (ep == 0) { - rules_out = acl4_rules_out; - nb_out_rules = RTE_DIM(acl4_rules_out); - rules_in = acl4_rules_in; - nb_in_rules = RTE_DIM(acl4_rules_in); - } else if (ep == 1) { - rules_out = acl4_rules_in; - nb_out_rules = RTE_DIM(acl4_rules_in); - rules_in = acl4_rules_out; - nb_in_rules = RTE_DIM(acl4_rules_out); + if (nb_acl4_rules_in > 0) { + name = "sp_ip4_in"; + ctx->sp_ip4_in = (struct sp_ctx *)acl4_init(name, + socket_id, acl4_rules_in, nb_acl4_rules_in); } else - rte_exit(EXIT_FAILURE, "Invalid EP value %u. " - "Only 0 or 1 supported.\n", ep); - - name = "sp_ip4_in"; - ctx->sp_ip4_in = (struct sp_ctx *)acl4_init(name, socket_id, - rules_in, nb_in_rules); + RTE_LOG(WARNING, IPSEC, "No IPv4 SP Inbound rule " + "specified\n"); - name = "sp_ip4_out"; - ctx->sp_ip4_out = (struct sp_ctx *)acl4_init(name, socket_id, - rules_out, nb_out_rules); + if (nb_acl4_rules_out > 0) { + name = "sp_ip4_out"; + ctx->sp_ip4_out = (struct sp_ctx *)acl4_init(name, + socket_id, acl4_rules_out, nb_acl4_rules_out); + } else + RTE_LOG(WARNING, IPSEC, "No IPv4 SP Outbound rule " + "specified\n"); } |