Blame view
net/netfilter/nf_conntrack_sane.c
6.1 KB
6fecd1985 [NETFILTER]: Add ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/* SANE connection tracking helper * (SANE = Scanner Access Now Easy) * For documentation about the SANE network protocol see * http://www.sane-project.org/html/doc015.html */ /* Copyright (C) 2007 Red Hat, Inc. * Author: Michal Schmidt <mschmidt@redhat.com> * Based on the FTP conntrack helper (net/netfilter/nf_conntrack_ftp.c): * (C) 1999-2001 Paul `Rusty' Russell * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> * (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org> * (C) 2003 Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/netfilter.h> |
5a0e3ad6a include cleanup: ... |
23 |
#include <linux/slab.h> |
6fecd1985 [NETFILTER]: Add ... |
24 25 26 27 28 29 30 31 32 33 |
#include <linux/in.h> #include <linux/tcp.h> #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_expect.h> #include <linux/netfilter/nf_conntrack_sane.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("Michal Schmidt <mschmidt@redhat.com>"); MODULE_DESCRIPTION("SANE connection tracking helper"); |
4dc06f963 netfilter: nf_con... |
34 |
MODULE_ALIAS_NFCT_HELPER("sane"); |
6fecd1985 [NETFILTER]: Add ... |
35 36 37 38 39 40 41 42 43 |
static char *sane_buffer; static DEFINE_SPINLOCK(nf_sane_lock); #define MAX_PORTS 8 static u_int16_t ports[MAX_PORTS]; static unsigned int ports_c; module_param_array(ports, ushort, &ports_c, 0400); |
6fecd1985 [NETFILTER]: Add ... |
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
struct sane_request { __be32 RPC_code; #define SANE_NET_START 7 /* RPC code */ __be32 handle; }; struct sane_reply_net_start { __be32 status; #define SANE_STATUS_SUCCESS 0 __be16 zero; __be16 port; /* other fields aren't interesting for conntrack */ }; |
3db05fea5 [NETFILTER]: Repl... |
59 |
static int help(struct sk_buff *skb, |
6fecd1985 [NETFILTER]: Add ... |
60 61 62 63 64 |
unsigned int protoff, struct nf_conn *ct, enum ip_conntrack_info ctinfo) { unsigned int dataoff, datalen; |
02e23f405 [NETFILTER]: nf_c... |
65 66 67 |
const struct tcphdr *th; struct tcphdr _tcph; void *sb_ptr; |
6fecd1985 [NETFILTER]: Add ... |
68 69 70 71 72 73 74 |
int ret = NF_ACCEPT; int dir = CTINFO2DIR(ctinfo); struct nf_ct_sane_master *ct_sane_info; struct nf_conntrack_expect *exp; struct nf_conntrack_tuple *tuple; struct sane_request *req; struct sane_reply_net_start *reply; |
6fecd1985 [NETFILTER]: Add ... |
75 76 77 78 |
ct_sane_info = &nfct_help(ct)->help.ct_sane_info; /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && |
fb0488337 netfilter: add mo... |
79 |
ctinfo != IP_CT_ESTABLISHED_REPLY) |
6fecd1985 [NETFILTER]: Add ... |
80 81 82 |
return NF_ACCEPT; /* Not a full tcp header? */ |
3db05fea5 [NETFILTER]: Repl... |
83 |
th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph); |
6fecd1985 [NETFILTER]: Add ... |
84 85 86 87 88 |
if (th == NULL) return NF_ACCEPT; /* No data? */ dataoff = protoff + th->doff * 4; |
3db05fea5 [NETFILTER]: Repl... |
89 |
if (dataoff >= skb->len) |
6fecd1985 [NETFILTER]: Add ... |
90 |
return NF_ACCEPT; |
3db05fea5 [NETFILTER]: Repl... |
91 |
datalen = skb->len - dataoff; |
6fecd1985 [NETFILTER]: Add ... |
92 93 |
spin_lock_bh(&nf_sane_lock); |
3db05fea5 [NETFILTER]: Repl... |
94 |
sb_ptr = skb_header_pointer(skb, dataoff, datalen, sane_buffer); |
6fecd1985 [NETFILTER]: Add ... |
95 96 97 98 99 |
BUG_ON(sb_ptr == NULL); if (dir == IP_CT_DIR_ORIGINAL) { if (datalen != sizeof(struct sane_request)) goto out; |
02e23f405 [NETFILTER]: nf_c... |
100 |
req = sb_ptr; |
6fecd1985 [NETFILTER]: Add ... |
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
if (req->RPC_code != htonl(SANE_NET_START)) { /* Not an interesting command */ ct_sane_info->state = SANE_STATE_NORMAL; goto out; } /* We're interested in the next reply */ ct_sane_info->state = SANE_STATE_START_REQUESTED; goto out; } /* Is it a reply to an uninteresting command? */ if (ct_sane_info->state != SANE_STATE_START_REQUESTED) goto out; /* It's a reply to SANE_NET_START. */ ct_sane_info->state = SANE_STATE_NORMAL; if (datalen < sizeof(struct sane_reply_net_start)) { |
0d53778e8 [NETFILTER]: Conv... |
120 121 |
pr_debug("nf_ct_sane: NET_START reply too short "); |
6fecd1985 [NETFILTER]: Add ... |
122 123 |
goto out; } |
02e23f405 [NETFILTER]: nf_c... |
124 |
reply = sb_ptr; |
6fecd1985 [NETFILTER]: Add ... |
125 126 |
if (reply->status != htonl(SANE_STATUS_SUCCESS)) { /* saned refused the command */ |
0d53778e8 [NETFILTER]: Conv... |
127 128 129 |
pr_debug("nf_ct_sane: unsuccessful SANE_STATUS = %u ", ntohl(reply->status)); |
6fecd1985 [NETFILTER]: Add ... |
130 131 132 133 134 135 |
goto out; } /* Invalid saned reply? Ignore it. */ if (reply->zero != 0) goto out; |
6823645d6 [NETFILTER]: nf_c... |
136 |
exp = nf_ct_expect_alloc(ct); |
6fecd1985 [NETFILTER]: Add ... |
137 138 139 140 141 142 |
if (exp == NULL) { ret = NF_DROP; goto out; } tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; |
5e8fbe2ac [NETFILTER]: nf_c... |
143 |
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct), |
6002f266b [NETFILTER]: nf_c... |
144 |
&tuple->src.u3, &tuple->dst.u3, |
6823645d6 [NETFILTER]: nf_c... |
145 |
IPPROTO_TCP, NULL, &reply->port); |
6fecd1985 [NETFILTER]: Add ... |
146 |
|
0d53778e8 [NETFILTER]: Conv... |
147 |
pr_debug("nf_ct_sane: expect: "); |
3c9fba656 [NETFILTER]: nf_c... |
148 |
nf_ct_dump_tuple(&exp->tuple); |
6fecd1985 [NETFILTER]: Add ... |
149 150 |
/* Can't expect this? Best to drop packet now. */ |
6823645d6 [NETFILTER]: nf_c... |
151 |
if (nf_ct_expect_related(exp) != 0) |
6fecd1985 [NETFILTER]: Add ... |
152 |
ret = NF_DROP; |
6823645d6 [NETFILTER]: nf_c... |
153 |
nf_ct_expect_put(exp); |
6fecd1985 [NETFILTER]: Add ... |
154 155 156 157 158 |
out: spin_unlock_bh(&nf_sane_lock); return ret; } |
ec59a1110 [NETFILTER]: nf_c... |
159 160 |
static struct nf_conntrack_helper sane[MAX_PORTS][2] __read_mostly; static char sane_names[MAX_PORTS][2][sizeof("sane-65535")] __read_mostly; |
6fecd1985 [NETFILTER]: Add ... |
161 |
|
6002f266b [NETFILTER]: nf_c... |
162 163 164 165 |
static const struct nf_conntrack_expect_policy sane_exp_policy = { .max_expected = 1, .timeout = 5 * 60, }; |
6fecd1985 [NETFILTER]: Add ... |
166 167 168 169 170 171 172 |
/* don't make this __exit, since it's called from __init ! */ static void nf_conntrack_sane_fini(void) { int i, j; for (i = 0; i < ports_c; i++) { for (j = 0; j < 2; j++) { |
0d53778e8 [NETFILTER]: Conv... |
173 174 175 176 |
pr_debug("nf_ct_sane: unregistering helper for pf: %d " "port: %d ", sane[i][j].tuple.src.l3num, ports[i]); |
6fecd1985 [NETFILTER]: Add ... |
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
nf_conntrack_helper_unregister(&sane[i][j]); } } kfree(sane_buffer); } static int __init nf_conntrack_sane_init(void) { int i, j = -1, ret = 0; char *tmpname; sane_buffer = kmalloc(65536, GFP_KERNEL); if (!sane_buffer) return -ENOMEM; if (ports_c == 0) ports[ports_c++] = SANE_PORT; /* FIXME should be configurable whether IPv4 and IPv6 connections are tracked or not - YK */ for (i = 0; i < ports_c; i++) { sane[i][0].tuple.src.l3num = PF_INET; sane[i][1].tuple.src.l3num = PF_INET6; for (j = 0; j < 2; j++) { sane[i][j].tuple.src.u.tcp.port = htons(ports[i]); sane[i][j].tuple.dst.protonum = IPPROTO_TCP; |
6002f266b [NETFILTER]: nf_c... |
204 |
sane[i][j].expect_policy = &sane_exp_policy; |
6fecd1985 [NETFILTER]: Add ... |
205 206 207 208 209 210 211 212 |
sane[i][j].me = THIS_MODULE; sane[i][j].help = help; tmpname = &sane_names[i][j][0]; if (ports[i] == SANE_PORT) sprintf(tmpname, "sane"); else sprintf(tmpname, "sane-%d", ports[i]); sane[i][j].name = tmpname; |
0d53778e8 [NETFILTER]: Conv... |
213 214 215 216 |
pr_debug("nf_ct_sane: registering helper for pf: %d " "port: %d ", sane[i][j].tuple.src.l3num, ports[i]); |
6fecd1985 [NETFILTER]: Add ... |
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
ret = nf_conntrack_helper_register(&sane[i][j]); if (ret) { printk(KERN_ERR "nf_ct_sane: failed to " "register helper for pf: %d port: %d ", sane[i][j].tuple.src.l3num, ports[i]); nf_conntrack_sane_fini(); return ret; } } } return 0; } module_init(nf_conntrack_sane_init); module_exit(nf_conntrack_sane_fini); |