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