Index: include/cache.h =================================================================== --- include/cache.h (revisión: 13) +++ include/cache.h (copia de trabajo) @@ -61,14 +61,14 @@ unsigned int flush; }; -struct nfct_conntrack; +struct nf_conntrack; -struct cache *cache_create(char *name, unsigned int features); +struct cache *cache_create(char *name, unsigned int features, u_int8_t proto); void cache_destroy(struct cache *e); -int cache_add_entry(struct cache *c, struct nfct_conntrack *ct); -int cache_update_entry(struct cache *c, struct nfct_conntrack *ct, u_int32_t flags); -int cache_del_entry(struct cache *c, struct nfct_conntrack *ct); +int cache_add_entry(struct cache *c, struct nf_conntrack *ct); +int cache_update_entry(struct cache *c, struct nf_conntrack *ct); +int cache_del_entry(struct cache *c, struct nf_conntrack *ct); void cache_dump(struct cache *c, int fd); void cache_commit(struct cache *c); Index: include/conntrackd.h =================================================================== --- include/conntrackd.h (revisión: 20) +++ include/conntrackd.h (copia de trabajo) @@ -76,6 +76,7 @@ union inet_address *listen_to; unsigned int listen_to_len; unsigned int flags; + int family; /* protocol family */ }; #define STATE(x) st.x @@ -139,14 +140,10 @@ void (*step)(fd_set *readfds); void (*local)(int fd, int type, void *data); void (*kill)(void); - void (*dump)(struct nfct_conntrack *ct, struct nlmsghdr *nlh, - unsigned int flags); - void (*event_new)(struct nfct_conntrack *ct, struct nlmsghdr *nlh, - unsigned int flags); - void (*event_upd)(struct nfct_conntrack *ct, struct nlmsghdr *nlh, - unsigned int flags); - int (*event_dst)(struct nfct_conntrack *ct, struct nlmsghdr *nlh, - unsigned int flags); + void (*dump)(struct nf_conntrack *ct, struct nlmsghdr *nlh); + void (*event_new)(struct nf_conntrack *ct, struct nlmsghdr *nlh); + void (*event_upd)(struct nf_conntrack *ct, struct nlmsghdr *nlh); + int (*event_dst)(struct nf_conntrack *ct, struct nlmsghdr *nlh); }; /* conntrackd modes */ Index: include/debug.h =================================================================== --- include/debug.h (revisión: 2) +++ include/debug.h (copia de trabajo) @@ -7,26 +7,47 @@ #define debug #endif +#include +#include #include -static inline void dump_tuple(struct nfct_tuple *tp) +static inline void debug_ct(struct nf_conntrack *ct, char *msg) { - struct in_addr src = { .s_addr = tp->src.v4 }; - struct in_addr dst = { .s_addr = tp->dst.v4 }; + struct in_addr addr, addr2, addr3, addr4; - debug("tuple %p: %u %s:%hu -> ", tp, tp->protonum, - inet_ntoa(src), - ntohs(tp->l4src.all)); - debug("%s:%hu\n", inet_ntoa(dst), ntohs(tp->l4dst.all)); -} + debug("----%s (%p) ----\n", msg, ct); + memcpy(&addr, + nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC), + sizeof(u_int32_t)); + memcpy(&addr2, + nfct_get_attr(ct, ATTR_ORIG_IPV4_DST), + sizeof(u_int32_t)); + memcpy(&addr3, + nfct_get_attr(ct, ATTR_REPL_IPV4_SRC), + sizeof(u_int32_t)); + memcpy(&addr4, + nfct_get_attr(ct, ATTR_REPL_IPV4_DST), + sizeof(u_int32_t)); -static inline void debug_info(struct nfct_conntrack *ct, char *msg) -{ - debug("-------- %s --------\n", msg); - debug("status: %x\n", ct->status); - dump_tuple(&ct->tuple[NFCT_DIR_ORIGINAL]); - dump_tuple(&ct->tuple[NFCT_DIR_REPLY]); - debug("-------------------------\n"); + debug("status: %x\n", nfct_get_attr_u32(ct, ATTR_STATUS)); + debug("l3:%d l4:%d ", + nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO), + nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)); + debug("%s:%hu ->", inet_ntoa(addr), + ntohs(nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC))); + debug("%s:%hu\n", + inet_ntoa(addr2), + ntohs(nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST))); + debug("l3:%d l4:%d ", + nfct_get_attr_u8(ct, ATTR_REPL_L3PROTO), + nfct_get_attr_u8(ct, ATTR_REPL_L4PROTO)); + debug("%s:%hu ->", + inet_ntoa(addr3), + ntohs(nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC))); + debug("%s:%hu\n", + inet_ntoa(addr4), + ntohs(nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST))); + debug("-------------------------\n"); } #endif Index: include/us-conntrack.h =================================================================== --- include/us-conntrack.h (revisión: 8) +++ include/us-conntrack.h (copia de trabajo) @@ -5,7 +5,7 @@ /* be careful, do not modify the layout */ struct us_conntrack { - struct nfct_conntrack ct; + struct nf_conntrack *ct; struct cache *cache; /* add new attributes here */ char data[0]; }; Index: src/sync-mode.c =================================================================== --- src/sync-mode.c (revisión: 20) +++ src/sync-mode.c (copia de trabajo) @@ -30,13 +30,14 @@ static void mcast_handler() { int ret; - char buf[8192]; + char buf[4096], tmp[256]; struct mcast_sock *m = STATE_SYNC(mcast_server); - struct nfct_conntrack ct, *tmp; - unsigned int flags; unsigned int type; struct nlmsghdr *nlh = (struct nlmsghdr *) buf; + struct nf_conntrack *ct = (struct nf_conntrack *) tmp; + memset(tmp, 0, sizeof(tmp)); + ret = mcast_recv_netlink(m, nlh, sizeof(buf)); if (ret <= 0) return; @@ -56,43 +57,43 @@ */ mcast_track_netlink_seq(nlh->nlmsg_seq); - if (nl_parse_network_message(&ct, nlh, &type, &flags) < 0) { + if ((type = nl_parse_network_message(ct, nlh)) == NFCT_T_ERROR) { dlog(STATE(log), "mcast_handler says: bad netlink msg!"); return; } - /* - * Set a reduced timeout for candidate-to-be-committed - * conntracks that live in the external cache - */ - if (ct.timeout > CONFIG(commit_timeout)) - ct.timeout = CONFIG(commit_timeout); + /* This is required by kernels < 2.6.20 */ + nfct_attr_unset(ct, ATTR_TIMEOUT); + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); switch(type) { - case NFCT_MSG_NEW: + case NFCT_T_NEW: retry: - if (cache_add_entry(STATE_SYNC(external), &ct)) - debug_info(&ct, "external new"); + if (cache_add_entry(STATE_SYNC(external), ct)) + debug_ct(ct, "external new"); else { if (errno == EEXIST) { - cache_del_entry(STATE_SYNC(external), &ct); + cache_del_entry(STATE_SYNC(external), ct); goto retry; } - debug_info(&ct, "can't add"); + debug_ct(ct, "can't add"); } break; - case NFCT_MSG_UPDATE: - if (cache_update_force(STATE_SYNC(external), &ct, flags)) - debug_info(&ct, "external update"); + case NFCT_T_UPDATE: + if (cache_update_force(STATE_SYNC(external), ct)) + debug_ct(ct, "external update"); else - debug_info(&ct, "can't update"); + debug_ct(ct, "can't update"); break; - case NFCT_MSG_DESTROY: - if (cache_del_entry(STATE_SYNC(external), &ct)) - debug_info(&ct, "external destroy"); + case NFCT_T_DESTROY: + if (cache_del_entry(STATE_SYNC(external), ct)) + debug_ct(ct, "external destroy"); else - debug_info(&ct, "can't destroy"); + debug_ct(ct, "can't destroy"); break; default: debug("unknown type %d\n", type); @@ -111,7 +112,9 @@ } memset(state.sync, 0, sizeof(struct ct_sync_state)); - STATE_SYNC(internal) = cache_create("internal", PERSISTENCE | LIFETIME); + STATE_SYNC(internal) = cache_create("internal", + PERSISTENCE | LIFETIME, + CONFIG(family)); if (!STATE_SYNC(internal)) { dlog(STATE(log), "[FAIL] can't allocate memory for " "the internal cache"); @@ -120,7 +123,9 @@ dlog(STATE(log), "[OK] internal cache created"); - STATE_SYNC(external) = cache_create("external", TIMER | LIFETIME); + STATE_SYNC(external) = cache_create("external", + TIMER | LIFETIME, + CONFIG(family)); if (!STATE_SYNC(external)) { dlog(STATE(log), "[FAIL] can't allocate memory for the " "external cache"); @@ -240,30 +245,33 @@ } } -static void dump_sync(struct nfct_conntrack *ct, - struct nlmsghdr *nlh, - unsigned int flags) +static void dump_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) { - if (cache_update_force(STATE_SYNC(internal), ct, flags)) - debug_info(ct, "resync entry"); + nfct_attr_unset(ct, ATTR_TIMEOUT); + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_ORIG_COUNTER_PACKETS); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_BYTES); + nfct_attr_unset(ct, ATTR_REPL_COUNTER_PACKETS); + + if (cache_update_force(STATE_SYNC(internal), ct)) + debug_ct(ct, "resync"); } -static void event_new_sync(struct nfct_conntrack *ct, - struct nlmsghdr *nlh, - unsigned int flags) +static void event_new_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) { + nfct_attr_unset(ct, ATTR_TIMEOUT); retry: if (cache_add_entry(STATE_SYNC(internal), ct)) { mcast_send_netlink(STATE_SYNC(mcast_client), nlh); - debug_info(ct, "internal new"); + debug_ct(ct, "internal new"); } else { if (errno == EEXIST) { char buf[4096]; struct nlmsghdr *nlh = (struct nlmsghdr *) buf; - int ret = nl_build_network_message(NFCT_MSG_DESTROY, + int ret = nl_build_network_message(NFCT_Q_DESTROY, STATE(subsys_event), - &ct, + ct, buf, sizeof(buf)); if (ret == -1) @@ -275,15 +283,15 @@ } dlog(STATE(log), "can't add to internal cache: " "%s\n", strerror(errno)); - debug_info(ct, "can't add"); + debug_ct(ct, "can't add"); } } -static void event_update_sync(struct nfct_conntrack *ct, - struct nlmsghdr *nlh, - unsigned int flags) +static void event_update_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) { - if (!cache_update_entry(STATE_SYNC(internal), ct, flags)) { + nfct_attr_unset(ct, ATTR_TIMEOUT); + + if (!cache_update_entry(STATE_SYNC(internal), ct)) { /* * Perhaps we are losing events. If we are working * in relax mode then add a new entry to the cache. @@ -292,38 +300,37 @@ */ if ((CONFIG(flags) & RELAX_TRANSITIONS) && cache_add_entry(STATE_SYNC(internal), ct)) { - debug_info(ct, "forcing internal update"); + debug_ct(ct, "forcing internal update"); } else { - debug_info(ct, "can't update"); + debug_ct(ct, "can't update"); return; } } - debug_info(ct, "update"); + debug_ct(ct, "internal update"); mcast_send_netlink(STATE_SYNC(mcast_client), nlh); } -static int event_destroy_sync(struct nfct_conntrack *ct, - struct nlmsghdr *nlh, - unsigned int flags) +static int event_destroy_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) { + nfct_attr_unset(ct, ATTR_TIMEOUT); + if (CONFIG(flags) & DELAY_DESTROY_MSG) { - flags |= NFCT_STATUS; - ct->status |= IPS_DYING; + nfct_set_attr_u32(ct, ATTR_STATUS, IPS_DYING); - if (cache_update_entry(STATE_SYNC(internal), ct, flags)) { - debug_info(ct, "internal destroy"); + if (cache_update_entry(STATE_SYNC(internal), ct)) { + debug_ct(ct, "delay internal destroy"); return 1; } else { - debug_info(ct, "can't destroy!"); + debug_ct(ct, "can't delay destroy!"); return 0; } } else { if (cache_del_entry(STATE_SYNC(internal), ct)) { mcast_send_netlink(STATE_SYNC(mcast_client), nlh); - debug_info(ct, "internal destroy"); + debug_ct(ct, "internal destroy"); } else - debug_info(ct, "can't destroy"); + debug_ct(ct, "can't destroy"); } } Index: src/cache.c =================================================================== --- src/cache.c (revisión: 19) +++ src/cache.c (copia de trabajo) @@ -29,34 +29,91 @@ { unsigned int a, b; struct us_conntrack *u = data; - struct nfct_tuple *tuple = &u->ct.tuple[NFCT_DIR_ORIGINAL]; + struct nf_conntrack *ct = u->ct; - a = jhash((void *)tuple->src.v6, sizeof(tuple->src.v6), - ((tuple->l3protonum) << 16) | tuple->protonum); - b = jhash((void *)tuple->dst.v6, sizeof(tuple->dst.v6), - (tuple->l4src.all << 16) | tuple->l4dst.all); + a = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC), sizeof(u_int32_t), + ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | + (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)))); + b = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV4_DST), sizeof(u_int32_t), + ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) | + (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)))); + return jhash_2words(a, b, 0) % table->hashsize; } +static u_int32_t hash6(void *data, struct hashtable *table) +{ + unsigned int a, b; + struct us_conntrack *u = data; + struct nf_conntrack *ct = u->ct; + + a = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC), sizeof(u_int32_t), + ((nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16) | + (nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)))); + + b = jhash(nfct_get_attr(ct, ATTR_ORIG_IPV6_DST), sizeof(u_int32_t), + ((nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16) | + (nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)))); + + return jhash_2words(a, b, 0) % table->hashsize; +} + +static int __compare(struct nf_conntrack *ct1, struct nf_conntrack *ct2) +{ + return ((nfct_get_attr_u8(ct1, ATTR_ORIG_L3PROTO) == + nfct_get_attr_u8(ct2, ATTR_ORIG_L3PROTO)) && + (nfct_get_attr_u8(ct1, ATTR_ORIG_L4PROTO) == + nfct_get_attr_u8(ct2, ATTR_ORIG_L4PROTO)) && + (nfct_get_attr_u16(ct1, ATTR_ORIG_PORT_SRC) == + nfct_get_attr_u16(ct2, ATTR_ORIG_PORT_SRC)) && + (nfct_get_attr_u16(ct1, ATTR_ORIG_PORT_DST) == + nfct_get_attr_u16(ct2, ATTR_ORIG_PORT_DST)) && + (nfct_get_attr_u16(ct1, ATTR_REPL_PORT_SRC) == + nfct_get_attr_u16(ct2, ATTR_REPL_PORT_SRC)) && + (nfct_get_attr_u16(ct1, ATTR_REPL_PORT_DST) == + nfct_get_attr_u16(ct2, ATTR_REPL_PORT_DST))); +} + static int compare(void *data1, void *data2) { - struct us_conntrack *u = data1; - struct nfct_conntrack *ct = data2; + struct us_conntrack *u1 = data1; + struct us_conntrack *u2 = data2; - return nfct_tuple_equal(&u->ct.tuple[NFCT_DIR_ORIGINAL], - &ct->tuple[NFCT_DIR_ORIGINAL]) && - nfct_tuple_equal(&u->ct.tuple[NFCT_DIR_REPLY], - &ct->tuple[NFCT_DIR_REPLY]); + return ((nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV4_SRC) == + nfct_get_attr_u32(u2->ct, ATTR_ORIG_IPV4_SRC)) && + (nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV4_DST) == + nfct_get_attr_u32(u2->ct, ATTR_ORIG_IPV4_DST)) && + (nfct_get_attr_u32(u1->ct, ATTR_REPL_IPV4_SRC) == + nfct_get_attr_u32(u2->ct, ATTR_REPL_IPV4_SRC)) && + (nfct_get_attr_u32(u1->ct, ATTR_REPL_IPV4_DST) == + nfct_get_attr_u32(u2->ct, ATTR_REPL_IPV4_DST)) && + __compare(u1->ct, u2->ct)); } +static int compare6(void *data1, void *data2) +{ + struct us_conntrack *u1 = data1; + struct us_conntrack *u2 = data2; + + return ((nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV6_SRC) == + nfct_get_attr_u32(u2->ct, ATTR_ORIG_IPV6_SRC)) && + (nfct_get_attr_u32(u1->ct, ATTR_ORIG_IPV6_DST) == + nfct_get_attr_u32(u2->ct, ATTR_ORIG_IPV6_DST)) && + (nfct_get_attr_u32(u1->ct, ATTR_REPL_IPV6_SRC) == + nfct_get_attr_u32(u2->ct, ATTR_REPL_IPV6_SRC)) && + (nfct_get_attr_u32(u1->ct, ATTR_REPL_IPV6_DST) == + nfct_get_attr_u32(u2->ct, ATTR_REPL_IPV6_DST)) && + __compare(u1->ct, u2->ct)); +} + struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = { [TIMER_BIT] = &timer_feature, [PERSISTENCE_BIT] = &persistence_feature, [LIFETIME_BIT] = &lifetime_feature, }; -struct cache *cache_create(char *name, unsigned int features) +struct cache *cache_create(char *name, unsigned int features, u_int8_t proto) { size_t size = sizeof(struct us_conntrack); int i, j = 0; @@ -85,11 +142,23 @@ memcpy(c->features, feature_array, sizeof(struct cache_feature) * j); c->num_features = j; - c->h = hashtable_create(CONFIG(hashsize), - CONFIG(limit), - size, - hash, - compare); + switch(proto) { + case AF_INET: + c->h = hashtable_create(CONFIG(hashsize), + CONFIG(limit), + size, + hash, + compare); + break; + case AF_INET6: + c->h = hashtable_create(CONFIG(hashsize), + CONFIG(limit), + size, + hash6, + compare6); + break; + } + if (!c->h) { free(c->features); free(c); @@ -108,19 +177,27 @@ free(c); } -int __cache_add_entry(struct cache *c, struct nfct_conntrack *ct) +int __cache_add_entry(struct cache *c, struct nf_conntrack *ct) { - char buf[sizeof(struct us_conntrack) + c->h->datasize]; + int i; + size_t size = sizeof(struct us_conntrack) + c->h->datasize; + char buf[size]; struct us_conntrack *u = (struct us_conntrack *) buf; - size_t size; - int i; + memset(u, 0, size); + u->cache = c; - memcpy(&u->ct, ct, sizeof(struct nfct_conntrack)); + if ((u->ct = nfct_new()) == NULL) { + errno = ENOMEM; + c->add_fail++; + return 0; + } + memcpy(u->ct, ct, nfct_sizeof(ct)); u = hashtable_add(c->h, u); if (u) { void *data = u->data; + for (i = 0; i < c->num_features; i++) { c->features[i]->add(u, data); data += c->features[i]->size; @@ -142,7 +219,7 @@ c->add_fail++; return 0; } -int cache_add_entry(struct cache *c, struct nfct_conntrack *ct) +int cache_add_entry(struct cache *c, struct nf_conntrack *ct) { int ret; @@ -153,13 +230,15 @@ return ret; } -static int __cache_update_entry(struct cache *c, - struct nfct_conntrack *ct, - u_int32_t flags) +static int __cache_update_entry(struct cache *c, struct nf_conntrack *ct) { - struct us_conntrack *u; + size_t size = sizeof(struct us_conntrack) + c->h->datasize; + char buf[size]; + struct us_conntrack *u = (struct us_conntrack *) buf; - u = (struct us_conntrack *) hashtable_test(c->h, ct); + u->ct = ct; + + u = (struct us_conntrack *) hashtable_test(c->h, u); if (u) { int i; void *data = u->data; @@ -169,26 +248,25 @@ data += c->features[i]->size; } - if (flags & NFCT_STATUS) - u->ct.status |= ct->status; - if (flags & NFCT_PROTOINFO) - memcpy(&u->ct.protoinfo, - &ct->protoinfo, - sizeof(union nfct_protoinfo)); - if (flags & NFCT_TIMEOUT) - u->ct.timeout = ct->timeout; + if (nfct_attr_is_set(ct, ATTR_STATUS)) + nfct_set_attr_u32(u->ct, ATTR_STATUS, + nfct_get_attr_u32(ct, ATTR_STATUS)); + if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) + nfct_set_attr_u8(u->ct, ATTR_TCP_STATE, + nfct_get_attr_u8(ct, ATTR_TCP_STATE)); + if (nfct_attr_is_set(ct, ATTR_TIMEOUT)) + nfct_set_attr_u32(u->ct, ATTR_TIMEOUT, + nfct_get_attr_u32(ct, ATTR_TIMEOUT)); return 1; } return 0; } -int cache_update_entry(struct cache *c, - struct nfct_conntrack *ct, - u_int32_t flags) +int cache_update_entry(struct cache *c, struct nf_conntrack *ct) { lock(); - if (__cache_update_entry(c, ct, flags)) { + if (__cache_update_entry(c, ct)) { c->upd_ok++; unlock(); return 1; @@ -198,12 +276,10 @@ return 0; } -int cache_update_force(struct cache *c, - struct nfct_conntrack *ct, - u_int32_t flags) +int cache_update_force(struct cache *c, struct nf_conntrack *ct) { lock(); - if (__cache_update_entry(c, ct, flags)) { + if (__cache_update_entry(c, ct)) { c->upd_ok++; unlock(); return 1; @@ -218,21 +294,27 @@ return 0; } -int __cache_del_entry(struct cache *c, struct nfct_conntrack *ct) +int __cache_del_entry(struct cache *c, struct nf_conntrack *ct) { - struct us_conntrack *u; + size_t size = sizeof(struct us_conntrack) + c->h->datasize; + char buf[size]; + struct us_conntrack *u = (struct us_conntrack *) buf; - u = (struct us_conntrack *) hashtable_test(c->h, ct); + u->ct = ct; + + u = (struct us_conntrack *) hashtable_test(c->h, u); if (u) { int i; void *data = u->data; + struct nf_conntrack *p = u->ct; for (i = 0; i < c->num_features; i++) { c->features[i]->destroy(u, data); data += c->features[i]->size; } - hashtable_del(c->h, ct); + hashtable_del(c->h, u); + free(p); c->del_ok++; return 1; } @@ -240,7 +322,7 @@ return 0; } -int cache_del_entry(struct cache *c, struct nfct_conntrack *ct) +int cache_del_entry(struct cache *c, struct nf_conntrack *ct) { int ret; @@ -255,14 +337,19 @@ { char buf[1024]; int size; - unsigned flags = NFCT_PROTOINFO | NFCT_MARK | NFCT_STATUS; int *fd = data1; struct us_conntrack *u = data2; void *data = u->data; int i; memset(buf, 0, sizeof(buf)); - size = nfct_sprintf_conntrack(buf, &u->ct, flags); + size = nfct_snprintf(buf, + sizeof(buf), + u->ct, + NFCT_T_UNKNOWN, + NFCT_O_DEFAULT, + 0); + for (i = 0; i < u->cache->num_features; i++) { if (u->cache->features[i]->dump) { size += u->cache->features[i]->dump(u, data, buf+size); @@ -289,21 +376,42 @@ { int ret; struct cache *c = data1; - struct nfct_conntrack *ct = data2; - struct nfct_conntrack strip_ct; + struct us_conntrack *u = data2; + struct nf_conntrack *ct; char buf[4096]; struct nlmsghdr *nlh = (struct nlmsghdr *)buf; - nfct_conntrack_strip_nat(ct, &strip_ct); - ret = nfct_build_netlink_message(NFCT_MSG_NEW, - STATE(subsys_sync), - &strip_ct, - buf, - sizeof(buf)); + ct = nfct_clone(u->ct); + if (ct == NULL) + return 0; + + if (nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT)) + nfct_setobjopt(ct, NFCT_SOPT_UNDO_SNAT); + if (nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT)) + nfct_setobjopt(ct, NFCT_SOPT_UNDO_DNAT); + if (nfct_getobjopt(ct, NFCT_GOPT_IS_SPAT)) + nfct_setobjopt(ct, NFCT_SOPT_UNDO_SPAT); + if (nfct_getobjopt(ct, NFCT_GOPT_IS_DPAT)) + nfct_setobjopt(ct, NFCT_SOPT_UNDO_DPAT); + + /* + * Set a reduced timeout for candidate-to-be-committed + * conntracks that live in the external cache + */ + nfct_set_attr_u32(ct, ATTR_TIMEOUT, CONFIG(commit_timeout)); + + ret = nfct_build_query(STATE(subsys_sync), + NFCT_Q_CREATE, + ct, + nlh, + sizeof(buf)); + + free(ct); + if (ret == -1) { /* XXX: Please cleanup this debug crap, default in logfile */ debug("--- failed to build: %s --- \n", strerror(errno)); - goto err; + return 0; } ret = nfnl_query(STATE(sync), nlh); @@ -322,12 +430,6 @@ debug("----- commit -----\n"); } -err: - debug("status: %x\n", strip_ct.status); - dump_tuple(&strip_ct.tuple[NFCT_DIR_ORIGINAL]); - dump_tuple(&strip_ct.tuple[NFCT_DIR_REPLY]); - debug("------------------\n"); - /* keep iterating even if we have found errors */ return 0; } @@ -384,22 +486,17 @@ static int iterate_bulk(void *data1, void *data2) { int ret; - struct nfct_conntrack *ct = data2; + struct us_conntrack *u = data2; char buf[4096]; struct nlmsghdr *nlh = (struct nlmsghdr *)buf; - ret = nfct_build_netlink_message(NFCT_MSG_UPDATE, - STATE(subsys_sync), - ct, - buf, - sizeof(buf)); - if (ret == -1) { - debug("--- failed to build: %s --- \n", strerror(errno)); - debug("status: %x\n", ct->status); - dump_tuple(&ct->tuple[NFCT_DIR_ORIGINAL]); - dump_tuple(&ct->tuple[NFCT_DIR_REPLY]); - debug("------------------\n"); - } + ret = nfct_build_query(STATE(subsys_sync), + NFCT_T_UPDATE, + u->ct, + buf, + sizeof(buf)); + if (ret == -1) + debug_ct(u->ct, "failed to build"); mcast_send_netlink(STATE_SYNC(mcast_client), nlh); Index: src/cache_timer.c =================================================================== --- src/cache_timer.c (revisión: 19) +++ src/cache_timer.c (copia de trabajo) @@ -26,8 +26,8 @@ { struct us_conntrack *u = data; - debug_info(&u->ct, "expired timeout"); - __cache_del_entry(u->cache, &u->ct); + debug_ct(u->ct, "expired timeout"); + __cache_del_entry(u->cache, u->ct); } static void timer_add(struct us_conntrack *u, void *data) Index: src/netlink.c =================================================================== --- src/netlink.c (revisión: 20) +++ src/netlink.c (copia de trabajo) @@ -18,6 +18,7 @@ #include "conntrackd.h" #include +#include #include #include "us-conntrack.h" #include @@ -27,51 +28,19 @@ * sent via network contain the whole conntrack state */ int nl_build_network_message(const int msg_type, struct nfnl_subsys_handle *ssh, - struct nfct_conntrack *ct, + struct nf_conntrack *ct, void *buffer, unsigned int size) { - struct nfnlhdr *req = buffer; - u_int8_t l3num = ct->tuple[NFCT_DIR_ORIGINAL].l3protonum; + u_int8_t l3num = nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO); unsigned type, flags; - - memset(req, 0, size); - switch(msg_type) { - case NFCT_MSG_NEW: - type = IPCTNL_MSG_CT_NEW; - flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL; - break; - case NFCT_MSG_UPDATE: - type = IPCTNL_MSG_CT_NEW; - flags = NLM_F_REQUEST|NLM_F_ACK; - break; - case NFCT_MSG_DESTROY: - type = IPCTNL_MSG_CT_DELETE; - flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST|NLM_F_ACK; - break; - default: - return -1; - } - - nfnl_fill_hdr(ssh, &req->nlh, 0, l3num, 0, type, flags); + memset(buffer, 0, size); - nfct_build_tuple(req, size, &ct->tuple[NFCT_DIR_ORIGINAL], - CTA_TUPLE_ORIG); - nfct_build_tuple(req, size, &ct->tuple[NFCT_DIR_REPLY], - CTA_TUPLE_REPLY); - - nfct_build_status(req, size, ct); - nfct_build_timeout(req, size, ct); - nfct_build_mark(req, size, ct); - nfct_build_protoinfo(req, size, ct); - nfct_build_snat(req, size, ct); - nfct_build_dnat(req, size, ct); - - return req->nlh.nlmsg_len; + return nfct_build_query(ssh, msg_type, ct, buffer, size); } -int nl_parse_network_message(struct nfct_conntrack *ct, +int nl_parse_network_message(struct nf_conntrack *ct, struct nlmsghdr *nlh, unsigned int *type, unsigned int *flags) @@ -84,38 +53,34 @@ * * Yup, this is a hack 8) */ - return nfct_parse_netlink_message(ct, nlh, type, flags); + return nfct_parse_conntrack(NFCT_T_ALL, nlh, ct); } -static int ignore_conntrack(struct nfct_conntrack *ct) +static int ignore_conntrack(struct nf_conntrack *ct) { /* ignore a certain protocol */ - if (CONFIG(ignore_protocol)[ct->tuple[NFCT_DIR_ORIGINAL].protonum] == 1) + if (CONFIG(ignore_protocol)[nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO)]) return 1; /* Accept DNAT'ed traffic: not really coming to the local machine */ - if ((CONFIG(flags) & STRIP_NAT) && nfct_conntrack_is_dnatted(ct)) { - debug_info(ct, "DNAT"); + if ((CONFIG(flags) & STRIP_NAT) && + nfct_getobjopt(ct, NFCT_GOPT_IS_DNAT)) { + debug_ct(ct, "DNAT"); return 0; } /* Accept SNAT'ed traffic: not really coming to the local machine */ - if ((CONFIG(flags) & STRIP_NAT) && nfct_conntrack_is_snatted(ct)) { - debug_info(ct, "SNAT"); + if ((CONFIG(flags) & STRIP_NAT) && + nfct_getobjopt(ct, NFCT_GOPT_IS_SNAT)) { + debug_ct(ct, "SNAT"); return 0; } /* Ignore traffic */ - if (hashtable_test(STATE(ignoreip), - &ct->tuple[NFCT_DIR_ORIGINAL].src.v6)) { - debug_info(ct, "ignore traffic (source)"); + if (hashtable_test(STATE(ignoreip), ct)) { + debug_ct(ct, "ignore traffic"); return 1; } - if (hashtable_test(STATE(ignoreip), - &ct->tuple[NFCT_DIR_ORIGINAL].dst.v6)) { - debug_info(ct, "ignore traffic (destination)"); - return 1; - } return 0; } @@ -124,36 +89,37 @@ struct nfattr *nfa[], void *data) { - struct nfct_conntrack ct; - unsigned int flags; - unsigned int type; + char tmp[1024]; + struct nf_conntrack *ct = (struct nf_conntrack *) tmp; + int type; - if (nfct_parse_netlink_message(&ct, nlh, &type, &flags) < 0) - return 0; + if ((type = nfct_parse_conntrack(NFCT_T_ALL, nlh, ct)) == NFCT_T_ERROR) + return NFCT_CB_STOP; /* * Ignore this conntrack: it talks about a * connection that is not interesting for us. */ - if (ignore_conntrack(&ct)) - return 0; + if (ignore_conntrack(ct)) + return NFCT_CB_STOP; switch(type) { - case NFCT_MSG_NEW: - STATE(mode)->event_new(&ct, nlh, flags); + case NFCT_T_NEW: + STATE(mode)->event_new(ct, nlh); break; - case NFCT_MSG_UPDATE: - STATE(mode)->event_upd(&ct, nlh, flags); + case NFCT_T_UPDATE: + STATE(mode)->event_upd(ct, nlh); break; - case NFCT_MSG_DESTROY: - if (STATE(mode)->event_dst(&ct, nlh, flags)) - update_traffic_stats(&ct); + case NFCT_T_DESTROY: + if (STATE(mode)->event_dst(ct, nlh)) + update_traffic_stats(ct); break; default: dlog(STATE(log), "received unknown msg from ctnetlink\n"); break; } - return 0; + + return NFCT_CB_STOP; } int nl_init_event_handler(void) @@ -212,29 +178,28 @@ struct nfattr *nfa[], void *data) { - struct nfct_conntrack ct; - unsigned int flags; - unsigned int type; + char buf[1024]; + struct nf_conntrack *ct = (struct nf_conntrack *) buf; + int type; - if (nfct_parse_netlink_message(&ct, nlh, &type, &flags) < 0) - return 1; + if ((type = nfct_parse_conntrack(NFCT_T_ALL, nlh, ct)) == NFCT_T_ERROR) + return NFCT_CB_CONTINUE; /* * Ignore this conntrack: it talks about a * connection that is not interesting for us. */ - if (ignore_conntrack(&ct)) - return 1; + if (ignore_conntrack(ct)) + return NFCT_CB_CONTINUE; switch(type) { - case NFCT_MSG_UPDATE: - STATE(mode)->dump(&ct, nlh, flags); + case NFCT_T_UPDATE: + STATE(mode)->dump(ct, nlh); break; default: dlog(STATE(log), "received unknown msg from ctnetlink"); break; } - return 1; } int nl_init_dump_handler(void) Index: src/cache_persistence.c =================================================================== --- src/cache_persistence.c (revisión: 19) +++ src/cache_persistence.c (copia de trabajo) @@ -28,25 +28,25 @@ char buf[8192]; int size; - if (u->ct.status & IPS_DYING) { + if (nfct_get_attr_u32(u->ct, ATTR_STATUS) & IPS_DYING) { - debug_info(&u->ct, "persistence destroy"); + debug_ct(u->ct, "persistence destroy"); - size = nl_build_network_message(NFCT_MSG_DESTROY, + size = nl_build_network_message(NFCT_Q_DESTROY, STATE(subsys_event), - &u->ct, + u->ct, buf, sizeof(buf)); - __cache_del_entry(u->cache, &u->ct); + __cache_del_entry(u->cache, u->ct); mcast_send_netlink(STATE_SYNC(mcast_client), buf); } else { - debug_info(&u->ct, "persistence update"); + debug_ct(u->ct, "persistence update"); a->expires = random() % CONFIG(refresh) + 1; - size = nl_build_network_message(NFCT_MSG_UPDATE, + size = nl_build_network_message(NFCT_Q_UPDATE, STATE(subsys_event), - &u->ct, + u->ct, buf, sizeof(buf)); mcast_send_netlink(STATE_SYNC(mcast_client), buf); Index: src/read_config_yy.y =================================================================== --- src/read_config_yy.y (revisión: 19) +++ src/read_config_yy.y (copia de trabajo) @@ -42,7 +42,7 @@ %token T_LOG T_UDP T_ICMP T_IGMP T_VRRP T_IGNORE_PROTOCOL %token T_LOCK T_STRIP_NAT T_BUFFER_SIZE_MAX_GROWN T_EXPIRE T_TIMEOUT %token T_GENERAL T_SYNC T_STATS T_RELAX_TRANSITIONS T_BUFFER_SIZE T_DELAY -%token T_SYNC_MODE T_LISTEN_TO +%token T_SYNC_MODE T_LISTEN_TO T_FAMILY %token T_IP T_PATH_VAL %token T_NUMBER @@ -358,6 +358,7 @@ | unix_line | netlink_buffer_size | netlink_buffer_size_max_grown + | family ; netlink_buffer_size: T_BUFFER_SIZE T_NUMBER @@ -370,6 +371,14 @@ conf.netlink_buffer_size_max_grown = $2; }; +family : T_FAMILY T_STRING +{ + if (strncmp($2, "IPv6", strlen("IPv6")) == 0) + conf.family = AF_INET6; + else + conf.family = AF_INET; +}; + stats: T_SYNC '{' stats_list '}'; stats_list: @@ -403,6 +412,10 @@ yyparse(); fclose(fp); + /* default to IPv4 */ + if (CONFIG(family) == 0) + CONFIG(family) = AF_INET; + /* set to default is not specified */ if (strcmp(CONFIG(lockfile), "") == 0) strncpy(CONFIG(lockfile), DEFAULT_LOCKFILE, FILENAME_MAXLEN); Index: src/stats-mode.c =================================================================== --- src/stats-mode.c (revisión: 19) +++ src/stats-mode.c (copia de trabajo) @@ -37,7 +37,7 @@ } memset(state.stats, 0, sizeof(struct ct_stats_state)); - STATE_STATS(cache) = cache_create("stats", LIFETIME); + STATE_STATS(cache) = cache_create("stats", LIFETIME, CONFIG(family)); if (!STATE_STATS(cache)) { dlog(STATE(log), "[FAIL] can't allocate memory for the " "external cache"); @@ -80,32 +80,29 @@ } } -static void dump_stats(struct nfct_conntrack *ct, - struct nlmsghdr *nlh, - unsigned int flags) +static void dump_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) { - if (cache_update_force(STATE_STATS(cache), ct, flags)) - debug_info(ct, "resync entry"); + if (cache_update_force(STATE_STATS(cache), ct)) + debug_ct(ct, "resync entry"); } -static void event_new_stats(struct nfct_conntrack *ct, - struct nlmsghdr *nlh, - unsigned int flags) +static void event_new_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) { + debug_ct(ct, "debug event"); if (cache_add_entry(STATE_STATS(cache), ct)) { - debug_info(ct, "cache new"); + debug_ct(ct, "cache new"); } else { dlog(STATE(log), "can't add to cache cache: " "%s\n", strerror(errno)); - debug_info(ct, "can't add"); + debug_ct(ct, "can't add"); } } -static void event_update_stats(struct nfct_conntrack *ct, - struct nlmsghdr *nlh, - unsigned int flags) +static void event_update_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) { - if (!cache_update_entry(STATE_STATS(cache), ct, flags)) { + debug_ct(ct, "update"); + + if (!cache_update_entry(STATE_STATS(cache), ct)) { /* * Perhaps we are losing events. If we are working * in relax mode then add a new entry to the cache. @@ -114,24 +111,22 @@ */ if ((CONFIG(flags) & RELAX_TRANSITIONS) && cache_add_entry(STATE_STATS(cache), ct)) { - debug_info(ct, "forcing cache update"); + debug_ct(ct, "forcing cache update"); } else { - debug_info(ct, "can't update"); + debug_ct(ct, "can't update"); return; } } - debug_info(ct, "update"); + debug_ct(ct, "update"); } -static int event_destroy_stats(struct nfct_conntrack *ct, - struct nlmsghdr *nlh, - unsigned int flags) +static int event_destroy_stats(struct nf_conntrack *ct, struct nlmsghdr *nlh) { if (cache_del_entry(STATE_STATS(cache), ct)) { - debug_info(ct, "cache destroy"); + debug_ct(ct, "cache destroy"); return 1; } else { - debug_info(ct, "can't destroy!"); + debug_ct(ct, "can't destroy!"); return 0; } } Index: src/read_config_lex.l =================================================================== --- src/read_config_lex.l (revisión: 19) +++ src/read_config_lex.l (copia de trabajo) @@ -79,6 +79,7 @@ "SocketBufferSizeMaxGrowth" { return T_BUFFER_SIZE_MAX_GROWN; } "Mode" { return T_SYNC_MODE; } "ListenTo" { return T_LISTEN_TO; } +"Family" { return T_FAMILY; } {integer} { yylval.val = atoi(yytext); return T_NUMBER; } {ip4} { yylval.string = strdup(yytext); return T_IP; } Index: src/traffic_stats.c =================================================================== --- src/traffic_stats.c (revisión: 19) +++ src/traffic_stats.c (copia de trabajo) @@ -25,16 +25,16 @@ #include "us-conntrack.h" #include -void update_traffic_stats(struct nfct_conntrack *ct) +void update_traffic_stats(struct nf_conntrack *ct) { STATE(bytes)[NFCT_DIR_ORIGINAL] += - ct->counters[NFCT_DIR_ORIGINAL].bytes; + nfct_get_attr_u32(ct, ATTR_ORIG_COUNTER_BYTES); STATE(bytes)[NFCT_DIR_REPLY] += - ct->counters[NFCT_DIR_REPLY].bytes; + nfct_get_attr_u32(ct, ATTR_REPL_COUNTER_BYTES); STATE(packets)[NFCT_DIR_ORIGINAL] += - ct->counters[NFCT_DIR_ORIGINAL].packets; + nfct_get_attr_u32(ct, ATTR_ORIG_COUNTER_PACKETS); STATE(packets)[NFCT_DIR_REPLY] += - ct->counters[NFCT_DIR_REPLY].packets; + nfct_get_attr_u32(ct, ATTR_REPL_COUNTER_PACKETS); } void dump_traffic_stats(int fd)