From: kaber@trash.net
To: davem@davemloft.net
Cc: netfilter-devel@vger.kernel.org, netdev@vger.kernel.org
Subject: [PATCH 26/72] IPVS: sip persistence engine
Date: Thu, 21 Oct 2010 17:19:13 +0200 [thread overview]
Message-ID: <1287674399-31455-27-git-send-email-kaber@trash.net> (raw)
In-Reply-To: <1287674399-31455-1-git-send-email-kaber@trash.net>
From: Simon Horman <horms@verge.net.au>
Add the SIP callid as a key for persistence.
This allows multiple connections from the same IP address to be
differentiated on the basis of the callid.
When used in conjunction with the persistence mask, it allows connections
from different IP addresses to be aggregated on the basis of the callid.
It is envisaged that a persistence mask of 0.0.0.0 will be a useful
setting. That is, ignore the source IP address when checking for
persistence.
It is envisaged that this option will be used in conjunction with
one-packet scheduling.
This only works with UDP and cannot be made to work with TCP
within the current framework.
Signed-off-by: Simon Horman <horms@verge.net.au>
Acked-by: Julian Anastasov <ja@ssi.bg>
---
net/netfilter/ipvs/Kconfig | 7 ++
net/netfilter/ipvs/Makefile | 3 +
net/netfilter/ipvs/ip_vs_pe_sip.c | 167 +++++++++++++++++++++++++++++++++++++
3 files changed, 177 insertions(+), 0 deletions(-)
create mode 100644 net/netfilter/ipvs/ip_vs_pe_sip.c
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig
index af3c9f4..a22dac2 100644
--- a/net/netfilter/ipvs/Kconfig
+++ b/net/netfilter/ipvs/Kconfig
@@ -256,4 +256,11 @@ config IP_VS_NFCT
connection state to be exported to the Netfilter framework
for filtering purposes.
+config IP_VS_PE_SIP
+ tristate "SIP persistence engine"
+ depends on IP_VS_PROTO_UDP
+ depends on NF_CONNTRACK_SIP
+ ---help---
+ Allow persistence based on the SIP Call-ID
+
endif # IP_VS
diff --git a/net/netfilter/ipvs/Makefile b/net/netfilter/ipvs/Makefile
index 4a87bf3..34ee602 100644
--- a/net/netfilter/ipvs/Makefile
+++ b/net/netfilter/ipvs/Makefile
@@ -35,3 +35,6 @@ obj-$(CONFIG_IP_VS_NQ) += ip_vs_nq.o
# IPVS application helpers
obj-$(CONFIG_IP_VS_FTP) += ip_vs_ftp.o
+
+# IPVS connection template retrievers
+obj-$(CONFIG_IP_VS_PE_SIP) += ip_vs_pe_sip.o
diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c
new file mode 100644
index 0000000..a0539f1
--- /dev/null
+++ b/net/netfilter/ipvs/ip_vs_pe_sip.c
@@ -0,0 +1,167 @@
+#define KMSG_COMPONENT "IPVS"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <net/ip_vs.h>
+#include <net/netfilter/nf_conntrack.h>
+#include <linux/netfilter/nf_conntrack_sip.h>
+
+static const char *ip_vs_dbg_callid(char *buf, size_t buf_len,
+ const char *callid, size_t callid_len,
+ int *idx)
+{
+ size_t len = min(min(callid_len, (size_t)64), buf_len - *idx - 1);
+ memcpy(buf + *idx, callid, len);
+ buf[*idx+len] = '\0';
+ *idx += len + 1;
+ return buf + *idx - len;
+}
+
+#define IP_VS_DEBUG_CALLID(callid, len) \
+ ip_vs_dbg_callid(ip_vs_dbg_buf, sizeof(ip_vs_dbg_buf), \
+ callid, len, &ip_vs_dbg_idx)
+
+static int get_callid(const char *dptr, unsigned int dataoff,
+ unsigned int datalen,
+ unsigned int *matchoff, unsigned int *matchlen)
+{
+ /* Find callid */
+ while (1) {
+ int ret = ct_sip_get_header(NULL, dptr, dataoff, datalen,
+ SIP_HDR_CALL_ID, matchoff,
+ matchlen);
+ if (ret > 0)
+ break;
+ if (!ret)
+ return 0;
+ dataoff += *matchoff;
+ }
+
+ /* Empty callid is useless */
+ if (!*matchlen)
+ return -EINVAL;
+
+ /* Too large is useless */
+ if (*matchlen > IP_VS_PEDATA_MAXLEN)
+ return -EINVAL;
+
+ /* SIP headers are always followed by a line terminator */
+ if (*matchoff + *matchlen == datalen)
+ return -EINVAL;
+
+ /* RFC 2543 allows lines to be terminated with CR, LF or CRLF,
+ * RFC 3261 allows only CRLF, we support both. */
+ if (*(dptr + *matchoff + *matchlen) != '\r' &&
+ *(dptr + *matchoff + *matchlen) != '\n')
+ return -EINVAL;
+
+ IP_VS_DBG_BUF(9, "SIP callid %s (%d bytes)\n",
+ IP_VS_DEBUG_CALLID(dptr + *matchoff, *matchlen),
+ *matchlen);
+ return 0;
+}
+
+static int
+ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
+{
+ struct ip_vs_iphdr iph;
+ unsigned int dataoff, datalen, matchoff, matchlen;
+ const char *dptr;
+
+ ip_vs_fill_iphdr(p->af, skb_network_header(skb), &iph);
+
+ /* Only useful with UDP */
+ if (iph.protocol != IPPROTO_UDP)
+ return -EINVAL;
+
+ /* No Data ? */
+ dataoff = iph.len + sizeof(struct udphdr);
+ if (dataoff >= skb->len)
+ return -EINVAL;
+
+ dptr = skb->data + dataoff;
+ datalen = skb->len - dataoff;
+
+ if (get_callid(dptr, dataoff, datalen, &matchoff, &matchlen))
+ return -EINVAL;
+
+ p->pe_data = kmalloc(matchlen, GFP_ATOMIC);
+ if (!p->pe_data)
+ return -ENOMEM;
+
+ /* N.B: pe_data is only set on success,
+ * this allows fallback to the default persistence logic on failure
+ */
+ memcpy(p->pe_data, dptr + matchoff, matchlen);
+ p->pe_data_len = matchlen;
+
+ return 0;
+}
+
+static bool ip_vs_sip_ct_match(const struct ip_vs_conn_param *p,
+ struct ip_vs_conn *ct)
+
+{
+ bool ret = 0;
+
+ if (ct->af == p->af &&
+ ip_vs_addr_equal(p->af, p->caddr, &ct->caddr) &&
+ /* protocol should only be IPPROTO_IP if
+ * d_addr is a fwmark */
+ ip_vs_addr_equal(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
+ p->vaddr, &ct->vaddr) &&
+ ct->vport == p->vport &&
+ ct->flags & IP_VS_CONN_F_TEMPLATE &&
+ ct->protocol == p->protocol &&
+ ct->pe_data && ct->pe_data_len == p->pe_data_len &&
+ !memcmp(ct->pe_data, p->pe_data, p->pe_data_len))
+ ret = 1;
+
+ IP_VS_DBG_BUF(9, "SIP template match %s %s->%s:%d %s\n",
+ ip_vs_proto_name(p->protocol),
+ IP_VS_DEBUG_CALLID(p->pe_data, p->pe_data_len),
+ IP_VS_DBG_ADDR(p->af, p->vaddr), ntohs(p->vport),
+ ret ? "hit" : "not hit");
+
+ return ret;
+}
+
+static u32 ip_vs_sip_hashkey_raw(const struct ip_vs_conn_param *p,
+ u32 initval, bool inverse)
+{
+ return jhash(p->pe_data, p->pe_data_len, initval);
+}
+
+static int ip_vs_sip_show_pe_data(const struct ip_vs_conn *cp, char *buf)
+{
+ memcpy(buf, cp->pe_data, cp->pe_data_len);
+ return cp->pe_data_len;
+}
+
+static struct ip_vs_pe ip_vs_sip_pe =
+{
+ .name = "sip",
+ .refcnt = ATOMIC_INIT(0),
+ .module = THIS_MODULE,
+ .n_list = LIST_HEAD_INIT(ip_vs_sip_pe.n_list),
+ .fill_param = ip_vs_sip_fill_param,
+ .ct_match = ip_vs_sip_ct_match,
+ .hashkey_raw = ip_vs_sip_hashkey_raw,
+ .show_pe_data = ip_vs_sip_show_pe_data,
+};
+
+static int __init ip_vs_sip_init(void)
+{
+ return register_ip_vs_pe(&ip_vs_sip_pe);
+}
+
+static void __exit ip_vs_sip_cleanup(void)
+{
+ unregister_ip_vs_pe(&ip_vs_sip_pe);
+}
+
+module_init(ip_vs_sip_init);
+module_exit(ip_vs_sip_cleanup);
+MODULE_LICENSE("GPL");
--
1.7.1
next prev parent reply other threads:[~2010-10-21 15:19 UTC|newest]
Thread overview: 75+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-10-21 15:18 [PATCH 00/72] netfilter: netfilter update for 2.6.37 kaber
2010-10-21 15:18 ` [PATCH 01/72] netfilter: nf_nat: add nf_nat_csum() kaber
2010-10-21 15:18 ` [PATCH 02/72] netfilter: use NFPROTO_IPV4 instead of AF_INET kaber
2010-10-21 15:18 ` [PATCH 03/72] netfilter: nf_nat_core: don't check if the tuple is used if there is no other choice kaber
2010-10-21 15:18 ` [PATCH 04/72] netfilter: nf_nat: no IP_NAT_RANGE_MAP_IPS flags when alloc_null_binding() kaber
2010-10-21 15:18 ` [PATCH 05/72] netfilter: nf_conntrack: fix the hash random initializing race kaber
2010-10-21 15:18 ` [PATCH 06/72] ipvs: extend connection flags to 32 bits kaber
2010-10-21 15:18 ` [PATCH 07/72] ipvs: netfilter connection tracking changes kaber
2010-10-21 15:18 ` [PATCH 08/72] ipvs: make rerouting optional with snat_reroute kaber
2010-10-21 15:18 ` [PATCH 09/72] netfilter: save the hash of the tuple in the original direction for latter use kaber
2010-10-21 15:18 ` [PATCH 10/72] ipvs: changes related to service usecnt kaber
2010-10-21 15:18 ` [PATCH 11/72] netfilter: nf_nat: better error handling of nf_ct_expect_related() in helpers kaber
2010-10-21 15:18 ` [PATCH 12/72] netfilter: ctnetlink: missing validation of CTA_EXPECT_ZONE attribute kaber
2010-10-21 15:19 ` [PATCH 13/72] netfilter: ctnetlink: allow to specify the expectation flags kaber
2010-10-21 15:19 ` [PATCH 14/72] netfilter: ctnetlink: add support for user-space expectation helpers kaber
2010-10-21 15:19 ` [PATCH 15/72] netfilter: nf_conntrack_sip: Allow ct_sip_get_header() to be called with a null ct argument kaber
2010-10-21 15:19 ` [PATCH 16/72] netfilter: nf_conntrack_sip: Add callid parser kaber
2010-10-21 15:19 ` [PATCH 17/72] IPVS: compact ip_vs_sched_persist() kaber
2010-10-21 15:19 ` [PATCH 18/72] IPVS: Add struct ip_vs_conn_param kaber
2010-10-21 15:19 ` [PATCH 19/72] IPVS: Allow null argument to ip_vs_scheduler_put() kaber
2010-10-21 15:19 ` [PATCH 20/72] IPVS: ip_vs_{un,}bind_scheduler NULL arguments kaber
2010-10-21 15:19 ` [PATCH 21/72] IPVS: Add struct ip_vs_pe kaber
2010-10-21 15:19 ` [PATCH 22/72] IPVS: Add persistence engine data to /proc/net/ip_vs_conn kaber
2010-10-21 15:19 ` [PATCH 23/72] IPVS: management of persistence engine modules kaber
2010-10-21 15:19 ` [PATCH 24/72] IPVS: Allow configuration of persistence engines kaber
2010-10-21 15:19 ` [PATCH 25/72] IPVS: Fallback if persistence engine fails kaber
2010-10-21 15:19 ` kaber [this message]
2010-10-21 15:19 ` [PATCH 27/72] netfilter: nf_nat: make find/put static kaber
2010-10-21 15:19 ` [PATCH 28/72] netfilter: ipt_LOG: add bufferisation to call printk() once kaber
2010-10-21 15:19 ` [PATCH 29/72] netfilter: remove duplicated include kaber
2010-10-21 15:19 ` [PATCH 30/72] netfilter: unregister nf hooks, matches and targets in the reverse order kaber
2010-10-21 15:19 ` [PATCH 31/72] netfilter: add missing xt_log.h file kaber
2010-10-21 15:19 ` [PATCH 32/72] netfilter: xtables: resolve indirect macros 1/3 kaber
2010-10-21 15:19 ` [PATCH 33/72] netfilter: xtables: resolve indirect macros 2/3 kaber
2010-10-21 15:19 ` [PATCH 34/72] netfilter: xtables: resolve indirect macros 3/3 kaber
2010-10-21 15:19 ` [PATCH 35/72] netfilter: xtables: unify {ip,ip6,arp}t_error_target kaber
2010-10-21 15:19 ` [PATCH 36/72] netfilter: xtables: remove unused defines kaber
2010-10-21 15:19 ` [PATCH 37/72] IPVS: ip_vs_dbg_callid() is only needed for debugging kaber
2010-10-21 15:19 ` [PATCH 38/72] netfilter: fix kconfig unmet dependency warning kaber
2010-10-21 15:19 ` [PATCH 39/72] netfilter: install missing ebtables headers for userspace kaber
2010-10-21 15:19 ` [PATCH 40/72] netfilter: ctnetlink: add expectation deletion events kaber
2010-10-21 15:19 ` [PATCH 41/72] ipvs: IPv6 tunnel mode kaber
2010-10-21 15:19 ` [PATCH 42/72] Fixed race condition at ip_vs.ko module init kaber
2010-10-21 15:19 ` [PATCH 43/72] ipvs: fix CHECKSUM_PARTIAL for TCP, UDP kaber
2010-10-21 15:19 ` [PATCH 44/72] ipvs: optimize checksums for apps kaber
2010-10-21 15:19 ` [PATCH 45/72] ipvs: switch to notrack mode kaber
2010-10-21 15:19 ` [PATCH 46/72] ipvs: do not schedule conns from real servers kaber
2010-10-21 15:19 ` [PATCH 47/72] ipvs: stop ICMP from FORWARD to local kaber
2010-10-21 15:19 ` [PATCH 48/72] ipvs: fix CHECKSUM_PARTIAL for TUN method kaber
2010-10-21 15:19 ` [PATCH 49/72] ipvs: create ip_vs_defrag_user kaber
2010-10-21 15:19 ` [PATCH 50/72] ipvs: move ip_route_me_harder for ICMP kaber
2010-10-21 15:19 ` [PATCH 51/72] ipvs: changes for local real server kaber
2010-10-21 15:19 ` [PATCH 52/72] ipvs: changes for local client kaber
2010-10-21 15:19 ` [PATCH 53/72] ipvs: inherit forwarding method in backup kaber
2010-10-21 15:19 ` [PATCH 54/72] ipvs: provide address family for debugging kaber
2010-10-21 15:19 ` [PATCH 55/72] tproxy: kick out TIME_WAIT sockets in case a new connection comes in with the same tuple kaber
2010-10-21 15:19 ` [PATCH 56/72] tproxy: add lookup type checks for UDP in nf_tproxy_get_sock_v4() kaber
2010-10-21 15:19 ` [PATCH 57/72] tproxy: fix hash locking issue when using port redirection in __inet_inherit_port() kaber
2010-10-21 15:19 ` [PATCH 58/72] nf_nat: restrict ICMP translation for embedded header kaber
2010-10-21 15:19 ` [PATCH 59/72] tproxy: split off ipv6 defragmentation to a separate module kaber
2010-10-21 15:19 ` [PATCH 60/72] tproxy: added const specifiers to udp lookup functions kaber
2010-10-21 15:19 ` [PATCH 61/72] tproxy: added udp6_lib_lookup function kaber
2010-10-21 15:19 ` [PATCH 62/72] tproxy: added tproxy sockopt interface in the IPV6 layer kaber
2010-10-21 15:19 ` [PATCH 63/72] tproxy: allow non-local binds of IPv6 sockets if IP_TRANSPARENT is enabled kaber
2010-10-21 21:07 ` YOSHIFUJI Hideaki
2010-10-21 15:19 ` [PATCH 64/72] tproxy: added IPv6 socket lookup function to nf_tproxy_core kaber
2010-10-21 15:19 ` [PATCH 65/72] tproxy: added IPv6 support to the TPROXY target kaber
2010-10-21 15:19 ` [PATCH 66/72] tproxy: added IPv6 support to the socket match kaber
2010-10-21 15:19 ` [PATCH 67/72] tproxy: use the interface primary IP address as a default value for --on-ip kaber
2010-10-21 15:19 ` [PATCH 68/72] netfilter: ebtables: remove unused definitions kaber
2010-10-21 15:19 ` [PATCH 69/72] netfilter: xtables: add a missing pair of parentheses kaber
2010-10-21 15:19 ` [PATCH 70/72] netfilter: ebtables: replace EBT_ENTRY_ITERATE macro kaber
2010-10-21 15:19 ` [PATCH 71/72] netfilter: ebtables: replace EBT_MATCH_ITERATE macro kaber
2010-10-21 15:19 ` [PATCH 72/72] netfilter: ebtables: replace EBT_WATCHER_ITERATE macro kaber
2010-10-21 15:40 ` [PATCH 00/72] netfilter: netfilter update for 2.6.37 David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1287674399-31455-27-git-send-email-kaber@trash.net \
--to=kaber@trash.net \
--cc=davem@davemloft.net \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).