aboutsummaryrefslogtreecommitdiff
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/Kconfig50
-rw-r--r--net/ipv4/Makefile6
-rw-r--r--net/ipv4/ah4.c15
-rw-r--r--net/ipv4/esp4.c18
-rw-r--r--net/ipv4/icmp.c5
-rw-r--r--net/ipv4/igmp.c2
-rw-r--r--net/ipv4/ip_output.c3
-rw-r--r--net/ipv4/ipcomp.c34
-rw-r--r--net/ipv4/netfilter/Kconfig40
-rw-r--r--net/ipv4/netfilter/Makefile2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_amanda.c143
-rw-r--r--net/ipv4/netfilter/ip_conntrack_core.c9
-rw-r--r--net/ipv4/netfilter/ip_conntrack_ftp.c77
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323.c111
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_h323_types.c6
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c85
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_gre.c6
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_icmp.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_tcp.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_proto_udp.c2
-rw-r--r--net/ipv4/netfilter/ip_conntrack_sip.c471
-rw-r--r--net/ipv4/netfilter/ip_conntrack_standalone.c18
-rw-r--r--net/ipv4/netfilter/ip_nat_helper_h323.c77
-rw-r--r--net/ipv4/netfilter/ip_nat_sip.c249
-rw-r--r--net/ipv4/netfilter/ip_nat_snmp_basic.c2
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c20
-rw-r--r--net/ipv4/netfilter/ipt_REJECT.c1
-rw-r--r--net/ipv4/netfilter/ipt_hashlimit.c73
-rw-r--r--net/ipv4/netfilter/ipt_recent.c1276
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c2
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c2
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/sysctl_net_ipv4.c26
-rw-r--r--net/ipv4/tcp.c127
-rw-r--r--net/ipv4/tcp_bic.c7
-rw-r--r--net/ipv4/tcp_compound.c448
-rw-r--r--net/ipv4/tcp_cong.c6
-rw-r--r--net/ipv4/tcp_cubic.c6
-rw-r--r--net/ipv4/tcp_highspeed.c24
-rw-r--r--net/ipv4/tcp_htcp.c9
-rw-r--r--net/ipv4/tcp_input.c89
-rw-r--r--net/ipv4/tcp_ipv4.c18
-rw-r--r--net/ipv4/tcp_lp.c338
-rw-r--r--net/ipv4/tcp_output.c6
-rw-r--r--net/ipv4/tcp_probe.c181
-rw-r--r--net/ipv4/tcp_veno.c231
-rw-r--r--net/ipv4/tcp_westwood.c80
-rw-r--r--net/ipv4/xfrm4_input.c28
-rw-r--r--net/ipv4/xfrm4_mode_transport.c83
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c125
-rw-r--r--net/ipv4/xfrm4_output.c61
-rw-r--r--net/ipv4/xfrm4_policy.c6
-rw-r--r--net/ipv4/xfrm4_state.c1
53 files changed, 3377 insertions, 1334 deletions
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index e40f7532237..da33393be45 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -414,6 +414,24 @@ config INET_TUNNEL
tristate
default n
+config INET_XFRM_MODE_TRANSPORT
+ tristate "IP: IPsec transport mode"
+ default y
+ select XFRM
+ ---help---
+ Support for IPsec transport mode.
+
+ If unsure, say Y.
+
+config INET_XFRM_MODE_TUNNEL
+ tristate "IP: IPsec tunnel mode"
+ default y
+ select XFRM
+ ---help---
+ Support for IPsec tunnel mode.
+
+ If unsure, say Y.
+
config INET_DIAG
tristate "INET: socket monitoring interface"
default y
@@ -532,6 +550,38 @@ config TCP_CONG_SCALABLE
properties, though is known to have fairness issues.
See http://www-lce.eng.cam.ac.uk/~ctk21/scalable/
+config TCP_CONG_LP
+ tristate "TCP Low Priority"
+ depends on EXPERIMENTAL
+ default n
+ ---help---
+ TCP Low Priority (TCP-LP), a distributed algorithm whose goal is
+ to utiliza only the excess network bandwidth as compared to the
+ ``fair share`` of bandwidth as targeted by TCP.
+ See http://www-ece.rice.edu/networks/TCP-LP/
+
+config TCP_CONG_VENO
+ tristate "TCP Veno"
+ depends on EXPERIMENTAL
+ default n
+ ---help---
+ TCP Veno is a sender-side only enhancement of TCP to obtain better
+ throughput over wireless networks. TCP Veno makes use of state
+ distinguishing to circumvent the difficult judgment of the packet loss
+ type. TCP Veno cuts down less congestion window in response to random
+ loss packets.
+ See http://www.ntu.edu.sg/home5/ZHOU0022/papers/CPFu03a.pdf
+
+config TCP_CONG_COMPOUND
+ tristate "TCP Compound"
+ depends on EXPERIMENTAL
+ default n
+ ---help---
+ TCP Compound is a sender-side only change to TCP that uses
+ a mixed Reno/Vegas approach to calculate the cwnd.
+ For further details look here:
+ ftp://ftp.research.microsoft.com/pub/tr/TR-2005-86.pdf
+
endmenu
config TCP_CONG_BIC
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 9ef50a0b9d2..38b8039bdd5 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -24,6 +24,8 @@ obj-$(CONFIG_INET_ESP) += esp4.o
obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o
obj-$(CONFIG_INET_TUNNEL) += tunnel4.o
+obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
+obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
obj-$(CONFIG_IP_PNP) += ipconfig.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_RR) += multipath_rr.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_RANDOM) += multipath_random.o
@@ -34,6 +36,7 @@ obj-$(CONFIG_IP_VS) += ipvs/
obj-$(CONFIG_INET_DIAG) += inet_diag.o
obj-$(CONFIG_IP_ROUTE_MULTIPATH_CACHED) += multipath.o
obj-$(CONFIG_INET_TCP_DIAG) += tcp_diag.o
+obj-$(CONFIG_NET_TCPPROBE) += tcp_probe.o
obj-$(CONFIG_TCP_CONG_BIC) += tcp_bic.o
obj-$(CONFIG_TCP_CONG_CUBIC) += tcp_cubic.o
obj-$(CONFIG_TCP_CONG_WESTWOOD) += tcp_westwood.o
@@ -41,7 +44,10 @@ obj-$(CONFIG_TCP_CONG_HSTCP) += tcp_highspeed.o
obj-$(CONFIG_TCP_CONG_HYBLA) += tcp_hybla.o
obj-$(CONFIG_TCP_CONG_HTCP) += tcp_htcp.o
obj-$(CONFIG_TCP_CONG_VEGAS) += tcp_vegas.o
+obj-$(CONFIG_TCP_CONG_VENO) += tcp_veno.o
obj-$(CONFIG_TCP_CONG_SCALABLE) += tcp_scalable.o
+obj-$(CONFIG_TCP_CONG_LP) += tcp_lp.o
+obj-$(CONFIG_TCP_CONG_COMPOUND) += tcp_compound.o
obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
xfrm4_output.o
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index e2e4771fa4c..c7782230080 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -119,6 +119,7 @@ error:
static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
{
int ah_hlen;
+ int ihl;
struct iphdr *iph;
struct ip_auth_hdr *ah;
struct ah_data *ahp;
@@ -149,13 +150,14 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
ah = (struct ip_auth_hdr*)skb->data;
iph = skb->nh.iph;
- memcpy(work_buf, iph, iph->ihl*4);
+ ihl = skb->data - skb->nh.raw;
+ memcpy(work_buf, iph, ihl);
iph->ttl = 0;
iph->tos = 0;
iph->frag_off = 0;
iph->check = 0;
- if (iph->ihl != 5) {
+ if (ihl > sizeof(*iph)) {
u32 dummy;
if (ip_clear_mutable_options(iph, &dummy))
goto out;
@@ -164,7 +166,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
u8 auth_data[MAX_AH_AUTH_LEN];
memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
- skb_push(skb, skb->data - skb->nh.raw);
+ skb_push(skb, ihl);
ahp->icv(ahp, skb, ah->auth_data);
if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
x->stats.integrity_failed++;
@@ -172,11 +174,8 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
}
}
((struct iphdr*)work_buf)->protocol = ah->nexthdr;
- skb->nh.raw = skb_pull(skb, ah_hlen);
- memcpy(skb->nh.raw, work_buf, iph->ihl*4);
- skb->nh.iph->tot_len = htons(skb->len);
- skb_pull(skb, skb->nh.iph->ihl*4);
- skb->h.raw = skb->data;
+ skb->h.raw = memcpy(skb->nh.raw += ah_hlen, work_buf, ihl);
+ __skb_pull(skb, ah_hlen + ihl);
return 0;
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 9d1881c07a3..9bbdd449455 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -143,10 +143,9 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
int alen = esp->auth.icv_trunc_len;
int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen;
int nfrags;
- int encap_len = 0;
+ int ihl;
u8 nexthdr[2];
struct scatterlist *sg;
- u8 workbuf[60];
int padlen;
if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr)))
@@ -177,7 +176,6 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
skb->ip_summed = CHECKSUM_NONE;
esph = (struct ip_esp_hdr*)skb->data;
- iph = skb->nh.iph;
/* Get ivec. This can be wrong, check against another impls. */
if (esp->conf.ivlen)
@@ -204,12 +202,12 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
/* ... check padding bits here. Silly. :-) */
+ iph = skb->nh.iph;
+ ihl = iph->ihl * 4;
+
if (x->encap) {
struct xfrm_encap_tmpl *encap = x->encap;
- struct udphdr *uh;
-
- uh = (struct udphdr *)(iph + 1);
- encap_len = (void*)esph - (void*)uh;
+ struct udphdr *uh = (void *)(skb->nh.raw + ihl);
/*
* 1) if the NAT-T peer's IP or port changed then
@@ -246,11 +244,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
iph->protocol = nexthdr[1];
pskb_trim(skb, skb->len - alen - padlen - 2);
- memcpy(workbuf, skb->nh.raw, iph->ihl*4);
- skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen);
- skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen;
- memcpy(skb->nh.raw, workbuf, iph->ihl*4);
- skb->nh.iph->tot_len = htons(skb->len);
+ skb->h.raw = __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen) - ihl;
return 0;
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 2a0455911ee..017900172f7 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -730,7 +730,6 @@ out_err:
static void icmp_redirect(struct sk_buff *skb)
{
struct iphdr *iph;
- unsigned long ip;
if (skb->len < sizeof(struct iphdr))
goto out_err;
@@ -742,7 +741,6 @@ static void icmp_redirect(struct sk_buff *skb)
goto out;
iph = (struct iphdr *)skb->data;
- ip = iph->daddr;
switch (skb->h.icmph->code & 7) {
case ICMP_REDIR_NET:
@@ -752,7 +750,8 @@ static void icmp_redirect(struct sk_buff *skb)
*/
case ICMP_REDIR_HOST:
case ICMP_REDIR_HOSTTOS:
- ip_rt_redirect(skb->nh.iph->saddr, ip, skb->h.icmph->un.gateway,
+ ip_rt_redirect(skb->nh.iph->saddr, iph->daddr,
+ skb->h.icmph->un.gateway,
iph->saddr, skb->dev);
break;
}
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index d512239a147..ab680c851aa 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -2361,7 +2361,7 @@ static int igmp_mc_seq_show(struct seq_file *seq, void *v)
}
seq_printf(seq,
- "\t\t\t\t%08lX %5d %d:%08lX\t\t%d\n",
+ "\t\t\t\t%08X %5d %d:%08lX\t\t%d\n",
im->multiaddr, im->users,
im->tm_running, im->tm_running ?
jiffies_to_clock_t(im->timer.expires-jiffies) : 0,
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index cff9c3a72da..8538aac3d14 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -410,6 +410,7 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from)
nf_bridge_get(to->nf_bridge);
#endif
#endif
+ skb_copy_secmark(to, from);
}
/*
@@ -839,7 +840,7 @@ int ip_append_data(struct sock *sk,
*/
if (transhdrlen &&
length + fragheaderlen <= mtu &&
- rt->u.dst.dev->features&(NETIF_F_IP_CSUM|NETIF_F_NO_CSUM|NETIF_F_HW_CSUM) &&
+ rt->u.dst.dev->features & NETIF_F_ALL_CSUM &&
!exthdrlen)
csummode = CHECKSUM_HW;
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index 95278b22b66..3ed8b57a100 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -45,7 +45,6 @@ static LIST_HEAD(ipcomp_tfms_list);
static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
{
int err, plen, dlen;
- struct iphdr *iph;
struct ipcomp_data *ipcd = x->data;
u8 *start, *scratch;
struct crypto_tfm *tfm;
@@ -74,8 +73,6 @@ static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb)
skb_put(skb, dlen - plen);
memcpy(skb->data, scratch, dlen);
- iph = skb->nh.iph;
- iph->tot_len = htons(dlen + iph->ihl * 4);
out:
put_cpu();
return err;
@@ -83,34 +80,21 @@ out:
static int ipcomp_input(struct xfrm_state *x, struct sk_buff *skb)
{
- u8 nexthdr;
- int err = 0;
+ int err = -ENOMEM;
struct iphdr *iph;
- union {
- struct iphdr iph;
- char buf[60];
- } tmp_iph;
-
+ struct ip_comp_hdr *ipch;
- if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
- skb_linearize(skb, GFP_ATOMIC) != 0) {
- err = -ENOMEM;
+ if (skb_linearize_cow(skb))
goto out;
- }
skb->ip_summed = CHECKSUM_NONE;
/* Remove ipcomp header and decompress original payload */
iph = skb->nh.iph;
- memcpy(&tmp_iph, iph, iph->ihl * 4);
- nexthdr = *(u8 *)skb->data;
- skb_pull(skb, sizeof(struct ip_comp_hdr));
- skb->nh.raw += sizeof(struct ip_comp_hdr);
- memcpy(skb->nh.raw, &tmp_iph, tmp_iph.iph.ihl * 4);
- iph = skb->nh.iph;
- iph->tot_len = htons(ntohs(iph->tot_len) - sizeof(struct ip_comp_hdr));
- iph->protocol = nexthdr;
- skb->h.raw = skb->data;
+ ipch = (void *)skb->data;
+ iph->protocol = ipch->nexthdr;
+ skb->h.raw = skb->nh.raw + sizeof(*ipch);
+ __skb_pull(skb, sizeof(*ipch));
err = ipcomp_decompress(x, skb);
out:
@@ -171,10 +155,8 @@ static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
goto out_ok;
}
- if ((skb_is_nonlinear(skb) || skb_cloned(skb)) &&
- skb_linearize(skb, GFP_ATOMIC) != 0) {
+ if (skb_linearize_cow(skb))
goto out_ok;
- }
err = ipcomp_compress(x, skb);
iph = skb->nh.iph;
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index d4072533da2..e1d7f5fbc52 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -55,6 +55,18 @@ config IP_NF_CONNTRACK_MARK
of packets, but this mark value is kept in the conntrack session
instead of the individual packets.
+config IP_NF_CONNTRACK_SECMARK
+ bool 'Connection tracking security mark support'
+ depends on IP_NF_CONNTRACK && NETWORK_SECMARK
+ help
+ This option enables security markings to be applied to
+ connections. Typically they are copied to connections from
+ packets using the CONNSECMARK target and copied back from
+ connections to packets with the same target, with the packets
+ being originally labeled via SECMARK.
+
+ If unsure, say 'N'.
+
config IP_NF_CONNTRACK_EVENTS
bool "Connection tracking events (EXPERIMENTAL)"
depends on EXPERIMENTAL && IP_NF_CONNTRACK
@@ -142,6 +154,8 @@ config IP_NF_TFTP
config IP_NF_AMANDA
tristate "Amanda backup protocol support"
depends on IP_NF_CONNTRACK
+ select TEXTSEARCH
+ select TEXTSEARCH_KMP
help
If you are running the Amanda backup package <http://www.amanda.org/>
on this machine or machines that will be MASQUERADED through this
@@ -181,14 +195,26 @@ config IP_NF_H323
With this module you can support H.323 on a connection tracking/NAT
firewall.
- This module supports RAS, Fast-start, H.245 tunnelling, RTP/RTCP
- and T.120 based data and applications including audio, video, FAX,
- chat, whiteboard, file transfer, etc. For more information, please
- see http://nath323.sourceforge.net/.
+ This module supports RAS, Fast Start, H.245 Tunnelling, Call
+ Forwarding, RTP/RTCP and T.120 based audio, video, fax, chat,
+ whiteboard, file transfer, etc. For more information, please
+ visit http://nath323.sourceforge.net/.
If you want to compile it as a module, say 'M' here and read
Documentation/modules.txt. If unsure, say 'N'.
+config IP_NF_SIP
+ tristate "SIP protocol support (EXPERIMENTAL)"
+ depends on IP_NF_CONNTRACK && EXPERIMENTAL
+ help
+ SIP is an application-layer control protocol that can establish,
+ modify, and terminate multimedia sessions (conferences) such as
+ Internet telephony calls. With the ip_conntrack_sip and
+ the ip_nat_sip modules you can support the protocol on a connection
+ tracking/NATing firewall.
+
+ To compile it as a module, choose M here. If unsure, say Y.
+
config IP_NF_QUEUE
tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
help
@@ -501,6 +527,12 @@ config IP_NF_NAT_H323
default IP_NF_NAT if IP_NF_H323=y
default m if IP_NF_H323=m
+config IP_NF_NAT_SIP
+ tristate
+ depends on IP_NF_IPTABLES!=n && IP_NF_CONNTRACK!=n && IP_NF_NAT!=n
+ default IP_NF_NAT if IP_NF_SIP=y
+ default m if IP_NF_SIP=m
+
# mangle + specific targets
config IP_NF_MANGLE
tristate "Packet mangling"
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
index 461cb1eb5de..3ded4a3af59 100644
--- a/net/ipv4/netfilter/Makefile
+++ b/net/ipv4/netfilter/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_IP_NF_AMANDA) += ip_conntrack_amanda.o
obj-$(CONFIG_IP_NF_TFTP) += ip_conntrack_tftp.o
obj-$(CONFIG_IP_NF_FTP) += ip_conntrack_ftp.o
obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
+obj-$(CONFIG_IP_NF_SIP) += ip_conntrack_sip.o
obj-$(CONFIG_IP_NF_NETBIOS_NS) += ip_conntrack_netbios_ns.o
# NAT helpers
@@ -40,6 +41,7 @@ obj-$(CONFIG_IP_NF_NAT_AMANDA) += ip_nat_amanda.o
obj-$(CONFIG_IP_NF_NAT_TFTP) += ip_nat_tftp.o
obj-$(CONFIG_IP_NF_NAT_FTP) += ip_nat_ftp.o
obj-$(CONFIG_IP_NF_NAT_IRC) += ip_nat_irc.o
+obj-$(CONFIG_IP_NF_NAT_SIP) += ip_nat_sip.o
# generic IP tables
obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
diff --git a/net/ipv4/netfilter/ip_conntrack_amanda.c b/net/ipv4/netfilter/ip_conntrack_amanda.c
index a604b1ccfda..0a7bd7f0406 100644
--- a/net/ipv4/netfilter/ip_conntrack_amanda.c
+++ b/net/ipv4/netfilter/ip_conntrack_amanda.c
@@ -17,33 +17,29 @@
* this value.
*
*/
-
-#include <linux/in.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/netfilter.h>
-#include <linux/ip.h>
#include <linux/moduleparam.h>
+#include <linux/textsearch.h>
+#include <linux/skbuff.h>
+#include <linux/in.h>
+#include <linux/ip.h>
#include <linux/udp.h>
-#include <net/checksum.h>
-#include <net/udp.h>
+#include <linux/netfilter.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
static unsigned int master_timeout = 300;
+static char *ts_algo = "kmp";
MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>");
MODULE_DESCRIPTION("Amanda connection tracking module");
MODULE_LICENSE("GPL");
module_param(master_timeout, uint, 0600);
MODULE_PARM_DESC(master_timeout, "timeout for the master connection");
-
-static const char *conns[] = { "DATA ", "MESG ", "INDEX " };
-
-/* This is slow, but it's simple. --RR */
-static char *amanda_buffer;
-static DEFINE_SPINLOCK(amanda_buffer_lock);
+module_param(ts_algo, charp, 0400);
+MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)");
unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
enum ip_conntrack_info ctinfo,
@@ -52,12 +48,48 @@ unsigned int (*ip_nat_amanda_hook)(struct sk_buff **pskb,
struct ip_conntrack_expect *exp);
EXPORT_SYMBOL_GPL(ip_nat_amanda_hook);
+enum amanda_strings {
+ SEARCH_CONNECT,
+ SEARCH_NEWLINE,
+ SEARCH_DATA,
+ SEARCH_MESG,
+ SEARCH_INDEX,
+};
+
+static struct {
+ char *string;
+ size_t len;
+ struct ts_config *ts;
+} search[] = {
+ [SEARCH_CONNECT] = {
+ .string = "CONNECT ",
+ .len = 8,
+ },
+ [SEARCH_NEWLINE] = {
+ .string = "\n",
+ .len = 1,
+ },
+ [SEARCH_DATA] = {
+ .string = "DATA ",
+ .len = 5,
+ },
+ [SEARCH_MESG] = {
+ .string = "MESG ",
+ .len = 5,
+ },
+ [SEARCH_INDEX] = {
+ .string = "INDEX ",
+ .len = 6,
+ },
+};
+
static int help(struct sk_buff **pskb,
struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
{
+ struct ts_state ts;
struct ip_conntrack_expect *exp;
- char *data, *data_limit, *tmp;
- unsigned int dataoff, i;
+ unsigned int dataoff, start, stop, off, i;
+ char pbuf[sizeof("65535")], *tmp;
u_int16_t port, len;
int ret = NF_ACCEPT;
@@ -77,29 +109,34 @@ static int help(struct sk_buff **pskb,
return NF_ACCEPT;
}
- spin_lock_bh(&amanda_buffer_lock);
- skb_copy_bits(*pskb, dataoff, amanda_buffer, (*pskb)->len - dataoff);
- data = amanda_buffer;
- data_limit = amanda_buffer + (*pskb)->len - dataoff;
- *data_limit = '\0';
-
- /* Search for the CONNECT string */
- data = strstr(data, "CONNECT ");
- if (!data)
+ memset(&ts, 0, sizeof(ts));
+ start = skb_find_text(*pskb, dataoff, (*pskb)->len,
+ search[SEARCH_CONNECT].ts, &ts);
+ if (start == UINT_MAX)
goto out;
- data += strlen("CONNECT ");
+ start += dataoff + search[SEARCH_CONNECT].len;
- /* Only search first line. */
- if ((tmp = strchr(data, '\n')))
- *tmp = '\0';
+ memset(&ts, 0, sizeof(ts));
+ stop = skb_find_text(*pskb, start, (*pskb)->len,
+ search[SEARCH_NEWLINE].ts, &ts);
+ if (stop == UINT_MAX)
+ goto out;
+ stop += start;
- for (i = 0; i < ARRAY_SIZE(conns); i++) {
- char *match = strstr(data, conns[i]);
- if (!match)
+ for (i = SEARCH_DATA; i <= SEARCH_INDEX; i++) {
+ memset(&ts, 0, sizeof(ts));
+ off = skb_find_text(*pskb, start, stop, search[i].ts, &ts);
+ if (off == UINT_MAX)
continue;
- tmp = data = match + strlen(conns[i]);
- port = simple_strtoul(data, &data, 10);
- len = data - tmp;
+ off += start + search[i].len;
+
+ len = min_t(unsigned int, sizeof(pbuf) - 1, stop - off);
+ if (skb_copy_bits(*pskb, off, pbuf, len))
+ break;
+ pbuf[len] = '\0';
+
+ port = simple_strtoul(pbuf, &tmp, 10);
+ len = tmp - pbuf;
if (port == 0 || len > 5)
break;
@@ -125,8 +162,7 @@ static int help(struct sk_buff **pskb,
exp->mask.dst.u.tcp.port = 0xFFFF;
if (ip_nat_amanda_hook)
- ret = ip_nat_amanda_hook(pskb, ctinfo,
- tmp - amanda_buffer,
+ ret = ip_nat_amanda_hook(pskb, ctinfo, off - dataoff,
len, exp);
else if (ip_conntrack_expect_related(exp) != 0)
ret = NF_DROP;
@@ -134,12 +170,11 @@ static int help(struct sk_buff **pskb,
}
out:
- spin_unlock_bh(&amanda_buffer_lock);
return ret;
}
static struct ip_conntrack_helper amanda_helper = {
- .max_expected = ARRAY_SIZE(conns),
+ .max_expected = 3,
.timeout = 180,
.me = THIS_MODULE,
.help = help,
@@ -155,26 +190,36 @@ static struct ip_conntrack_helper amanda_helper = {
static void __exit ip_conntrack_amanda_fini(void)
{
+ int i;
+
ip_conntrack_helper_unregister(&amanda_helper);
- kfree(amanda_buffer);
+ for (i = 0; i < ARRAY_SIZE(search); i++)
+ textsearch_destroy(search[i].ts);
}
static int __init ip_conntrack_amanda_init(void)
{
- int ret;
-
- amanda_buffer = kmalloc(65536, GFP_KERNEL);
- if (!amanda_buffer)
- return -ENOMEM;
-
- ret = ip_conntrack_helper_register(&amanda_helper);
- if (ret < 0) {
- kfree(amanda_buffer);
- return ret;
+ int ret, i;
+
+ ret = -ENOMEM;
+ for (i = 0; i < ARRAY_SIZE(search); i++) {
+ search[i].ts = textsearch_prepare(ts_algo, search[i].string,
+ search[i].len,
+ GFP_KERNEL, TS_AUTOLOAD);
+ if (search[i].ts == NULL)
+ goto err;
}
+ ret = ip_conntrack_helper_register(&amanda_helper);
+ if (ret < 0)
+ goto err;
return 0;
-
+err:
+ for (; i >= 0; i--) {
+ if (search[i].ts)
+ textsearch_destroy(search[i].ts);
+ }
+ return ret;
}
module_init(ip_conntrack_amanda_init);
diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c
index a297da7bbef..7e4cf9a4d15 100644
--- a/net/ipv4/netfilter/ip_conntrack_core.c
+++ b/