From 8e63e483240687ee4c4325073d84926e39416bc9 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 4 Jan 2012 17:16:39 +0100 Subject: expect: add nfexp_cmp This patch adds nfexp_cmp that allows you to compare two expectation objects. This includes the extension of test_api for this new function. Signed-off-by: Pablo Neira Ayuso --- include/internal/prototypes.h | 2 + .../libnetfilter_conntrack.h | 4 ++ qa/test_api.c | 22 +++++++- src/conntrack/compare.c | 10 ++-- src/expect/Makefile.am | 1 + src/expect/api.c | 34 +++++++++++++ src/expect/compare.c | 59 ++++++++++++++++++++++ 7 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 src/expect/compare.c diff --git a/include/internal/prototypes.h b/include/internal/prototypes.h index 5f1418f..7ca8d35 100644 --- a/include/internal/prototypes.h +++ b/include/internal/prototypes.h @@ -21,6 +21,7 @@ int __callback(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data); int __setobjopt(struct nf_conntrack *ct, unsigned int option); int __getobjopt(const struct nf_conntrack *ct, unsigned int option); int __compare(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2, unsigned int flags); +int __cmp_orig(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2, unsigned int flags); void __copy_fast(struct nf_conntrack *ct1, const struct nf_conntrack *ct); int __setup_netlink_socket_filter(int fd, struct nfct_filter *filter); @@ -32,6 +33,7 @@ int __build_expect(struct nfnl_subsys_handle *ssh, struct nfnlhdr *req, size_t s int __parse_expect_message_type(const struct nlmsghdr *nlh); void __parse_expect(const struct nlmsghdr *nlh, struct nfattr *cda[], struct nf_expect *exp); int __expect_callback(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data); +int __cmp_expect(const struct nf_expect *exp1, const struct nf_expect *exp2, unsigned int flags); int __snprintf_expect(char *buf, unsigned int len, const struct nf_expect *exp, unsigned int type, unsigned int msg_output, unsigned int flags); int __snprintf_expect_default(char *buf, unsigned int len, const struct nf_expect *exp, unsigned int msg_type, unsigned int flags); diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h index 89d07ad..2e1c22c 100644 --- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h +++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h @@ -599,6 +599,10 @@ extern int nfexp_snprintf(char *buf, const unsigned int out_type, const unsigned int out_flags); +/* compare */ +extern int nfexp_cmp(const struct nf_expect *exp1, + const struct nf_expect *exp2, + unsigned int flags); extern int nfexp_send(struct nfct_handle *h, const enum nf_conntrack_query qt, diff --git a/qa/test_api.c b/qa/test_api.c index 1efaf2f..74f02d0 100644 --- a/qa/test_api.c +++ b/qa/test_api.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -33,7 +34,7 @@ int main(void) { int ret, i; struct nf_conntrack *ct, *tmp; - struct nf_expect *exp; + struct nf_expect *exp, *tmp_exp; char data[32]; const char *val; int status; @@ -135,6 +136,11 @@ int main(void) perror("nfexp_new"); return 0; } + tmp_exp = nfexp_new(); + if (!tmp_exp) { + perror("nfexp_new"); + return 0; + } printf("== test expect set API ==\n"); ret = fork(); @@ -180,8 +186,22 @@ int main(void) eval_sigterm(status); } + /* XXX: missing nfexp_copy API. */ + memcpy(tmp_exp, exp, nfexp_maxsize()); + + printf("== test expect cmp API ==\n"); + ret = fork(); + if (ret == 0) { + nfexp_cmp(tmp_exp, exp, 0); + exit(0); + } else { + wait(&status); + eval_sigterm(status); + } + nfct_destroy(ct); nfct_destroy(tmp); nfexp_destroy(exp); + nfexp_destroy(tmp_exp); return EXIT_SUCCESS; } diff --git a/src/conntrack/compare.c b/src/conntrack/compare.c index f94f1b9..830195f 100644 --- a/src/conntrack/compare.c +++ b/src/conntrack/compare.c @@ -144,9 +144,9 @@ cmp_orig_ipv6_dst(const struct nf_conntrack *ct1, sizeof(struct in6_addr)) == 0); } -static int cmp_orig(const struct nf_conntrack *ct1, - const struct nf_conntrack *ct2, - unsigned int flags) +int __cmp_orig(const struct nf_conntrack *ct1, + const struct nf_conntrack *ct2, + unsigned int flags) { if (!__cmp(ATTR_ORIG_L3PROTO, ct1, ct2, flags, cmp_orig_l3proto)) return 0; @@ -399,10 +399,10 @@ int __compare(const struct nf_conntrack *ct1, { if ((flags & ~(NFCT_CMP_MASK|NFCT_CMP_STRICT)) == NFCT_CMP_ALL) return cmp_meta(ct1, ct2, flags) && - cmp_orig(ct1, ct2, flags) && + __cmp_orig(ct1, ct2, flags) && cmp_repl(ct1, ct2, flags); - if (flags & NFCT_CMP_ORIG && !cmp_orig(ct1, ct2, flags)) + if (flags & NFCT_CMP_ORIG && !__cmp_orig(ct1, ct2, flags)) return 0; if (flags & NFCT_CMP_REPL && !cmp_repl(ct1, ct2, flags)) diff --git a/src/expect/Makefile.am b/src/expect/Makefile.am index 8adf740..977a359 100644 --- a/src/expect/Makefile.am +++ b/src/expect/Makefile.am @@ -3,6 +3,7 @@ include $(top_srcdir)/Make_global.am noinst_LTLIBRARIES = libnfexpect.la libnfexpect_la_SOURCES = api.c \ + compare.c \ getter.c setter.c \ parse.c build.c \ snprintf.c \ diff --git a/src/expect/api.c b/src/expect/api.c index cf45091..4da44a0 100644 --- a/src/expect/api.c +++ b/src/expect/api.c @@ -98,6 +98,40 @@ struct nf_expect *nfexp_clone(const struct nf_expect *exp) return clone; } +/** + * nfexp_cmp - compare two expectation objects + * \param exp1 pointer to a valid expectation object + * \param exp2 pointer to a valid expectation object + * \param flags flags + * + * This function only compare attribute set in both objects, by default + * the comparison is not strict, ie. if a certain attribute is not set in one + * of the objects, then such attribute is not used in the comparison. + * If you want more strict comparisons, you can use the appropriate flags + * to modify this behaviour (see NFCT_CMP_STRICT and NFCT_CMP_MASK). + * + * The available flags are: + * - NFCT_CMP_STRICT: the compared objects must have the same attributes + * and the same values, otherwise it returns that the objects are + * different. + * - NFCT_CMP_MASK: the first object is used as mask, this means that + * if an attribute is present in exp1 but not in exp2, this function + * returns that the objects are different. + * + * Other existing flags that are used by nfct_cmp() are ignored. + * + * If both conntrack object are equal, this function returns 1, otherwise + * 0 is returned. + */ +int nfexp_cmp(const struct nf_expect *exp1, const struct nf_expect *exp2, + unsigned int flags) +{ + assert(exp1 != NULL); + assert(exp2 != NULL); + + return __cmp_expect(exp1, exp2, flags); +} + /** * @} */ diff --git a/src/expect/compare.c b/src/expect/compare.c new file mode 100644 index 0000000..65ec9c2 --- /dev/null +++ b/src/expect/compare.c @@ -0,0 +1,59 @@ +/* + * (C) 2005-2012 by Pablo Neira Ayuso + * (C) 2012 by Vyatta Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include "internal/internal.h" + +static int exp_cmp(int attr, + const struct nf_expect *exp1, + const struct nf_expect *exp2, + unsigned int flags, + int (*cmp)(const struct nf_expect *exp1, + const struct nf_expect *exp2, + unsigned int flags)) +{ + if (test_bit(attr, exp1->set) && test_bit(attr, exp2->set)) { + return cmp(exp1, exp2, flags); + } else if (flags & NFCT_CMP_MASK && + test_bit(attr, exp1->set)) { + return 0; + } else if (flags & NFCT_CMP_STRICT) { + return 0; + } + return 1; +} + +static int +cmp_exp_flags(const struct nf_expect *exp1, const struct nf_expect *exp, + unsigned int flags) +{ + return (exp->flags == exp->flags); +} + +int __cmp_expect(const struct nf_expect *exp1, + const struct nf_expect *exp2, + unsigned int flags) +{ + if (!__cmp_orig((struct nf_conntrack *)&exp1->master, + (struct nf_conntrack *)&exp2->master, flags)) { + return 0; + } + if (!__cmp_orig((struct nf_conntrack *)&exp1->expected, + (struct nf_conntrack *)&exp2->expected, flags)) { + return 0; + } + if (!__cmp_orig((struct nf_conntrack *)&exp1->mask, + (struct nf_conntrack *)&exp2->mask, flags)) { + return 0; + } + if (!exp_cmp(ATTR_EXP_FLAGS, exp1, exp2, flags, cmp_exp_flags)) + return 0; + + return 1; +} -- cgit v1.2.3