diff options
author | Gaurav Sinha <gaurav.sinha@vyatta.com> | 2012-01-12 14:45:24 -0800 |
---|---|---|
committer | Gaurav Sinha <gaurav.sinha@vyatta.com> | 2012-01-12 14:45:24 -0800 |
commit | ca37a710d526d17490ebdc3af760bfddd316426d (patch) | |
tree | caeb883cf2302d30e010909bc543b09e191472cb /src/netlink.c | |
parent | c4414d9a8b31bedfb7471cd2365aaf5ea5cf55d5 (diff) | |
parent | 414fedd879fdc3cd0a910acd2fd9262251a6bfe7 (diff) | |
download | conntrack-tools-ca37a710d526d17490ebdc3af760bfddd316426d.tar.gz conntrack-tools-ca37a710d526d17490ebdc3af760bfddd316426d.zip |
Updating upstream with merged content from netfilter conntrack-tools version 1.0.1
Diffstat (limited to 'src/netlink.c')
-rw-r--r-- | src/netlink.c | 167 |
1 files changed, 119 insertions, 48 deletions
diff --git a/src/netlink.c b/src/netlink.c index a43f782..fe979e3 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -1,5 +1,6 @@ /* - * (C) 2006 by Pablo Neira Ayuso <pablo@netfilter.org> + * (C) 2006-2011 by Pablo Neira Ayuso <pablo@netfilter.org> + * (C) 2011 by Vyatta Inc. <http://www.vyatta.com> * * 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 @@ -32,10 +33,23 @@ struct nfct_handle *nl_init_event_handler(void) { struct nfct_handle *h; - h = nfct_open(CONNTRACK, NFCT_ALL_CT_GROUPS); + h = nfct_open(CONFIG(netlink).subsys_id, CONFIG(netlink).groups); if (h == NULL) return NULL; + if (CONFIG(netlink).events_reliable) { + int on = 1; + + setsockopt(nfct_fd(h), SOL_NETLINK, + NETLINK_BROADCAST_SEND_ERROR, &on, sizeof(int)); + + setsockopt(nfct_fd(h), SOL_NETLINK, + NETLINK_NO_ENOBUFS, &on, sizeof(int)); + + dlog(LOG_NOTICE, "reliable ctnetlink event delivery " + "is ENABLED."); + } + if (STATE(filter)) { if (CONFIG(filter_from_kernelspace)) { if (nfct_filter_attach(nfct_fd(h), @@ -53,10 +67,18 @@ struct nfct_handle *nl_init_event_handler(void) fcntl(nfct_fd(h), F_SETFL, O_NONBLOCK); /* set up socket buffer size */ - if (CONFIG(netlink_buffer_size)) { - CONFIG(netlink_buffer_size) = - nfnl_rcvbufsiz(nfct_nfnlh(h), CONFIG(netlink_buffer_size)); + if (CONFIG(netlink_buffer_size) && + CONFIG(netlink_buffer_size) <= + CONFIG(netlink_buffer_size_max_grown)) { + /* we divide netlink_buffer_size by 2 here since value passed + to kernel gets doubled in SO_RCVBUF; see net/core/sock.c */ + CONFIG(netlink_buffer_size) = + nfnl_rcvbufsiz(nfct_nfnlh(h), CONFIG(netlink_buffer_size)/2); } else { + dlog(LOG_NOTICE, "NetlinkBufferSize is either not set or " + "is greater than NetlinkBufferSizeMaxGrowth. " + "Using current system buffer size"); + socklen_t socklen = sizeof(unsigned int); unsigned int read_size; @@ -70,23 +92,6 @@ struct nfct_handle *nl_init_event_handler(void) dlog(LOG_NOTICE, "netlink event socket buffer size has been set " "to %u bytes", CONFIG(netlink_buffer_size)); - /* ensure that maximum grown size is >= than maximum size */ - if (CONFIG(netlink_buffer_size_max_grown) < CONFIG(netlink_buffer_size)) - CONFIG(netlink_buffer_size_max_grown) = - CONFIG(netlink_buffer_size); - - if (CONFIG(netlink).events_reliable) { - int on = 1; - - setsockopt(nfct_fd(h), SOL_NETLINK, - NETLINK_BROADCAST_SEND_ERROR, &on, sizeof(int)); - - setsockopt(nfct_fd(h), SOL_NETLINK, - NETLINK_NO_ENOBUFS, &on, sizeof(int)); - - dlog(LOG_NOTICE, "reliable ctnetlink event delivery " - "is ENABLED."); - } return h; } @@ -110,31 +115,34 @@ static int warned = 0; void nl_resize_socket_buffer(struct nfct_handle *h) { - /* sock_setsockopt in net/core/sock.c doubles the size of the buffer */ unsigned int s = CONFIG(netlink_buffer_size); /* already warned that we have reached the maximum buffer size */ if (warned) return; - if (s > CONFIG(netlink_buffer_size_max_grown)) { + /* since sock_setsockopt in net/core/sock.c doubles the size of socket + buffer passed to it using nfnl_rcvbufsiz, only call nfnl_rcvbufsiz + if new value is not greater than netlink_buffer_size_max_grown */ + if (s*2 > CONFIG(netlink_buffer_size_max_grown)) { dlog(LOG_WARNING, - "maximum netlink socket buffer " - "size has been reached. We are likely to " + "netlink event socket buffer size cannot " + "be doubled further since it will exceed " + "NetlinkBufferSizeMaxGrowth. We are likely to " "be losing events, this may lead to " "unsynchronized replicas. Please, consider " "increasing netlink socket buffer size via " - "SocketBufferSize and " - "SocketBufferSizeMaxGrowth clauses in " + "NetlinkBufferSize and " + "NetlinkBufferSizeMaxGrowth clauses in " "conntrackd.conf"); - s = CONFIG(netlink_buffer_size_max_grown); warned = 1; + return; } CONFIG(netlink_buffer_size) = nfnl_rcvbufsiz(nfct_nfnlh(h), s); /* notify the sysadmin */ - dlog(LOG_NOTICE, "netlink socket buffer size has been increased " + dlog(LOG_NOTICE, "netlink event socket buffer size has been doubled " "to %u bytes", CONFIG(netlink_buffer_size)); } @@ -157,20 +165,21 @@ int nl_send_resync(struct nfct_handle *h) /* if the handle has no callback, check for existence, otherwise, update */ int nl_get_conntrack(struct nfct_handle *h, const struct nf_conntrack *ct) { - int ret; - char __tmp[nfct_maxsize()]; - struct nf_conntrack *tmp = (struct nf_conntrack *) (void *)__tmp; + int ret = 1; + struct nf_conntrack *tmp; - memset(__tmp, 0, sizeof(__tmp)); + tmp = nfct_new(); + if (tmp == NULL) + return -1; /* use the original tuple to check if it is there */ nfct_copy(tmp, ct, NFCT_CP_ORIG); - ret = nfct_query(h, NFCT_Q_GET, tmp); - if (ret == -1) - return errno == ENOENT ? 0 : -1; + if (nfct_query(h, NFCT_Q_GET, tmp) == -1) + ret = (errno == ENOENT) ? 0 : -1; - return 1; + nfct_destroy(tmp); + return ret; } int nl_create_conntrack(struct nfct_handle *h, @@ -196,12 +205,14 @@ int nl_create_conntrack(struct nfct_handle *h, nfct_setobjopt(ct, NFCT_SOPT_SETUP_REPLY); - /* - * TCP flags to overpass window tracking for recovered connections - */ + /* disable TCP window tracking for recovered connections if required */ if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) { - uint8_t flags = IP_CT_TCP_FLAG_BE_LIBERAL | - IP_CT_TCP_FLAG_SACK_PERM; + uint8_t flags = IP_CT_TCP_FLAG_SACK_PERM; + + if (!CONFIG(sync).tcp_window_tracking) + flags |= IP_CT_TCP_FLAG_BE_LIBERAL; + else + flags |= IP_CT_TCP_FLAG_WINDOW_SCALE; /* FIXME: workaround, we should send TCP flags in updates */ if (nfct_get_attr_u8(ct, ATTR_TCP_STATE) >= @@ -261,12 +272,14 @@ int nl_update_conntrack(struct nfct_handle *h, nfct_attr_unset(ct, ATTR_MASTER_PORT_DST); } - /* - * TCP flags to overpass window tracking for recovered connections - */ + /* disable TCP window tracking for recovered connections if required */ if (nfct_attr_is_set(ct, ATTR_TCP_STATE)) { - uint8_t flags = IP_CT_TCP_FLAG_BE_LIBERAL | - IP_CT_TCP_FLAG_SACK_PERM; + uint8_t flags = IP_CT_TCP_FLAG_SACK_PERM; + + if (!CONFIG(sync).tcp_window_tracking) + flags |= IP_CT_TCP_FLAG_BE_LIBERAL; + else + flags |= IP_CT_TCP_FLAG_WINDOW_SCALE; /* FIXME: workaround, we should send TCP flags in updates */ if (nfct_get_attr_u8(ct, ATTR_TCP_STATE) >= @@ -289,3 +302,61 @@ int nl_destroy_conntrack(struct nfct_handle *h, const struct nf_conntrack *ct) { return nfct_query(h, NFCT_Q_DESTROY, ct); } + +int nl_create_expect(struct nfct_handle *h, const struct nf_expect *orig, + int timeout) +{ + int ret; + struct nf_expect *exp; + + exp = nfexp_clone(orig); + if (exp == NULL) + return -1; + + if (timeout > 0) + nfexp_set_attr_u32(exp, ATTR_EXP_TIMEOUT, timeout); + + ret = nfexp_query(h, NFCT_Q_CREATE, exp); + nfexp_destroy(exp); + + return ret; +} + +int nl_destroy_expect(struct nfct_handle *h, const struct nf_expect *exp) +{ + return nfexp_query(h, NFCT_Q_DESTROY, exp); +} + +/* if the handle has no callback, check for existence, otherwise, update */ +int nl_get_expect(struct nfct_handle *h, const struct nf_expect *exp) +{ + int ret = 1; + struct nf_expect *tmp; + + /* XXX: we only need the expectation, not the mask and the master. */ + tmp = nfexp_clone(exp); + if (tmp == NULL) + return -1; + + if (nfexp_query(h, NFCT_Q_GET, tmp) == -1) + ret = (errno == ENOENT) ? 0 : -1; + + nfexp_destroy(tmp); + return ret; +} + +int nl_dump_expect_table(struct nfct_handle *h) +{ + return nfexp_query(h, NFCT_Q_DUMP, &CONFIG(family)); +} + +int nl_flush_expect_table(struct nfct_handle *h) +{ + return nfexp_query(h, NFCT_Q_FLUSH, &CONFIG(family)); +} + +int nl_send_expect_resync(struct nfct_handle *h) +{ + int family = CONFIG(family); + return nfexp_send(h, NFCT_Q_DUMP, &family); +} |