From 2932c6b8e6952ae84b221b854b43810c61e5c8fa Mon Sep 17 00:00:00 2001 From: "/C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org" Date: Fri, 18 May 2007 19:33:40 +0000 Subject: - remove dead code sync-mode.c - flush nack queue in the conntrackd -f path - do not increase add_fail counter for EEXIST errors - cleanup sync-nack code - improve mcast_recv_netmsg: sanity check before checksumming! --- include/sync.h | 4 ++- src/cache.c | 9 ++++--- src/cache_iterators.c | 6 ++++- src/network.c | 47 ++++++++++++++++++++++++---------- src/sync-mode.c | 51 ++++++++++-------------------------- src/sync-nack.c | 71 ++++++++++++++++++++++++--------------------------- src/sync-notrack.c | 4 ++- 7 files changed, 96 insertions(+), 96 deletions(-) diff --git a/include/sync.h b/include/sync.h index 7756c87..d8f1bca 100644 --- a/include/sync.h +++ b/include/sync.h @@ -14,7 +14,9 @@ struct sync_mode { void (*kill)(void); int (*local)(int fd, int type, void *data); int (*pre_recv)(const struct nlnetwork *net); - void (*post_send)(const struct nlnetwork *net, struct us_conntrack *u); + void (*post_send)(int type, + const struct nlnetwork *net, + struct us_conntrack *u); }; extern struct sync_mode notrack; diff --git a/src/cache.c b/src/cache.c index 6f7442b..32caee5 100644 --- a/src/cache.c +++ b/src/cache.c @@ -228,7 +228,7 @@ static struct us_conntrack *__add(struct cache *c, struct nf_conntrack *ct) data += c->features[i]->size; } - if (c->extra) + if (c->extra && c->extra->add) c->extra->add(u, ((void *) u) + c->extra_offset); return u; @@ -247,7 +247,8 @@ struct us_conntrack *__cache_add(struct cache *c, struct nf_conntrack *ct) c->add_ok++; return u; } - c->add_fail++; + if (errno != EEXIST) + c->add_fail++; return NULL; } @@ -281,7 +282,7 @@ static struct us_conntrack *__update(struct cache *c, struct nf_conntrack *ct) data += c->features[i]->size; } - if (c->extra) + if (c->extra && c->extra->update) c->extra->update(u, ((void *) u) + c->extra_offset); if (nfct_attr_is_set(ct, ATTR_STATUS)) @@ -380,7 +381,7 @@ static int __del(struct cache *c, struct nf_conntrack *ct) data += c->features[i]->size; } - if (c->extra) + if (c->extra && c->extra->destroy) c->extra->destroy(u, ((void *) u) + c->extra_offset); hashtable_del(c->h, u); diff --git a/src/cache_iterators.c b/src/cache_iterators.c index 5d5d22b..e1f3798 100644 --- a/src/cache_iterators.c +++ b/src/cache_iterators.c @@ -182,6 +182,10 @@ static int do_flush(void *data1, void *data2) c->features[i]->destroy(u, data); data += c->features[i]->size; } + + if (c->extra && c->extra->destroy) + c->extra->destroy(u, ((void *) u) + c->extra_offset); + free(u->ct); return 0; @@ -215,7 +219,7 @@ static int do_bulk(void *data1, void *data2) debug_ct(u->ct, "failed to build"); mcast_send_netmsg(STATE_SYNC(mcast_client), net); - STATE_SYNC(mcast_sync)->post_send(net, u); + STATE_SYNC(mcast_sync)->post_send(NFCT_T_UPDATE, net, u); /* keep iterating even if we have found errors */ return 0; diff --git a/src/network.c b/src/network.c index b9be318..51e89c7 100644 --- a/src/network.c +++ b/src/network.c @@ -70,7 +70,7 @@ int mcast_resend_netmsg(struct mcast_sock *m, void *data) { struct nlnetwork *net = data; struct nlmsghdr *nlh = data + sizeof(struct nlnetwork); - unsigned int len = htonl(nlh->nlmsg_len) + sizeof(struct nlnetwork); + unsigned int len; net->flags = ntohs(net->flags); @@ -80,10 +80,10 @@ int mcast_resend_netmsg(struct mcast_sock *m, void *data) net->flags |= NET_HELLO; } - if (net->flags & NET_NACK || net->flags & NET_ACK) { - struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; + if (net->flags & NET_NACK || net->flags & NET_ACK) len = sizeof(struct nlnetwork_ack); - } + else + len = sizeof(struct nlnetwork) + ntohl(nlh->nlmsg_len); net->flags = htons(net->flags); net->seq = htonl(cur_seq++); @@ -147,32 +147,44 @@ int mcast_recv_netmsg(struct mcast_sock *m, void *data, int len) if (ret <= 0) return ret; + /* message too small: no room for the header */ if (ret < sizeof(struct nlnetwork)) return -1; - if (!valid_checksum(data, ret)) - return -1; - - net->flags = ntohs(net->flags); - net->seq = ntohl(net->seq); - - if (net->flags & NET_HELLO) - STATE_SYNC(last_seq_recv) = net->seq-1; + if (ntohs(net->flags) & NET_HELLO) + STATE_SYNC(last_seq_recv) = ntohl(net->seq) - 1; - if (net->flags & NET_NACK || net->flags & NET_ACK) { + if (ntohs(net->flags) & NET_NACK || ntohs(net->flags) & NET_ACK) { struct nlnetwork_ack *nack = (struct nlnetwork_ack *) net; + /* message too small: no room for the header */ if (ret < sizeof(struct nlnetwork_ack)) return -1; + if (!valid_checksum(data, ret)) + return -1; + + /* host byte order conversion */ + net->flags = ntohs(net->flags); + net->seq = ntohl(net->seq); + + /* acknowledgement conversion */ nack->from = ntohl(nack->from); nack->to = ntohl(nack->to); return ret; } - if (net->flags & NET_RESYNC) + if (ntohs(net->flags) & NET_RESYNC) { + if (!valid_checksum(data, ret)) + return -1; + + /* host byte order conversion */ + net->flags = ntohs(net->flags); + net->seq = ntohl(net->seq); + return ret; + } /* information received is too small */ if (ret < NLMSG_SPACE(sizeof(struct nfgenmsg))) @@ -197,6 +209,13 @@ int mcast_recv_netmsg(struct mcast_sock *m, void *data, int len) if (nfhdr->version != NFNETLINK_V0) return -1; + if (!valid_checksum(data, ret)) + return -1; + + /* host byte order conversion */ + net->flags = ntohs(net->flags); + net->seq = ntohl(net->seq); + if (nlh_network2host(nlh) == -1) return -1; diff --git a/src/sync-mode.c b/src/sync-mode.c index b32bef7..0a195d7 100644 --- a/src/sync-mode.c +++ b/src/sync-mode.c @@ -282,18 +282,15 @@ static void mcast_send_sync(struct nlmsghdr *nlh, { char buf[4096]; struct nlnetwork *net = (struct nlnetwork *) buf; - int mangled = 0; memset(buf, 0, sizeof(buf)); if (!state_helper_verdict(type, ct)) return; - if (!mangled) - memcpy(buf + sizeof(struct nlnetwork), nlh, nlh->nlmsg_len); - + memcpy(buf + sizeof(struct nlnetwork), nlh, nlh->nlmsg_len); mcast_send_netmsg(STATE_SYNC(mcast_client), net); - STATE_SYNC(mcast_sync)->post_send(net, u); + STATE_SYNC(mcast_sync)->post_send(type, net, u); } static void overrun_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) @@ -333,7 +330,8 @@ retry: } else { if (errno == EEXIST) { char buf[4096]; - struct nlmsghdr *nlh = (struct nlmsghdr *) buf; + unsigned int size = sizeof(struct nlnetwork); + struct nlmsghdr *nlh = (struct nlmsghdr *) (buf + size); int ret = build_network_msg(NFCT_Q_DESTROY, STATE(subsys_event), @@ -344,9 +342,10 @@ retry: return; cache_del(STATE_SYNC(internal), ct); - mcast_send_sync(nlh, NULL, ct, NFCT_T_NEW); + mcast_send_sync(nlh, NULL, ct, NFCT_T_DESTROY); goto retry; } + dlog(STATE(log), "can't add to internal cache: " "%s\n", strerror(errno)); debug_ct(ct, "can't add"); @@ -360,19 +359,8 @@ static void event_update_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) nfct_attr_unset(ct, ATTR_TIMEOUT); if ((u = cache_update(STATE_SYNC(internal), ct)) == NULL) { - /* - * Perhaps we are losing events. If we are working - * in relax mode then add a new entry to the cache. - * - * FIXME: relax transitions not implemented yet - */ - if ((CONFIG(flags) & RELAX_TRANSITIONS) - && (u = cache_add(STATE_SYNC(internal), ct))) { - debug_ct(u->ct, "forcing internal update"); - } else { - debug_ct(ct, "can't update"); - return; - } + debug_ct(ct, "can't update"); + return; } debug_ct(u->ct, "internal update"); mcast_send_sync(nlh, u, ct, NFCT_T_UPDATE); @@ -382,24 +370,11 @@ static int event_destroy_sync(struct nf_conntrack *ct, struct nlmsghdr *nlh) { nfct_attr_unset(ct, ATTR_TIMEOUT); - if (CONFIG(flags) & DELAY_DESTROY_MSG) { - - nfct_set_attr_u32(ct, ATTR_STATUS, IPS_DYING); - - if (cache_update(STATE_SYNC(internal), ct)) { - debug_ct(ct, "delay internal destroy"); - return 1; - } else { - debug_ct(ct, "can't delay destroy!"); - return 0; - } - } else { - if (cache_del(STATE_SYNC(internal), ct)) { - mcast_send_sync(nlh, NULL, ct, NFCT_T_DESTROY); - debug_ct(ct, "internal destroy"); - } else - debug_ct(ct, "can't destroy"); - } + if (cache_del(STATE_SYNC(internal), ct)) { + mcast_send_sync(nlh, NULL, ct, NFCT_T_DESTROY); + debug_ct(ct, "internal destroy"); + } else + debug_ct(ct, "can't destroy"); } struct ct_mode sync_mode = { diff --git a/src/sync-nack.c b/src/sync-nack.c index 288dba4..73f6dc2 100644 --- a/src/sync-nack.c +++ b/src/sync-nack.c @@ -43,37 +43,24 @@ struct cache_nack { static void cache_nack_add(struct us_conntrack *u, void *data) { struct cache_nack *cn = data; - INIT_LIST_HEAD(&cn->head); - list_add(&cn->head, &queue); } -static void cache_nack_update(struct us_conntrack *u, void *data) +static void cache_nack_del(struct us_conntrack *u, void *data) { struct cache_nack *cn = data; - if (cn->head.next != LIST_POISON1 && - cn->head.prev != LIST_POISON2) - list_del(&cn->head); + if (cn->head.next == &cn->head && + cn->head.prev == &cn->head) + return; - INIT_LIST_HEAD(&cn->head); - list_add(&cn->head, &queue); -} - -static void cache_nack_destroy(struct us_conntrack *u, void *data) -{ - struct cache_nack *cn = data; - - if (cn->head.next != LIST_POISON1 && - cn->head.prev != LIST_POISON2) - list_del(&cn->head); + list_del(&cn->head); } static struct cache_extra cache_nack_extra = { .size = sizeof(struct cache_nack), .add = cache_nack_add, - .update = cache_nack_update, - .destroy = cache_nack_destroy + .destroy = cache_nack_del }; static int nack_init() @@ -200,7 +187,9 @@ static void queue_resend(struct cache *c, unsigned int from, unsigned int to) } mcast_send_netmsg(STATE_SYNC(mcast_client), buf); - STATE_SYNC(mcast_sync)->post_send(net, u); + STATE_SYNC(mcast_sync)->post_send(NFCT_T_UPDATE, + net, + u); dp("(newseq=%u)\n", *seq); } } @@ -224,6 +213,7 @@ static void queue_empty(struct cache *c, unsigned int from, unsigned int to) debug_ct(u->ct, "ack received: empty queue"); dp("queue: deleting from queue (seq=%u)\n", cn->seq); list_del(&cn->head); + INIT_LIST_HEAD(&cn->head); } } unlock(); @@ -272,28 +262,35 @@ static int nack_pre_recv(const struct nlnetwork *net) return 0; } -static void nack_post_send(const struct nlnetwork *net, struct us_conntrack *u) +static void nack_post_send(int type, + const struct nlnetwork *net, + struct us_conntrack *u) { - unsigned int size = sizeof(struct nlnetwork); - struct nlmsghdr *nlh = (struct nlmsghdr *) ((void *) net + size); - - if (NFNL_MSG_TYPE(ntohs(nlh->nlmsg_type)) == IPCTNL_MSG_CT_DELETE) { - buffer_add(STATE_SYNC(buffer), net, - ntohl(nlh->nlmsg_len) + size); - } else if (u != NULL) { - unsigned int *seq; - struct list_head *n; - struct cache_nack *cn; - - cn = (struct cache_nack *) + unsigned int size = sizeof(struct nlnetwork); + struct nlmsghdr *nlh = (struct nlmsghdr *) ((void *) net + size); + struct cache_nack *cn; + + size += ntohl(nlh->nlmsg_len); + + switch(type) { + case NFCT_T_NEW: + case NFCT_T_UPDATE: + cn = (struct cache_nack *) cache_get_extra(STATE_SYNC(internal), u); - cn->seq = ntohl(net->seq); - if (cn->head.next != LIST_POISON1 && - cn->head.prev != LIST_POISON2) - list_del(&cn->head); + if (cn->head.next == &cn->head && + cn->head.prev == &cn->head) + goto insert; + + list_del(&cn->head); INIT_LIST_HEAD(&cn->head); +insert: + cn->seq = ntohl(net->seq); list_add(&cn->head, &queue); + break; + case NFCT_T_DESTROY: + buffer_add(STATE_SYNC(buffer), net, size); + break; } } diff --git a/src/sync-notrack.c b/src/sync-notrack.c index 2b5ae38..cc56436 100644 --- a/src/sync-notrack.c +++ b/src/sync-notrack.c @@ -114,7 +114,9 @@ static int notrack_pre_recv(const struct nlnetwork *net) return 0; } -static void notrack_post_send(const struct nlnetwork *n, struct us_conntrack *u) +static void notrack_post_send(int type, + const struct nlnetwork *n, + struct us_conntrack *u) { } -- cgit v1.2.3