[NETFILTER]: conntrack: get rid of sparse warnings
[GitHub/exynos8895/android_kernel_samsung_universal8895.git] / net / netfilter / nf_conntrack_proto_sctp.c
CommitLineData
9fb9cbb1
YK
1/*
2 * Connection tracking protocol helper module for SCTP.
601e68e1
YH
3 *
4 * SCTP is defined in RFC 2960. References to various sections in this code
9fb9cbb1 5 * are to this RFC.
601e68e1 6 *
9fb9cbb1
YK
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
9fb9cbb1
YK
10 */
11
12#include <linux/types.h>
9fb9cbb1
YK
13#include <linux/timer.h>
14#include <linux/netfilter.h>
15#include <linux/module.h>
16#include <linux/in.h>
17#include <linux/ip.h>
18#include <linux/sctp.h>
19#include <linux/string.h>
20#include <linux/seq_file.h>
40a839fd
YK
21#include <linux/spinlock.h>
22#include <linux/interrupt.h>
9fb9cbb1
YK
23
24#include <net/netfilter/nf_conntrack.h>
605dcad6 25#include <net/netfilter/nf_conntrack_l4proto.h>
f6180121 26#include <net/netfilter/nf_conntrack_ecache.h>
9fb9cbb1 27
9fb9cbb1
YK
28/* Protects conntrack->proto.sctp */
29static DEFINE_RWLOCK(sctp_lock);
30
31/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
601e68e1 32 closely. They're more complex. --RR
9fb9cbb1
YK
33
34 And so for me for SCTP :D -Kiran */
35
36static const char *sctp_conntrack_names[] = {
37 "NONE",
38 "CLOSED",
39 "COOKIE_WAIT",
40 "COOKIE_ECHOED",
41 "ESTABLISHED",
42 "SHUTDOWN_SENT",
43 "SHUTDOWN_RECD",
44 "SHUTDOWN_ACK_SENT",
45};
46
47#define SECS * HZ
48#define MINS * 60 SECS
49#define HOURS * 60 MINS
50#define DAYS * 24 HOURS
51
86c0bf40
PM
52static unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX] __read_mostly = {
53 [SCTP_CONNTRACK_CLOSED] = 10 SECS,
54 [SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS,
55 [SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS,
56 [SCTP_CONNTRACK_ESTABLISHED] = 5 DAYS,
57 [SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000,
58 [SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000,
59 [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS,
60};
9fb9cbb1
YK
61
62#define sNO SCTP_CONNTRACK_NONE
63#define sCL SCTP_CONNTRACK_CLOSED
64#define sCW SCTP_CONNTRACK_COOKIE_WAIT
65#define sCE SCTP_CONNTRACK_COOKIE_ECHOED
66#define sES SCTP_CONNTRACK_ESTABLISHED
67#define sSS SCTP_CONNTRACK_SHUTDOWN_SENT
68#define sSR SCTP_CONNTRACK_SHUTDOWN_RECD
69#define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
70#define sIV SCTP_CONNTRACK_MAX
71
601e68e1 72/*
9fb9cbb1
YK
73 These are the descriptions of the states:
74
601e68e1 75NOTE: These state names are tantalizingly similar to the states of an
9fb9cbb1 76SCTP endpoint. But the interpretation of the states is a little different,
601e68e1 77considering that these are the states of the connection and not of an end
9fb9cbb1
YK
78point. Please note the subtleties. -Kiran
79
80NONE - Nothing so far.
601e68e1
YH
81COOKIE WAIT - We have seen an INIT chunk in the original direction, or also
82 an INIT_ACK chunk in the reply direction.
9fb9cbb1
YK
83COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction.
84ESTABLISHED - We have seen a COOKIE_ACK in the reply direction.
85SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction.
86SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply directoin.
87SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
601e68e1
YH
88 to that of the SHUTDOWN chunk.
89CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
90 the SHUTDOWN chunk. Connection is closed.
9fb9cbb1
YK
91*/
92
93/* TODO
601e68e1 94 - I have assumed that the first INIT is in the original direction.
9fb9cbb1
YK
95 This messes things when an INIT comes in the reply direction in CLOSED
96 state.
601e68e1 97 - Check the error type in the reply dir before transitioning from
9fb9cbb1
YK
98cookie echoed to closed.
99 - Sec 5.2.4 of RFC 2960
100 - Multi Homing support.
101*/
102
103/* SCTP conntrack state transitions */
a5e73c29 104static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
9fb9cbb1
YK
105 {
106/* ORIGINAL */
107/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
108/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
109/* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
110/* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
111/* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
112/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
113/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/
114/* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */
115/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */
116/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
117 },
118 {
119/* REPLY */
120/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA */
121/* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* INIT in sCL Big TODO */
122/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
123/* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
124/* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
125/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
126/* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
127/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */
128/* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
129/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
130 }
131};
132
133static int sctp_pkt_to_tuple(const struct sk_buff *skb,
134 unsigned int dataoff,
135 struct nf_conntrack_tuple *tuple)
136{
137 sctp_sctphdr_t _hdr, *hp;
138
9fb9cbb1
YK
139 /* Actually only need first 8 bytes. */
140 hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
141 if (hp == NULL)
142 return 0;
143
144 tuple->src.u.sctp.port = hp->source;
145 tuple->dst.u.sctp.port = hp->dest;
146 return 1;
147}
148
149static int sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
150 const struct nf_conntrack_tuple *orig)
151{
9fb9cbb1
YK
152 tuple->src.u.sctp.port = orig->dst.u.sctp.port;
153 tuple->dst.u.sctp.port = orig->src.u.sctp.port;
154 return 1;
155}
156
157/* Print out the per-protocol part of the tuple. */
158static int sctp_print_tuple(struct seq_file *s,
159 const struct nf_conntrack_tuple *tuple)
160{
9fb9cbb1
YK
161 return seq_printf(s, "sport=%hu dport=%hu ",
162 ntohs(tuple->src.u.sctp.port),
163 ntohs(tuple->dst.u.sctp.port));
164}
165
166/* Print out the private part of the conntrack. */
112f35c9 167static int sctp_print_conntrack(struct seq_file *s, const struct nf_conn *ct)
9fb9cbb1
YK
168{
169 enum sctp_conntrack state;
170
9fb9cbb1 171 read_lock_bh(&sctp_lock);
112f35c9 172 state = ct->proto.sctp.state;
9fb9cbb1
YK
173 read_unlock_bh(&sctp_lock);
174
175 return seq_printf(s, "%s ", sctp_conntrack_names[state]);
176}
177
178#define for_each_sctp_chunk(skb, sch, _sch, offset, dataoff, count) \
e79ec50b
JE
179for ((offset) = (dataoff) + sizeof(sctp_sctphdr_t), (count) = 0; \
180 (offset) < (skb)->len && \
181 ((sch) = skb_header_pointer((skb), (offset), sizeof(_sch), &(_sch))); \
182 (offset) += (ntohs((sch)->length) + 3) & ~3, (count)++)
9fb9cbb1
YK
183
184/* Some validity checks to make sure the chunks are fine */
112f35c9 185static int do_basic_checks(struct nf_conn *ct,
9fb9cbb1
YK
186 const struct sk_buff *skb,
187 unsigned int dataoff,
35c6d3cb 188 unsigned long *map)
9fb9cbb1
YK
189{
190 u_int32_t offset, count;
191 sctp_chunkhdr_t _sch, *sch;
192 int flag;
193
9fb9cbb1
YK
194 flag = 0;
195
196 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
0d53778e 197 pr_debug("Chunk Num: %d Type: %d\n", count, sch->type);
9fb9cbb1 198
5447d477
PM
199 if (sch->type == SCTP_CID_INIT ||
200 sch->type == SCTP_CID_INIT_ACK ||
201 sch->type == SCTP_CID_SHUTDOWN_COMPLETE)
9fb9cbb1 202 flag = 1;
9fb9cbb1 203
e17df688
PM
204 /*
205 * Cookie Ack/Echo chunks not the first OR
206 * Init / Init Ack / Shutdown compl chunks not the only chunks
207 * OR zero-length.
208 */
5447d477
PM
209 if (((sch->type == SCTP_CID_COOKIE_ACK ||
210 sch->type == SCTP_CID_COOKIE_ECHO ||
211 flag) &&
212 count != 0) || !sch->length) {
0d53778e 213 pr_debug("Basic checks failed\n");
9fb9cbb1
YK
214 return 1;
215 }
216
5447d477 217 if (map)
35c6d3cb 218 set_bit(sch->type, map);
9fb9cbb1
YK
219 }
220
0d53778e 221 pr_debug("Basic checks passed\n");
dd7271fe 222 return count == 0;
9fb9cbb1
YK
223}
224
efe9f68a
PM
225static int sctp_new_state(enum ip_conntrack_dir dir,
226 enum sctp_conntrack cur_state,
227 int chunk_type)
9fb9cbb1
YK
228{
229 int i;
230
0d53778e 231 pr_debug("Chunk type: %d\n", chunk_type);
9fb9cbb1
YK
232
233 switch (chunk_type) {
5447d477
PM
234 case SCTP_CID_INIT:
235 pr_debug("SCTP_CID_INIT\n");
236 i = 0;
237 break;
238 case SCTP_CID_INIT_ACK:
239 pr_debug("SCTP_CID_INIT_ACK\n");
240 i = 1;
241 break;
242 case SCTP_CID_ABORT:
243 pr_debug("SCTP_CID_ABORT\n");
244 i = 2;
245 break;
246 case SCTP_CID_SHUTDOWN:
247 pr_debug("SCTP_CID_SHUTDOWN\n");
248 i = 3;
249 break;
250 case SCTP_CID_SHUTDOWN_ACK:
251 pr_debug("SCTP_CID_SHUTDOWN_ACK\n");
252 i = 4;
253 break;
254 case SCTP_CID_ERROR:
255 pr_debug("SCTP_CID_ERROR\n");
256 i = 5;
257 break;
258 case SCTP_CID_COOKIE_ECHO:
259 pr_debug("SCTP_CID_COOKIE_ECHO\n");
260 i = 6;
261 break;
262 case SCTP_CID_COOKIE_ACK:
263 pr_debug("SCTP_CID_COOKIE_ACK\n");
264 i = 7;
265 break;
266 case SCTP_CID_SHUTDOWN_COMPLETE:
267 pr_debug("SCTP_CID_SHUTDOWN_COMPLETE\n");
268 i = 8;
269 break;
270 default:
271 /* Other chunks like DATA, SACK, HEARTBEAT and
272 its ACK do not cause a change in state */
273 pr_debug("Unknown chunk type, Will stay in %s\n",
274 sctp_conntrack_names[cur_state]);
275 return cur_state;
9fb9cbb1
YK
276 }
277
0d53778e
PM
278 pr_debug("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
279 dir, sctp_conntrack_names[cur_state], chunk_type,
280 sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
9fb9cbb1
YK
281
282 return sctp_conntracks[dir][i][cur_state];
283}
284
b37e933a 285/* Returns verdict for packet, or -NF_ACCEPT for invalid. */
112f35c9 286static int sctp_packet(struct nf_conn *ct,
9fb9cbb1
YK
287 const struct sk_buff *skb,
288 unsigned int dataoff,
289 enum ip_conntrack_info ctinfo,
290 int pf,
291 unsigned int hooknum)
292{
efe9f68a 293 enum sctp_conntrack new_state, old_state;
8528819a 294 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
9fb9cbb1
YK
295 sctp_sctphdr_t _sctph, *sh;
296 sctp_chunkhdr_t _sch, *sch;
297 u_int32_t offset, count;
35c6d3cb 298 unsigned long map[256 / sizeof(unsigned long)] = { 0 };
9fb9cbb1 299
9fb9cbb1
YK
300 sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
301 if (sh == NULL)
b37e933a 302 goto out;
9fb9cbb1 303
112f35c9 304 if (do_basic_checks(ct, skb, dataoff, map) != 0)
b37e933a 305 goto out;
9fb9cbb1
YK
306
307 /* Check the verification tag (Sec 8.5) */
35c6d3cb
PM
308 if (!test_bit(SCTP_CID_INIT, map) &&
309 !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) &&
310 !test_bit(SCTP_CID_COOKIE_ECHO, map) &&
311 !test_bit(SCTP_CID_ABORT, map) &&
312 !test_bit(SCTP_CID_SHUTDOWN_ACK, map) &&
8528819a 313 sh->vtag != ct->proto.sctp.vtag[dir]) {
0d53778e 314 pr_debug("Verification tag check failed\n");
b37e933a 315 goto out;
9fb9cbb1
YK
316 }
317
efe9f68a 318 old_state = new_state = SCTP_CONNTRACK_MAX;
4a64830a 319 write_lock_bh(&sctp_lock);
9fb9cbb1 320 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
9fb9cbb1
YK
321 /* Special cases of Verification tag check (Sec 8.5.1) */
322 if (sch->type == SCTP_CID_INIT) {
323 /* Sec 8.5.1 (A) */
b37e933a
PM
324 if (sh->vtag != 0)
325 goto out_unlock;
9fb9cbb1
YK
326 } else if (sch->type == SCTP_CID_ABORT) {
327 /* Sec 8.5.1 (B) */
8528819a 328 if (sh->vtag != ct->proto.sctp.vtag[dir] &&
b37e933a
PM
329 sh->vtag != ct->proto.sctp.vtag[!dir])
330 goto out_unlock;
9fb9cbb1
YK
331 } else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
332 /* Sec 8.5.1 (C) */
8528819a
PM
333 if (sh->vtag != ct->proto.sctp.vtag[dir] &&
334 sh->vtag != ct->proto.sctp.vtag[!dir] &&
9b1c2cfd 335 sch->flags & SCTP_CHUNK_FLAG_T)
b37e933a 336 goto out_unlock;
9fb9cbb1
YK
337 } else if (sch->type == SCTP_CID_COOKIE_ECHO) {
338 /* Sec 8.5.1 (D) */
b37e933a
PM
339 if (sh->vtag != ct->proto.sctp.vtag[dir])
340 goto out_unlock;
9fb9cbb1
YK
341 }
342
efe9f68a
PM
343 old_state = ct->proto.sctp.state;
344 new_state = sctp_new_state(dir, old_state, sch->type);
9fb9cbb1
YK
345
346 /* Invalid */
efe9f68a 347 if (new_state == SCTP_CONNTRACK_MAX) {
0d53778e
PM
348 pr_debug("nf_conntrack_sctp: Invalid dir=%i ctype=%u "
349 "conntrack=%u\n",
efe9f68a 350 dir, sch->type, old_state);
b37e933a 351 goto out_unlock;
9fb9cbb1
YK
352 }
353
354 /* If it is an INIT or an INIT ACK note down the vtag */
5447d477
PM
355 if (sch->type == SCTP_CID_INIT ||
356 sch->type == SCTP_CID_INIT_ACK) {
9fb9cbb1
YK
357 sctp_inithdr_t _inithdr, *ih;
358
359 ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
601e68e1 360 sizeof(_inithdr), &_inithdr);
b37e933a
PM
361 if (ih == NULL)
362 goto out_unlock;
0d53778e 363 pr_debug("Setting vtag %x for dir %d\n",
8528819a
PM
364 ih->init_tag, !dir);
365 ct->proto.sctp.vtag[!dir] = ih->init_tag;
9fb9cbb1
YK
366 }
367
efe9f68a
PM
368 ct->proto.sctp.state = new_state;
369 if (old_state != new_state)
9fb9cbb1 370 nf_conntrack_event_cache(IPCT_PROTOINFO, skb);
9fb9cbb1 371 }
4a64830a 372 write_unlock_bh(&sctp_lock);
9fb9cbb1 373
86c0bf40 374 nf_ct_refresh_acct(ct, ctinfo, skb, sctp_timeouts[new_state]);
9fb9cbb1 375
efe9f68a 376 if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED &&
8528819a 377 dir == IP_CT_DIR_REPLY &&
efe9f68a 378 new_state == SCTP_CONNTRACK_ESTABLISHED) {
0d53778e 379 pr_debug("Setting assured bit\n");
112f35c9 380 set_bit(IPS_ASSURED_BIT, &ct->status);
9fb9cbb1
YK
381 nf_conntrack_event_cache(IPCT_STATUS, skb);
382 }
383
384 return NF_ACCEPT;
b37e933a
PM
385
386out_unlock:
387 write_unlock_bh(&sctp_lock);
388out:
389 return -NF_ACCEPT;
9fb9cbb1
YK
390}
391
392/* Called when a new connection for this protocol found. */
112f35c9 393static int sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
9fb9cbb1
YK
394 unsigned int dataoff)
395{
efe9f68a 396 enum sctp_conntrack new_state;
9fb9cbb1
YK
397 sctp_sctphdr_t _sctph, *sh;
398 sctp_chunkhdr_t _sch, *sch;
399 u_int32_t offset, count;
35c6d3cb 400 unsigned long map[256 / sizeof(unsigned long)] = { 0 };
9fb9cbb1 401
9fb9cbb1
YK
402 sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
403 if (sh == NULL)
404 return 0;
405
112f35c9 406 if (do_basic_checks(ct, skb, dataoff, map) != 0)
9fb9cbb1
YK
407 return 0;
408
409 /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
35c6d3cb
PM
410 if (test_bit(SCTP_CID_ABORT, map) ||
411 test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) ||
412 test_bit(SCTP_CID_COOKIE_ACK, map))
9fb9cbb1 413 return 0;
9fb9cbb1 414
efe9f68a 415 new_state = SCTP_CONNTRACK_MAX;
9fb9cbb1
YK
416 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
417 /* Don't need lock here: this conntrack not in circulation yet */
efe9f68a
PM
418 new_state = sctp_new_state(IP_CT_DIR_ORIGINAL,
419 SCTP_CONNTRACK_NONE, sch->type);
9fb9cbb1
YK
420
421 /* Invalid: delete conntrack */
efe9f68a
PM
422 if (new_state == SCTP_CONNTRACK_NONE ||
423 new_state == SCTP_CONNTRACK_MAX) {
0d53778e 424 pr_debug("nf_conntrack_sctp: invalid new deleting.\n");
9fb9cbb1
YK
425 return 0;
426 }
427
428 /* Copy the vtag into the state info */
429 if (sch->type == SCTP_CID_INIT) {
430 if (sh->vtag == 0) {
431 sctp_inithdr_t _inithdr, *ih;
432
433 ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
601e68e1 434 sizeof(_inithdr), &_inithdr);
9fb9cbb1
YK
435 if (ih == NULL)
436 return 0;
437
0d53778e
PM
438 pr_debug("Setting vtag %x for new conn\n",
439 ih->init_tag);
9fb9cbb1 440
112f35c9 441 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] =
9fb9cbb1
YK
442 ih->init_tag;
443 } else {
444 /* Sec 8.5.1 (A) */
445 return 0;
446 }
447 }
448 /* If it is a shutdown ack OOTB packet, we expect a return
449 shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
450 else {
0d53778e
PM
451 pr_debug("Setting vtag %x for new conn OOTB\n",
452 sh->vtag);
112f35c9 453 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
9fb9cbb1
YK
454 }
455
efe9f68a 456 ct->proto.sctp.state = new_state;
9fb9cbb1
YK
457 }
458
459 return 1;
460}
461
9fb9cbb1 462#ifdef CONFIG_SYSCTL
933a41e7
PM
463static unsigned int sctp_sysctl_table_users;
464static struct ctl_table_header *sctp_sysctl_header;
465static struct ctl_table sctp_sysctl_table[] = {
9fb9cbb1 466 {
9fb9cbb1 467 .procname = "nf_conntrack_sctp_timeout_closed",
86c0bf40 468 .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
9fb9cbb1
YK
469 .maxlen = sizeof(unsigned int),
470 .mode = 0644,
471 .proc_handler = &proc_dointvec_jiffies,
472 },
473 {
9fb9cbb1 474 .procname = "nf_conntrack_sctp_timeout_cookie_wait",
86c0bf40 475 .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
9fb9cbb1
YK
476 .maxlen = sizeof(unsigned int),
477 .mode = 0644,
478 .proc_handler = &proc_dointvec_jiffies,
479 },
480 {
9fb9cbb1 481 .procname = "nf_conntrack_sctp_timeout_cookie_echoed",
86c0bf40 482 .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
9fb9cbb1
YK
483 .maxlen = sizeof(unsigned int),
484 .mode = 0644,
485 .proc_handler = &proc_dointvec_jiffies,
486 },
487 {
9fb9cbb1 488 .procname = "nf_conntrack_sctp_timeout_established",
86c0bf40 489 .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
9fb9cbb1
YK
490 .maxlen = sizeof(unsigned int),
491 .mode = 0644,
492 .proc_handler = &proc_dointvec_jiffies,
493 },
494 {
9fb9cbb1 495 .procname = "nf_conntrack_sctp_timeout_shutdown_sent",
86c0bf40 496 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
9fb9cbb1
YK
497 .maxlen = sizeof(unsigned int),
498 .mode = 0644,
499 .proc_handler = &proc_dointvec_jiffies,
500 },
501 {
9fb9cbb1 502 .procname = "nf_conntrack_sctp_timeout_shutdown_recd",
86c0bf40 503 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
9fb9cbb1
YK
504 .maxlen = sizeof(unsigned int),
505 .mode = 0644,
506 .proc_handler = &proc_dointvec_jiffies,
507 },
508 {
9fb9cbb1 509 .procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent",
86c0bf40 510 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
9fb9cbb1
YK
511 .maxlen = sizeof(unsigned int),
512 .mode = 0644,
513 .proc_handler = &proc_dointvec_jiffies,
514 },
9fb9cbb1 515 {
933a41e7
PM
516 .ctl_name = 0
517 }
9fb9cbb1 518};
a999e683
PM
519
520#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
521static struct ctl_table sctp_compat_sysctl_table[] = {
522 {
a999e683 523 .procname = "ip_conntrack_sctp_timeout_closed",
86c0bf40 524 .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
a999e683
PM
525 .maxlen = sizeof(unsigned int),
526 .mode = 0644,
527 .proc_handler = &proc_dointvec_jiffies,
528 },
529 {
a999e683 530 .procname = "ip_conntrack_sctp_timeout_cookie_wait",
86c0bf40 531 .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
a999e683
PM
532 .maxlen = sizeof(unsigned int),
533 .mode = 0644,
534 .proc_handler = &proc_dointvec_jiffies,
535 },
536 {
a999e683 537 .procname = "ip_conntrack_sctp_timeout_cookie_echoed",
86c0bf40 538 .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
a999e683
PM
539 .maxlen = sizeof(unsigned int),
540 .mode = 0644,
541 .proc_handler = &proc_dointvec_jiffies,
542 },
543 {
a999e683 544 .procname = "ip_conntrack_sctp_timeout_established",
86c0bf40 545 .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
a999e683
PM
546 .maxlen = sizeof(unsigned int),
547 .mode = 0644,
548 .proc_handler = &proc_dointvec_jiffies,
549 },
550 {
a999e683 551 .procname = "ip_conntrack_sctp_timeout_shutdown_sent",
86c0bf40 552 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
a999e683
PM
553 .maxlen = sizeof(unsigned int),
554 .mode = 0644,
555 .proc_handler = &proc_dointvec_jiffies,
556 },
557 {
a999e683 558 .procname = "ip_conntrack_sctp_timeout_shutdown_recd",
86c0bf40 559 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
a999e683
PM
560 .maxlen = sizeof(unsigned int),
561 .mode = 0644,
562 .proc_handler = &proc_dointvec_jiffies,
563 },
564 {
a999e683 565 .procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent",
86c0bf40 566 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
a999e683
PM
567 .maxlen = sizeof(unsigned int),
568 .mode = 0644,
569 .proc_handler = &proc_dointvec_jiffies,
570 },
571 {
572 .ctl_name = 0
573 }
574};
575#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
933a41e7 576#endif
9fb9cbb1 577
61075af5 578static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
933a41e7
PM
579 .l3proto = PF_INET,
580 .l4proto = IPPROTO_SCTP,
581 .name = "sctp",
582 .pkt_to_tuple = sctp_pkt_to_tuple,
583 .invert_tuple = sctp_invert_tuple,
584 .print_tuple = sctp_print_tuple,
585 .print_conntrack = sctp_print_conntrack,
586 .packet = sctp_packet,
587 .new = sctp_new,
588 .me = THIS_MODULE,
c7212e9d
PNA
589#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
590 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
591 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
592 .nla_policy = nf_ct_port_nla_policy,
593#endif
933a41e7
PM
594#ifdef CONFIG_SYSCTL
595 .ctl_table_users = &sctp_sysctl_table_users,
596 .ctl_table_header = &sctp_sysctl_header,
597 .ctl_table = sctp_sysctl_table,
a999e683
PM
598#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
599 .ctl_compat_table = sctp_compat_sysctl_table,
600#endif
933a41e7 601#endif
9fb9cbb1
YK
602};
603
61075af5 604static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
933a41e7
PM
605 .l3proto = PF_INET6,
606 .l4proto = IPPROTO_SCTP,
607 .name = "sctp",
608 .pkt_to_tuple = sctp_pkt_to_tuple,
609 .invert_tuple = sctp_invert_tuple,
610 .print_tuple = sctp_print_tuple,
611 .print_conntrack = sctp_print_conntrack,
612 .packet = sctp_packet,
613 .new = sctp_new,
614 .me = THIS_MODULE,
c7212e9d
PNA
615#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
616 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
617 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
618 .nla_policy = nf_ct_port_nla_policy,
619#endif
933a41e7
PM
620#ifdef CONFIG_SYSCTL
621 .ctl_table_users = &sctp_sysctl_table_users,
622 .ctl_table_header = &sctp_sysctl_header,
623 .ctl_table = sctp_sysctl_table,
9fb9cbb1 624#endif
933a41e7 625};
9fb9cbb1 626
2f0d2f10 627static int __init nf_conntrack_proto_sctp_init(void)
9fb9cbb1
YK
628{
629 int ret;
630
605dcad6 631 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp4);
9fb9cbb1 632 if (ret) {
605dcad6 633 printk("nf_conntrack_l4proto_sctp4: protocol register failed\n");
9fb9cbb1
YK
634 goto out;
635 }
605dcad6 636 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp6);
9fb9cbb1 637 if (ret) {
605dcad6 638 printk("nf_conntrack_l4proto_sctp6: protocol register failed\n");
9fb9cbb1
YK
639 goto cleanup_sctp4;
640 }
641
9fb9cbb1
YK
642 return ret;
643
9fb9cbb1 644 cleanup_sctp4:
605dcad6 645 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
9fb9cbb1 646 out:
9fb9cbb1
YK
647 return ret;
648}
649
2f0d2f10 650static void __exit nf_conntrack_proto_sctp_fini(void)
9fb9cbb1 651{
605dcad6
MJ
652 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
653 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
9fb9cbb1
YK
654}
655
65b4b4e8
AM
656module_init(nf_conntrack_proto_sctp_init);
657module_exit(nf_conntrack_proto_sctp_fini);
9fb9cbb1
YK
658
659MODULE_LICENSE("GPL");
660MODULE_AUTHOR("Kiran Kumar Immidi");
661MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
d2483dde 662MODULE_ALIAS("ip_conntrack_proto_sctp");