summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sync.h4
-rw-r--r--src/cache.c9
-rw-r--r--src/cache_iterators.c6
-rw-r--r--src/network.c47
-rw-r--r--src/sync-mode.c51
-rw-r--r--src/sync-nack.c71
-rw-r--r--src/sync-notrack.c4
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)
{
}