From 7e629bad0f752f6fb3e3a435666307992e74bee2 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 21 May 2008 13:30:43 +0200 Subject: add full support of SCTP --- src/conntrack/build.c | 19 +++++++++++++++++++ src/conntrack/compare.c | 5 +++++ src/conntrack/copy.c | 23 +++++++++++++++++++++++ src/conntrack/getter.c | 18 ++++++++++++++++++ src/conntrack/parse.c | 34 +++++++++++++++++++++++++++++++--- src/conntrack/setter.c | 18 ++++++++++++++++++ src/conntrack/snprintf_default.c | 22 ++++++++++++++++++++++ 7 files changed, 136 insertions(+), 3 deletions(-) (limited to 'src/conntrack') diff --git a/src/conntrack/build.c b/src/conntrack/build.c index 638fbe2..f11af42 100644 --- a/src/conntrack/build.c +++ b/src/conntrack/build.c @@ -123,6 +123,25 @@ void __build_protoinfo(struct nfnlhdr *req, nfnl_nest_end(&req->nlh, nest_proto); nfnl_nest_end(&req->nlh, nest); break; + case IPPROTO_SCTP: + nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO); + nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_SCTP); + if (test_bit(ATTR_SCTP_STATE, ct->set)) + nfnl_addattr_l(&req->nlh, size, + CTA_PROTOINFO_SCTP_STATE, + &ct->protoinfo.sctp.state, + sizeof(u_int8_t)); + if (test_bit(ATTR_SCTP_VTAG_ORIG, ct->set)) + nfnl_addattr32(&req->nlh, size, + CTA_PROTOINFO_SCTP_VTAG_ORIGINAL, + htonl(ct->protoinfo.sctp.vtag[__DIR_ORIG])); + if (test_bit(ATTR_SCTP_VTAG_REPL, ct->set)) + nfnl_addattr32(&req->nlh, size, + CTA_PROTOINFO_SCTP_VTAG_REPLY, + htonl(ct->protoinfo.sctp.vtag[__DIR_REPL])); + nfnl_nest_end(&req->nlh, nest_proto); + nfnl_nest_end(&req->nlh, nest); + break; default: break; } diff --git a/src/conntrack/compare.c b/src/conntrack/compare.c index cd51f9d..d30a902 100644 --- a/src/conntrack/compare.c +++ b/src/conntrack/compare.c @@ -222,6 +222,11 @@ static int cmp_meta(const struct nf_conntrack *ct1, ct1->protoinfo.tcp.state != ct2->protoinfo.tcp.state) return 0; + if (test_bit(ATTR_SCTP_STATE, ct1->set) && + test_bit(ATTR_SCTP_STATE, ct2->set) && + ct1->protoinfo.sctp.state != ct2->protoinfo.sctp.state) + return 0; + return 1; } diff --git a/src/conntrack/copy.c b/src/conntrack/copy.c index 142f868..562f801 100644 --- a/src/conntrack/copy.c +++ b/src/conntrack/copy.c @@ -224,6 +224,26 @@ static void copy_attr_tcp_mask_repl(struct nf_conntrack *dest, orig->protoinfo.tcp.flags[__DIR_REPL].mask; } +static void copy_attr_sctp_state(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->protoinfo.sctp.state = orig->protoinfo.sctp.state; +} + +static void copy_attr_sctp_vtag_orig(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->protoinfo.sctp.vtag[__DIR_ORIG] = + orig->protoinfo.sctp.vtag[__DIR_ORIG]; +} + +static void copy_attr_sctp_vtag_repl(struct nf_conntrack *dest, + const struct nf_conntrack *orig) +{ + dest->protoinfo.sctp.vtag[__DIR_REPL] = + orig->protoinfo.sctp.vtag[__DIR_REPL]; +} + static void copy_attr_snat_ipv4(struct nf_conntrack *dest, const struct nf_conntrack *orig) { @@ -403,4 +423,7 @@ copy_attr copy_attr_array[] = { [ATTR_REPL_NAT_SEQ_CORRECTION_POS] = copy_attr_repl_cor_pos, [ATTR_REPL_NAT_SEQ_OFFSET_BEFORE] = copy_attr_repl_off_bfr, [ATTR_REPL_NAT_SEQ_OFFSET_AFTER] = copy_attr_repl_off_aft, + [ATTR_SCTP_STATE] = copy_attr_sctp_state, + [ATTR_SCTP_VTAG_ORIG] = copy_attr_sctp_vtag_orig, + [ATTR_SCTP_VTAG_REPL] = copy_attr_sctp_vtag_repl, }; diff --git a/src/conntrack/getter.c b/src/conntrack/getter.c index 48ba386..8591f88 100644 --- a/src/conntrack/getter.c +++ b/src/conntrack/getter.c @@ -167,6 +167,21 @@ static const void *get_attr_tcp_mask_repl(const struct nf_conntrack *ct) return &ct->protoinfo.tcp.flags[__DIR_REPL].mask; } +static const void *get_attr_sctp_state(const struct nf_conntrack *ct) +{ + return &ct->protoinfo.sctp.state; +} + +static const void *get_attr_sctp_vtag_orig(const struct nf_conntrack *ct) +{ + return &ct->protoinfo.sctp.vtag[__DIR_ORIG]; +} + +static const void *get_attr_sctp_vtag_repl(const struct nf_conntrack *ct) +{ + return &ct->protoinfo.sctp.vtag[__DIR_REPL]; +} + static const void *get_attr_snat_ipv4(const struct nf_conntrack *ct) { return &ct->snat.min_ip; @@ -320,4 +335,7 @@ get_attr get_attr_array[] = { [ATTR_REPL_NAT_SEQ_CORRECTION_POS] = get_attr_repl_cor_pos, [ATTR_REPL_NAT_SEQ_OFFSET_BEFORE] = get_attr_repl_off_bfr, [ATTR_REPL_NAT_SEQ_OFFSET_AFTER] = get_attr_repl_off_aft, + [ATTR_SCTP_STATE] = get_attr_sctp_state, + [ATTR_SCTP_VTAG_ORIG] = get_attr_sctp_vtag_orig, + [ATTR_SCTP_VTAG_REPL] = get_attr_sctp_vtag_repl, }; diff --git a/src/conntrack/parse.c b/src/conntrack/parse.c index c21f304..a18e3ad 100644 --- a/src/conntrack/parse.c +++ b/src/conntrack/parse.c @@ -217,6 +217,33 @@ static void __parse_protoinfo_tcp(const struct nfattr *attr, } } +static void __parse_protoinfo_sctp(const struct nfattr *attr, + struct nf_conntrack *ct) +{ + struct nfattr *tb[CTA_PROTOINFO_SCTP_MAX]; + + nfnl_parse_nested(tb, CTA_PROTOINFO_SCTP_MAX, attr); + + if (tb[CTA_PROTOINFO_SCTP_STATE-1]) { + ct->protoinfo.sctp.state = + *(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_SCTP_STATE-1]); + set_bit(ATTR_SCTP_STATE, ct->set); + } + + if (tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL-1]) { + ct->protoinfo.sctp.vtag[__DIR_ORIG] = + ntohl(*(u_int32_t *)NFA_DATA(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL-1])); + set_bit(ATTR_SCTP_VTAG_ORIG, ct->set); + } + + if (tb[CTA_PROTOINFO_SCTP_VTAG_REPLY-1]) { + ct->protoinfo.sctp.vtag[__DIR_ORIG] = + ntohl(*(u_int32_t *)NFA_DATA(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY-1])); + set_bit(ATTR_SCTP_VTAG_ORIG, ct->set); + } + +} + static void __parse_protoinfo(const struct nfattr *attr, struct nf_conntrack *ct) { @@ -224,10 +251,11 @@ static void __parse_protoinfo(const struct nfattr *attr, nfnl_parse_nested(tb, CTA_PROTOINFO_MAX, attr); - if (!tb[CTA_PROTOINFO_TCP-1]) - return; + if (tb[CTA_PROTOINFO_TCP-1]) + __parse_protoinfo_tcp(tb[CTA_PROTOINFO_TCP-1], ct); - __parse_protoinfo_tcp(tb[CTA_PROTOINFO_TCP-1], ct); + if (tb[CTA_PROTOINFO_SCTP-1]) + __parse_protoinfo_sctp(tb[CTA_PROTOINFO_SCTP-1], ct); } static void __parse_counters(const struct nfattr *attr, diff --git a/src/conntrack/setter.c b/src/conntrack/setter.c index 52a2aab..53698bf 100644 --- a/src/conntrack/setter.c +++ b/src/conntrack/setter.c @@ -170,6 +170,21 @@ static void set_attr_tcp_mask_repl(struct nf_conntrack *ct, const void *value) ct->protoinfo.tcp.flags[__DIR_REPL].mask = *((u_int8_t *) value); } +static void set_attr_sctp_state(struct nf_conntrack *ct, const void *value) +{ + ct->protoinfo.sctp.state = *((u_int8_t *) value); +} + +static void set_attr_sctp_vtag_orig(struct nf_conntrack *ct, const void *value) +{ + ct->protoinfo.sctp.vtag[__DIR_ORIG] = *((u_int32_t *) value); +} + +static void set_attr_sctp_vtag_repl(struct nf_conntrack *ct, const void *value) +{ + ct->protoinfo.sctp.vtag[__DIR_REPL] = *((u_int32_t *) value); +} + static void set_attr_snat_ipv4(struct nf_conntrack *ct, const void *value) { ct->snat.min_ip = ct->snat.max_ip = *((u_int32_t *) value); @@ -340,4 +355,7 @@ set_attr set_attr_array[] = { [ATTR_REPL_NAT_SEQ_CORRECTION_POS] = set_attr_repl_cor_pos, [ATTR_REPL_NAT_SEQ_OFFSET_BEFORE] = set_attr_repl_off_aft, [ATTR_REPL_NAT_SEQ_OFFSET_AFTER] = set_attr_repl_off_bfr, + [ATTR_SCTP_STATE] = set_attr_sctp_state, + [ATTR_SCTP_VTAG_ORIG] = set_attr_sctp_vtag_orig, + [ATTR_SCTP_VTAG_REPL] = set_attr_sctp_vtag_repl, }; diff --git a/src/conntrack/snprintf_default.c b/src/conntrack/snprintf_default.c index e2573df..e89f2f5 100644 --- a/src/conntrack/snprintf_default.c +++ b/src/conntrack/snprintf_default.c @@ -34,6 +34,17 @@ static const char *states[] = { "LISTEN" }; +static const char *sctp_states[] = { + "NONE", + "CLOSED", + "COOKIE_WAIT", + "COOKIE_ECHOED", + "ESTABLISHED", + "SHUTDOWN_SENT", + "SHUTDOWN_RECD", + "SHUTDOWN_ACK_SENT", +}; + static int __snprintf_l3protocol(char *buf, unsigned int len, const struct nf_conntrack *ct) @@ -67,6 +78,12 @@ int __snprintf_protoinfo(char *buf, { return snprintf(buf, len, "%s ", states[ct->protoinfo.tcp.state]); } +int __snprintf_protoinfo_sctp(char *buf, + unsigned int len, + const struct nf_conntrack *ct) +{ + return snprintf(buf, len, "%s ", sctp_states[ct->protoinfo.sctp.state]); +} int __snprintf_address_ipv4(char *buf, unsigned int len, @@ -260,6 +277,11 @@ int __snprintf_conntrack_default(char *buf, BUFFER_SIZE(ret, size, len, offset); } + if (test_bit(ATTR_SCTP_STATE, ct->set)) { + ret = __snprintf_protoinfo_sctp(buf+offset, len, ct); + BUFFER_SIZE(ret, size, len, offset); + } + ret = __snprintf_address(buf+offset, len, &ct->tuple[__DIR_ORIG]); BUFFER_SIZE(ret, size, len, offset); -- cgit v1.2.3