diff options
author | /C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org </C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org> | 2007-07-09 19:11:53 +0000 |
---|---|---|
committer | /C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org </C=EU/ST=EU/CN=Pablo Neira Ayuso/emailAddress=pablo@netfilter.org> | 2007-07-09 19:11:53 +0000 |
commit | 96084e1a1f2e0a49c961bbddb9fffd2e03bfae3f (patch) | |
tree | c078d88b157faa7c5ce76bc4591205756f09742b /src/network.c | |
parent | 4df0be6fbf6a47905e0edf11c13b49ea0eacee5b (diff) | |
download | conntrack-tools-96084e1a1f2e0a49c961bbddb9fffd2e03bfae3f.tar.gz conntrack-tools-96084e1a1f2e0a49c961bbddb9fffd2e03bfae3f.zip |
- conntrack-tools requires libnetfilter_conntrack >= 0.0.81
- add len field to nethdr
- implement buffered send/recv to batch messages
- stop using netlink format for network messages: use similar TLV-based format
- reduce synchronization messages size up to 60%
- introduce periodic alive messages for sync-nack protocol
- timeslice alarm implementation: remove alarm pthread, remove locking
- simplify debugging functions: use nfct_snprintf instead
- remove major use of libnfnetlink functions: use libnetfilter_conntrack API
- deprecate conntrackd -F, use conntrack -F instead
- major rework of the network infrastructure: much simple, less messy
Diffstat (limited to 'src/network.c')
-rw-r--r-- | src/network.c | 238 |
1 files changed, 90 insertions, 148 deletions
diff --git a/src/network.c b/src/network.c index 159bdf3..d162839 100644 --- a/src/network.c +++ b/src/network.c @@ -18,190 +18,159 @@ #include "conntrackd.h" #include "network.h" +#include "us-conntrack.h" +#include "sync.h" static unsigned int seq_set, cur_seq; -static int send_netmsg(struct mcast_sock *m, void *data, unsigned int len) +static int __do_send(struct mcast_sock *m, void *data, int len) { struct nethdr *net = data; - if (!seq_set) { - seq_set = 1; - cur_seq = time(NULL); - net->flags |= NET_F_HELLO; - } - - net->flags = htons(net->flags); - net->seq = htonl(cur_seq++); - #undef _TEST_DROP #ifdef _TEST_DROP static int drop = 0; - if (++drop > 10) { + if (++drop >= 10) { + printf("drop sq: %u fl:%u len:%u\n", + ntohl(net->seq), ntohs(net->flags), + ntohs(net->len)); drop = 0; - printf("dropping resend (seq=%u)\n", ntohl(net->seq)); return 0; } #endif + debug("send sq: %u fl:%u len:%u\n", + ntohl(net->seq), ntohs(net->flags), + ntohs(net->len)); + return mcast_send(m, net, len); } -int mcast_send_netmsg(struct mcast_sock *m, void *data) +static int __do_prepare(struct mcast_sock *m, void *data, int len) { - struct nlmsghdr *nlh = data + NETHDR_SIZ; - unsigned int len = nlh->nlmsg_len + NETHDR_SIZ; struct nethdr *net = data; - if (nlh_host2network(nlh) == -1) - return -1; + if (!seq_set) { + seq_set = 1; + cur_seq = time(NULL); + net->flags |= NET_F_HELLO; + } + net->len = len; + net->seq = cur_seq++; + HDR_HOST2NETWORK(net); - return send_netmsg(m, data, len); + return len; } -int mcast_resend_netmsg(struct mcast_sock *m, void *data) +static int __prepare_ctl(struct mcast_sock *m, void *data) { - struct nethdr *net = data; - struct nlmsghdr *nlh = data + NETHDR_SIZ; - unsigned int len; + struct nethdr_ack *nack = (struct nethdr_ack *) data; - net->flags = ntohs(net->flags); + return __do_prepare(m, data, NETHDR_ACK_SIZ); +} - if (net->flags & NET_F_NACK || net->flags & NET_F_ACK) - len = NETHDR_ACK_SIZ; - else - len = ntohl(nlh->nlmsg_len) + NETHDR_SIZ; +static int __prepare_data(struct mcast_sock *m, void *data) +{ + struct nethdr *net = (struct nethdr *) data; + struct netpld *pld = NETHDR_DATA(net); - return send_netmsg(m, data, len); + return __do_prepare(m, data, ntohs(pld->len) + NETPLD_SIZ + NETHDR_SIZ); } -int mcast_send_error(struct mcast_sock *m, void *data) +int prepare_send_netmsg(struct mcast_sock *m, void *data) { - struct nethdr *net = data; - unsigned int len = NETHDR_SIZ; + int ret = 0; + struct nethdr *net = (struct nethdr *) data; - if (net->flags & NET_F_NACK || net->flags & NET_F_ACK) { - struct nethdr_ack *nack = (struct nethdr_ack *) net; - nack->from = htonl(nack->from); - nack->to = htonl(nack->to); - len = NETHDR_ACK_SIZ; - } + if (IS_DATA(net)) + ret = __prepare_data(m, data); + else if (IS_CTL(net)) + ret = __prepare_ctl(m, data); - return send_netmsg(m, data, len); + return ret; } -#include "us-conntrack.h" -#include "sync.h" +static int tx_buflen = 0; +/* XXX: use buffer size of interface MTU */ +static char __tx_buf[1460], *tx_buf = __tx_buf; -static int __build_send(struct us_conntrack *u, int type, int query) +/* return 0 if it is not sent, otherwise return 1 */ +int mcast_buffered_send_netmsg(struct mcast_sock *m, void *data, int len) { - char __net[4096]; - struct nethdr *net = (struct nethdr *) __net; + int ret = 0; + struct nethdr *net = data; - if (!state_helper_verdict(type, u->ct)) - return 0; +retry: + if (tx_buflen + len < sizeof(__tx_buf)) { + memcpy(__tx_buf + tx_buflen, net, len); + tx_buflen += len; + } else { + __do_send(m, tx_buf, tx_buflen); + ret = 1; + tx_buflen = 0; + goto retry; + } - int ret = build_network_msg(query, - STATE(subsys_event), - u->ct, - __net, - sizeof(__net)); + return ret; +} - if (ret == -1) - return -1; +int mcast_buffered_pending_netmsg(struct mcast_sock *m) +{ + int ret; + + if (tx_buflen == 0) + return 0; - mcast_send_netmsg(STATE_SYNC(mcast_client), __net); - if (STATE_SYNC(sync)->send) - STATE_SYNC(sync)->send(type, net, u); + ret = __do_send(m, tx_buf, tx_buflen); + tx_buflen = 0; - return 0; + return ret; } -int mcast_build_send_update(struct us_conntrack *u) +int mcast_send_netmsg(struct mcast_sock *m, void *data) { - return __build_send(u, NFCT_T_UPDATE, NFCT_Q_UPDATE); + int ret; + int len = prepare_send_netmsg(m, data); + + ret = mcast_buffered_send_netmsg(m, data, len); + mcast_buffered_pending_netmsg(m); + + return ret; } -int mcast_build_send_destroy(struct us_conntrack *u) +void build_netmsg(struct nf_conntrack *ct, int query, struct nethdr *net) { - return __build_send(u, NFCT_T_DESTROY, NFCT_Q_DESTROY); + struct netpld *pld = NETHDR_DATA(net); + + build_netpld(ct, pld, query); } -int mcast_recv_netmsg(struct mcast_sock *m, void *data, int len) +int handle_netmsg(struct nethdr *net) { int ret; - struct nethdr *net = data; - struct nlmsghdr *nlh = data + NETHDR_SIZ; - struct nfgenmsg *nfhdr; - - ret = mcast_recv(m, net, len); - if (ret <= 0) - return ret; + struct netpld *pld = NETHDR_DATA(net); /* message too small: no room for the header */ - if (ret < NETHDR_SIZ) + if (ntohs(net->len) < NETHDR_ACK_SIZ) return -1; - if (ntohs(net->flags) & NET_F_HELLO) - STATE_SYNC(last_seq_recv) = ntohl(net->seq) - 1; + HDR_NETWORK2HOST(net); - if (ntohs(net->flags) & NET_F_NACK || ntohs(net->flags) & NET_F_ACK) { - struct nethdr_ack *nack = (struct nethdr_ack *) net; + if (IS_HELLO(net)) + STATE_SYNC(last_seq_recv) = net->seq - 1; - /* message too small: no room for the header */ - if (ret < NETHDR_ACK_SIZ) - 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 (ntohs(net->flags) & NET_F_RESYNC) { - /* host byte order conversion */ - net->flags = ntohs(net->flags); - net->seq = ntohl(net->seq); - - return ret; - } + if (IS_CTL(net)) + return 0; /* information received is too small */ - if (ret < NLMSG_SPACE(sizeof(struct nfgenmsg))) - return -1; - - /* information received and message length does not match */ - if (ret != ntohl(nlh->nlmsg_len) + NETHDR_SIZ) - return -1; - - /* this message does not come from ctnetlink */ - if (NFNL_SUBSYS_ID(ntohs(nlh->nlmsg_type)) != NFNL_SUBSYS_CTNETLINK) + if (net->len < sizeof(struct netpld)) return -1; - nfhdr = NLMSG_DATA(nlh); - - /* only AF_INET and AF_INET6 are supported */ - if (nfhdr->nfgen_family != AF_INET && - nfhdr->nfgen_family != AF_INET6) - return -1; - - /* only process message coming from nfnetlink v0 */ - if (nfhdr->version != NFNETLINK_V0) - return -1; - - /* host byte order conversion */ - net->flags = ntohs(net->flags); - net->seq = ntohl(net->seq); - - if (nlh_network2host(nlh) == -1) + /* size mismatch! */ + if (net->len < ntohs(pld->len) + NETHDR_SIZ) return -1; - return ret; + return 0; } int mcast_track_seq(u_int32_t seq, u_int32_t *exp_seq) @@ -238,30 +207,3 @@ out: return ret; } - -int build_network_msg(const int msg_type, - struct nfnl_subsys_handle *ssh, - struct nf_conntrack *ct, - void *buffer, - unsigned int size) -{ - memset(buffer, 0, size); - buffer += NETHDR_SIZ; - size -= NETHDR_SIZ; - return nfct_build_query(ssh, msg_type, ct, buffer, size); -} - -unsigned int parse_network_msg(struct nf_conntrack *ct, - const struct nlmsghdr *nlh) -{ - /* - * The parsing of netlink messages going through network is - * similar to the one that is done for messages coming from - * kernel, therefore do not replicate more code and use the - * function provided in the libraries. - * - * Yup, this is a hack 8) - */ - return nfct_parse_conntrack(NFCT_T_ALL, nlh, ct); -} - |