netfilter: xt_socket: added new revision of the 'socket' match supporting flags
[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
c88130bc 28/* Protects ct->proto.sctp */
9fb9cbb1
YK
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
12c33aa2 36static const char *const sctp_conntrack_names[] = {
9fb9cbb1
YK
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
09f263cd
JE
133static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
134 struct nf_conntrack_tuple *tuple)
9fb9cbb1 135{
12c33aa2
JE
136 const struct sctphdr *hp;
137 struct sctphdr _hdr;
9fb9cbb1 138
9fb9cbb1
YK
139 /* Actually only need first 8 bytes. */
140 hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
141 if (hp == NULL)
09f263cd 142 return false;
9fb9cbb1
YK
143
144 tuple->src.u.sctp.port = hp->source;
145 tuple->dst.u.sctp.port = hp->dest;
09f263cd 146 return true;
9fb9cbb1
YK
147}
148
09f263cd
JE
149static bool sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
150 const struct nf_conntrack_tuple *orig)
9fb9cbb1 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;
09f263cd 154 return true;
9fb9cbb1
YK
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,
76108cea 290 u_int8_t pf,
9fb9cbb1
YK
291 unsigned int hooknum)
292{
efe9f68a 293 enum sctp_conntrack new_state, old_state;
8528819a 294 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
12c33aa2
JE
295 const struct sctphdr *sh;
296 struct sctphdr _sctph;
297 const struct sctp_chunkhdr *sch;
298 struct sctp_chunkhdr _sch;
9fb9cbb1 299 u_int32_t offset, count;
35c6d3cb 300 unsigned long map[256 / sizeof(unsigned long)] = { 0 };
9fb9cbb1 301
9fb9cbb1
YK
302 sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
303 if (sh == NULL)
b37e933a 304 goto out;
9fb9cbb1 305
112f35c9 306 if (do_basic_checks(ct, skb, dataoff, map) != 0)
b37e933a 307 goto out;
9fb9cbb1
YK
308
309 /* Check the verification tag (Sec 8.5) */
35c6d3cb
PM
310 if (!test_bit(SCTP_CID_INIT, map) &&
311 !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) &&
312 !test_bit(SCTP_CID_COOKIE_ECHO, map) &&
313 !test_bit(SCTP_CID_ABORT, map) &&
314 !test_bit(SCTP_CID_SHUTDOWN_ACK, map) &&
8528819a 315 sh->vtag != ct->proto.sctp.vtag[dir]) {
0d53778e 316 pr_debug("Verification tag check failed\n");
b37e933a 317 goto out;
9fb9cbb1
YK
318 }
319
328bd899 320 old_state = new_state = SCTP_CONNTRACK_NONE;
4a64830a 321 write_lock_bh(&sctp_lock);
9fb9cbb1 322 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
9fb9cbb1
YK
323 /* Special cases of Verification tag check (Sec 8.5.1) */
324 if (sch->type == SCTP_CID_INIT) {
325 /* Sec 8.5.1 (A) */
b37e933a
PM
326 if (sh->vtag != 0)
327 goto out_unlock;
9fb9cbb1
YK
328 } else if (sch->type == SCTP_CID_ABORT) {
329 /* Sec 8.5.1 (B) */
8528819a 330 if (sh->vtag != ct->proto.sctp.vtag[dir] &&
b37e933a
PM
331 sh->vtag != ct->proto.sctp.vtag[!dir])
332 goto out_unlock;
9fb9cbb1
YK
333 } else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
334 /* Sec 8.5.1 (C) */
8528819a
PM
335 if (sh->vtag != ct->proto.sctp.vtag[dir] &&
336 sh->vtag != ct->proto.sctp.vtag[!dir] &&
9b1c2cfd 337 sch->flags & SCTP_CHUNK_FLAG_T)
b37e933a 338 goto out_unlock;
9fb9cbb1
YK
339 } else if (sch->type == SCTP_CID_COOKIE_ECHO) {
340 /* Sec 8.5.1 (D) */
b37e933a
PM
341 if (sh->vtag != ct->proto.sctp.vtag[dir])
342 goto out_unlock;
9fb9cbb1
YK
343 }
344
efe9f68a
PM
345 old_state = ct->proto.sctp.state;
346 new_state = sctp_new_state(dir, old_state, sch->type);
9fb9cbb1
YK
347
348 /* Invalid */
efe9f68a 349 if (new_state == SCTP_CONNTRACK_MAX) {
0d53778e
PM
350 pr_debug("nf_conntrack_sctp: Invalid dir=%i ctype=%u "
351 "conntrack=%u\n",
efe9f68a 352 dir, sch->type, old_state);
b37e933a 353 goto out_unlock;
9fb9cbb1
YK
354 }
355
356 /* If it is an INIT or an INIT ACK note down the vtag */
5447d477
PM
357 if (sch->type == SCTP_CID_INIT ||
358 sch->type == SCTP_CID_INIT_ACK) {
9fb9cbb1
YK
359 sctp_inithdr_t _inithdr, *ih;
360
361 ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
601e68e1 362 sizeof(_inithdr), &_inithdr);
b37e933a
PM
363 if (ih == NULL)
364 goto out_unlock;
0d53778e 365 pr_debug("Setting vtag %x for dir %d\n",
8528819a
PM
366 ih->init_tag, !dir);
367 ct->proto.sctp.vtag[!dir] = ih->init_tag;
9fb9cbb1
YK
368 }
369
efe9f68a
PM
370 ct->proto.sctp.state = new_state;
371 if (old_state != new_state)
a71996fc 372 nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
9fb9cbb1 373 }
4a64830a 374 write_unlock_bh(&sctp_lock);
9fb9cbb1 375
86c0bf40 376 nf_ct_refresh_acct(ct, ctinfo, skb, sctp_timeouts[new_state]);
9fb9cbb1 377
efe9f68a 378 if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED &&
8528819a 379 dir == IP_CT_DIR_REPLY &&
efe9f68a 380 new_state == SCTP_CONNTRACK_ESTABLISHED) {
0d53778e 381 pr_debug("Setting assured bit\n");
112f35c9 382 set_bit(IPS_ASSURED_BIT, &ct->status);
a71996fc 383 nf_conntrack_event_cache(IPCT_STATUS, ct);
9fb9cbb1
YK
384 }
385
386 return NF_ACCEPT;
b37e933a
PM
387
388out_unlock:
389 write_unlock_bh(&sctp_lock);
390out:
391 return -NF_ACCEPT;
9fb9cbb1
YK
392}
393
394/* Called when a new connection for this protocol found. */
09f263cd
JE
395static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
396 unsigned int dataoff)
9fb9cbb1 397{
efe9f68a 398 enum sctp_conntrack new_state;
12c33aa2
JE
399 const struct sctphdr *sh;
400 struct sctphdr _sctph;
401 const struct sctp_chunkhdr *sch;
402 struct sctp_chunkhdr _sch;
9fb9cbb1 403 u_int32_t offset, count;
35c6d3cb 404 unsigned long map[256 / sizeof(unsigned long)] = { 0 };
9fb9cbb1 405
9fb9cbb1
YK
406 sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
407 if (sh == NULL)
09f263cd 408 return false;
9fb9cbb1 409
112f35c9 410 if (do_basic_checks(ct, skb, dataoff, map) != 0)
09f263cd 411 return false;
9fb9cbb1
YK
412
413 /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
35c6d3cb
PM
414 if (test_bit(SCTP_CID_ABORT, map) ||
415 test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) ||
416 test_bit(SCTP_CID_COOKIE_ACK, map))
09f263cd 417 return false;
9fb9cbb1 418
efe9f68a 419 new_state = SCTP_CONNTRACK_MAX;
9fb9cbb1
YK
420 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
421 /* Don't need lock here: this conntrack not in circulation yet */
efe9f68a
PM
422 new_state = sctp_new_state(IP_CT_DIR_ORIGINAL,
423 SCTP_CONNTRACK_NONE, sch->type);
9fb9cbb1
YK
424
425 /* Invalid: delete conntrack */
efe9f68a
PM
426 if (new_state == SCTP_CONNTRACK_NONE ||
427 new_state == SCTP_CONNTRACK_MAX) {
0d53778e 428 pr_debug("nf_conntrack_sctp: invalid new deleting.\n");
09f263cd 429 return false;
9fb9cbb1
YK
430 }
431
432 /* Copy the vtag into the state info */
433 if (sch->type == SCTP_CID_INIT) {
434 if (sh->vtag == 0) {
435 sctp_inithdr_t _inithdr, *ih;
436
437 ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
601e68e1 438 sizeof(_inithdr), &_inithdr);
9fb9cbb1 439 if (ih == NULL)
09f263cd 440 return false;
9fb9cbb1 441
0d53778e
PM
442 pr_debug("Setting vtag %x for new conn\n",
443 ih->init_tag);
9fb9cbb1 444
112f35c9 445 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] =
9fb9cbb1
YK
446 ih->init_tag;
447 } else {
448 /* Sec 8.5.1 (A) */
09f263cd 449 return false;
9fb9cbb1
YK
450 }
451 }
452 /* If it is a shutdown ack OOTB packet, we expect a return
453 shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
454 else {
0d53778e
PM
455 pr_debug("Setting vtag %x for new conn OOTB\n",
456 sh->vtag);
112f35c9 457 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
9fb9cbb1
YK
458 }
459
efe9f68a 460 ct->proto.sctp.state = new_state;
9fb9cbb1
YK
461 }
462
09f263cd 463 return true;
9fb9cbb1
YK
464}
465
a258860e
PNA
466#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
467
468#include <linux/netfilter/nfnetlink.h>
469#include <linux/netfilter/nfnetlink_conntrack.h>
470
471static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
472 const struct nf_conn *ct)
473{
474 struct nlattr *nest_parms;
475
476 read_lock_bh(&sctp_lock);
477 nest_parms = nla_nest_start(skb, CTA_PROTOINFO_SCTP | NLA_F_NESTED);
478 if (!nest_parms)
479 goto nla_put_failure;
480
481 NLA_PUT_U8(skb, CTA_PROTOINFO_SCTP_STATE, ct->proto.sctp.state);
482
483 NLA_PUT_BE32(skb,
484 CTA_PROTOINFO_SCTP_VTAG_ORIGINAL,
5547cd0a 485 ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL]);
a258860e
PNA
486
487 NLA_PUT_BE32(skb,
488 CTA_PROTOINFO_SCTP_VTAG_REPLY,
5547cd0a 489 ct->proto.sctp.vtag[IP_CT_DIR_REPLY]);
a258860e
PNA
490
491 read_unlock_bh(&sctp_lock);
492
493 nla_nest_end(skb, nest_parms);
494
495 return 0;
496
497nla_put_failure:
498 read_unlock_bh(&sctp_lock);
499 return -1;
500}
501
502static const struct nla_policy sctp_nla_policy[CTA_PROTOINFO_SCTP_MAX+1] = {
503 [CTA_PROTOINFO_SCTP_STATE] = { .type = NLA_U8 },
504 [CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] = { .type = NLA_U32 },
505 [CTA_PROTOINFO_SCTP_VTAG_REPLY] = { .type = NLA_U32 },
506};
507
508static int nlattr_to_sctp(struct nlattr *cda[], struct nf_conn *ct)
509{
510 struct nlattr *attr = cda[CTA_PROTOINFO_SCTP];
511 struct nlattr *tb[CTA_PROTOINFO_SCTP_MAX+1];
512 int err;
513
514 /* updates may not contain the internal protocol info, skip parsing */
515 if (!attr)
516 return 0;
517
518 err = nla_parse_nested(tb,
519 CTA_PROTOINFO_SCTP_MAX,
520 attr,
521 sctp_nla_policy);
522 if (err < 0)
523 return err;
524
525 if (!tb[CTA_PROTOINFO_SCTP_STATE] ||
526 !tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] ||
527 !tb[CTA_PROTOINFO_SCTP_VTAG_REPLY])
528 return -EINVAL;
529
530 write_lock_bh(&sctp_lock);
531 ct->proto.sctp.state = nla_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]);
532 ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] =
5547cd0a 533 nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]);
a258860e 534 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] =
5547cd0a 535 nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]);
a258860e
PNA
536 write_unlock_bh(&sctp_lock);
537
538 return 0;
539}
a400c30e
HE
540
541static int sctp_nlattr_size(void)
542{
543 return nla_total_size(0) /* CTA_PROTOINFO_SCTP */
544 + nla_policy_len(sctp_nla_policy, CTA_PROTOINFO_SCTP_MAX + 1);
545}
a258860e
PNA
546#endif
547
9fb9cbb1 548#ifdef CONFIG_SYSCTL
933a41e7
PM
549static unsigned int sctp_sysctl_table_users;
550static struct ctl_table_header *sctp_sysctl_header;
551static struct ctl_table sctp_sysctl_table[] = {
9fb9cbb1 552 {
9fb9cbb1 553 .procname = "nf_conntrack_sctp_timeout_closed",
86c0bf40 554 .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
9fb9cbb1
YK
555 .maxlen = sizeof(unsigned int),
556 .mode = 0644,
6d9f239a 557 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1
YK
558 },
559 {
9fb9cbb1 560 .procname = "nf_conntrack_sctp_timeout_cookie_wait",
86c0bf40 561 .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
9fb9cbb1
YK
562 .maxlen = sizeof(unsigned int),
563 .mode = 0644,
6d9f239a 564 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1
YK
565 },
566 {
9fb9cbb1 567 .procname = "nf_conntrack_sctp_timeout_cookie_echoed",
86c0bf40 568 .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
9fb9cbb1
YK
569 .maxlen = sizeof(unsigned int),
570 .mode = 0644,
6d9f239a 571 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1
YK
572 },
573 {
9fb9cbb1 574 .procname = "nf_conntrack_sctp_timeout_established",
86c0bf40 575 .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
9fb9cbb1
YK
576 .maxlen = sizeof(unsigned int),
577 .mode = 0644,
6d9f239a 578 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1
YK
579 },
580 {
9fb9cbb1 581 .procname = "nf_conntrack_sctp_timeout_shutdown_sent",
86c0bf40 582 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
9fb9cbb1
YK
583 .maxlen = sizeof(unsigned int),
584 .mode = 0644,
6d9f239a 585 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1
YK
586 },
587 {
9fb9cbb1 588 .procname = "nf_conntrack_sctp_timeout_shutdown_recd",
86c0bf40 589 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
9fb9cbb1
YK
590 .maxlen = sizeof(unsigned int),
591 .mode = 0644,
6d9f239a 592 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1
YK
593 },
594 {
9fb9cbb1 595 .procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent",
86c0bf40 596 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
9fb9cbb1
YK
597 .maxlen = sizeof(unsigned int),
598 .mode = 0644,
6d9f239a 599 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1 600 },
9fb9cbb1 601 {
933a41e7
PM
602 .ctl_name = 0
603 }
9fb9cbb1 604};
a999e683
PM
605
606#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
607static struct ctl_table sctp_compat_sysctl_table[] = {
608 {
a999e683 609 .procname = "ip_conntrack_sctp_timeout_closed",
86c0bf40 610 .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
a999e683
PM
611 .maxlen = sizeof(unsigned int),
612 .mode = 0644,
6d9f239a 613 .proc_handler = proc_dointvec_jiffies,
a999e683
PM
614 },
615 {
a999e683 616 .procname = "ip_conntrack_sctp_timeout_cookie_wait",
86c0bf40 617 .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
a999e683
PM
618 .maxlen = sizeof(unsigned int),
619 .mode = 0644,
6d9f239a 620 .proc_handler = proc_dointvec_jiffies,
a999e683
PM
621 },
622 {
a999e683 623 .procname = "ip_conntrack_sctp_timeout_cookie_echoed",
86c0bf40 624 .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
a999e683
PM
625 .maxlen = sizeof(unsigned int),
626 .mode = 0644,
6d9f239a 627 .proc_handler = proc_dointvec_jiffies,
a999e683
PM
628 },
629 {
a999e683 630 .procname = "ip_conntrack_sctp_timeout_established",
86c0bf40 631 .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
a999e683
PM
632 .maxlen = sizeof(unsigned int),
633 .mode = 0644,
6d9f239a 634 .proc_handler = proc_dointvec_jiffies,
a999e683
PM
635 },
636 {
a999e683 637 .procname = "ip_conntrack_sctp_timeout_shutdown_sent",
86c0bf40 638 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
a999e683
PM
639 .maxlen = sizeof(unsigned int),
640 .mode = 0644,
6d9f239a 641 .proc_handler = proc_dointvec_jiffies,
a999e683
PM
642 },
643 {
a999e683 644 .procname = "ip_conntrack_sctp_timeout_shutdown_recd",
86c0bf40 645 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
a999e683
PM
646 .maxlen = sizeof(unsigned int),
647 .mode = 0644,
6d9f239a 648 .proc_handler = proc_dointvec_jiffies,
a999e683
PM
649 },
650 {
a999e683 651 .procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent",
86c0bf40 652 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
a999e683
PM
653 .maxlen = sizeof(unsigned int),
654 .mode = 0644,
6d9f239a 655 .proc_handler = proc_dointvec_jiffies,
a999e683
PM
656 },
657 {
658 .ctl_name = 0
659 }
660};
661#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
933a41e7 662#endif
9fb9cbb1 663
61075af5 664static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
933a41e7
PM
665 .l3proto = PF_INET,
666 .l4proto = IPPROTO_SCTP,
667 .name = "sctp",
668 .pkt_to_tuple = sctp_pkt_to_tuple,
669 .invert_tuple = sctp_invert_tuple,
670 .print_tuple = sctp_print_tuple,
671 .print_conntrack = sctp_print_conntrack,
672 .packet = sctp_packet,
673 .new = sctp_new,
674 .me = THIS_MODULE,
c7212e9d 675#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
a258860e 676 .to_nlattr = sctp_to_nlattr,
a400c30e 677 .nlattr_size = sctp_nlattr_size,
a258860e 678 .from_nlattr = nlattr_to_sctp,
c7212e9d 679 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
a400c30e 680 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
c7212e9d
PNA
681 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
682 .nla_policy = nf_ct_port_nla_policy,
683#endif
933a41e7
PM
684#ifdef CONFIG_SYSCTL
685 .ctl_table_users = &sctp_sysctl_table_users,
686 .ctl_table_header = &sctp_sysctl_header,
687 .ctl_table = sctp_sysctl_table,
a999e683
PM
688#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
689 .ctl_compat_table = sctp_compat_sysctl_table,
690#endif
933a41e7 691#endif
9fb9cbb1
YK
692};
693
61075af5 694static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
933a41e7
PM
695 .l3proto = PF_INET6,
696 .l4proto = IPPROTO_SCTP,
697 .name = "sctp",
698 .pkt_to_tuple = sctp_pkt_to_tuple,
699 .invert_tuple = sctp_invert_tuple,
700 .print_tuple = sctp_print_tuple,
701 .print_conntrack = sctp_print_conntrack,
702 .packet = sctp_packet,
703 .new = sctp_new,
704 .me = THIS_MODULE,
c7212e9d 705#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
a258860e 706 .to_nlattr = sctp_to_nlattr,
a400c30e 707 .nlattr_size = sctp_nlattr_size,
a258860e 708 .from_nlattr = nlattr_to_sctp,
c7212e9d 709 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
a400c30e 710 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
c7212e9d
PNA
711 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
712 .nla_policy = nf_ct_port_nla_policy,
713#endif
933a41e7
PM
714#ifdef CONFIG_SYSCTL
715 .ctl_table_users = &sctp_sysctl_table_users,
716 .ctl_table_header = &sctp_sysctl_header,
717 .ctl_table = sctp_sysctl_table,
9fb9cbb1 718#endif
933a41e7 719};
9fb9cbb1 720
2f0d2f10 721static int __init nf_conntrack_proto_sctp_init(void)
9fb9cbb1
YK
722{
723 int ret;
724
605dcad6 725 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp4);
9fb9cbb1 726 if (ret) {
605dcad6 727 printk("nf_conntrack_l4proto_sctp4: protocol register failed\n");
9fb9cbb1
YK
728 goto out;
729 }
605dcad6 730 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp6);
9fb9cbb1 731 if (ret) {
605dcad6 732 printk("nf_conntrack_l4proto_sctp6: protocol register failed\n");
9fb9cbb1
YK
733 goto cleanup_sctp4;
734 }
735
9fb9cbb1
YK
736 return ret;
737
9fb9cbb1 738 cleanup_sctp4:
605dcad6 739 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
9fb9cbb1 740 out:
9fb9cbb1
YK
741 return ret;
742}
743
2f0d2f10 744static void __exit nf_conntrack_proto_sctp_fini(void)
9fb9cbb1 745{
605dcad6
MJ
746 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
747 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
9fb9cbb1
YK
748}
749
65b4b4e8
AM
750module_init(nf_conntrack_proto_sctp_init);
751module_exit(nf_conntrack_proto_sctp_fini);
9fb9cbb1
YK
752
753MODULE_LICENSE("GPL");
754MODULE_AUTHOR("Kiran Kumar Immidi");
755MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
d2483dde 756MODULE_ALIAS("ip_conntrack_proto_sctp");