1
2
3
4
5
6
7
8
9
10
11
12#include <linux/types.h>
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>
21#include <linux/spinlock.h>
22#include <linux/interrupt.h>
23
24#include <net/netfilter/nf_conntrack.h>
25#include <net/netfilter/nf_conntrack_l4proto.h>
26#include <net/netfilter/nf_conntrack_ecache.h>
27
28
29static DEFINE_RWLOCK(sctp_lock);
30
31
32
33
34
35
36static const char *const 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
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};
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = {
105 {
106
107
108 {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA},
109 {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
110 {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
111 {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA},
112 {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA},
113 {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
114 {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},
115 {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},
116 {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL}
117 },
118 {
119
120
121 {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
122 {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
123 {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
124 {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA},
125 {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA},
126 {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA},
127 {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},
128 {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA},
129 {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL}
130 }
131};
132
133static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
134 struct nf_conntrack_tuple *tuple)
135{
136 const struct sctphdr *hp;
137 struct sctphdr _hdr;
138
139
140 hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
141 if (hp == NULL)
142 return false;
143
144 tuple->src.u.sctp.port = hp->source;
145 tuple->dst.u.sctp.port = hp->dest;
146 return true;
147}
148
149static bool sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
150 const struct nf_conntrack_tuple *orig)
151{
152 tuple->src.u.sctp.port = orig->dst.u.sctp.port;
153 tuple->dst.u.sctp.port = orig->src.u.sctp.port;
154 return true;
155}
156
157
158static int sctp_print_tuple(struct seq_file *s,
159 const struct nf_conntrack_tuple *tuple)
160{
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
167static int sctp_print_conntrack(struct seq_file *s, const struct nf_conn *ct)
168{
169 enum sctp_conntrack state;
170
171 read_lock_bh(&sctp_lock);
172 state = ct->proto.sctp.state;
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) \
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)++)
183
184
185static int do_basic_checks(struct nf_conn *ct,
186 const struct sk_buff *skb,
187 unsigned int dataoff,
188 unsigned long *map)
189{
190 u_int32_t offset, count;
191 sctp_chunkhdr_t _sch, *sch;
192 int flag;
193
194 flag = 0;
195
196 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
197 pr_debug("Chunk Num: %d Type: %d\n", count, sch->type);
198
199 if (sch->type == SCTP_CID_INIT ||
200 sch->type == SCTP_CID_INIT_ACK ||
201 sch->type == SCTP_CID_SHUTDOWN_COMPLETE)
202 flag = 1;
203
204
205
206
207
208
209 if (((sch->type == SCTP_CID_COOKIE_ACK ||
210 sch->type == SCTP_CID_COOKIE_ECHO ||
211 flag) &&
212 count != 0) || !sch->length) {
213 pr_debug("Basic checks failed\n");
214 return 1;
215 }
216
217 if (map)
218 set_bit(sch->type, map);
219 }
220
221 pr_debug("Basic checks passed\n");
222 return count == 0;
223}
224
225static int sctp_new_state(enum ip_conntrack_dir dir,
226 enum sctp_conntrack cur_state,
227 int chunk_type)
228{
229 int i;
230
231 pr_debug("Chunk type: %d\n", chunk_type);
232
233 switch (chunk_type) {
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
272
273 pr_debug("Unknown chunk type, Will stay in %s\n",
274 sctp_conntrack_names[cur_state]);
275 return cur_state;
276 }
277
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]]);
281
282 return sctp_conntracks[dir][i][cur_state];
283}
284
285
286static int sctp_packet(struct nf_conn *ct,
287 const struct sk_buff *skb,
288 unsigned int dataoff,
289 enum ip_conntrack_info ctinfo,
290 u_int8_t pf,
291 unsigned int hooknum)
292{
293 enum sctp_conntrack new_state, old_state;
294 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
295 const struct sctphdr *sh;
296 struct sctphdr _sctph;
297 const struct sctp_chunkhdr *sch;
298 struct sctp_chunkhdr _sch;
299 u_int32_t offset, count;
300 unsigned long map[256 / sizeof(unsigned long)] = { 0 };
301
302 sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
303 if (sh == NULL)
304 goto out;
305
306 if (do_basic_checks(ct, skb, dataoff, map) != 0)
307 goto out;
308
309
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) &&
315 sh->vtag != ct->proto.sctp.vtag[dir]) {
316 pr_debug("Verification tag check failed\n");
317 goto out;
318 }
319
320 old_state = new_state = SCTP_CONNTRACK_NONE;
321 write_lock_bh(&sctp_lock);
322 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
323
324 if (sch->type == SCTP_CID_INIT) {
325
326 if (sh->vtag != 0)
327 goto out_unlock;
328 } else if (sch->type == SCTP_CID_ABORT) {
329
330 if (sh->vtag != ct->proto.sctp.vtag[dir] &&
331 sh->vtag != ct->proto.sctp.vtag[!dir])
332 goto out_unlock;
333 } else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
334
335 if (sh->vtag != ct->proto.sctp.vtag[dir] &&
336 sh->vtag != ct->proto.sctp.vtag[!dir] &&
337 sch->flags & SCTP_CHUNK_FLAG_T)
338 goto out_unlock;
339 } else if (sch->type == SCTP_CID_COOKIE_ECHO) {
340
341 if (sh->vtag != ct->proto.sctp.vtag[dir])
342 goto out_unlock;
343 }
344
345 old_state = ct->proto.sctp.state;
346 new_state = sctp_new_state(dir, old_state, sch->type);
347
348
349 if (new_state == SCTP_CONNTRACK_MAX) {
350 pr_debug("nf_conntrack_sctp: Invalid dir=%i ctype=%u "
351 "conntrack=%u\n",
352 dir, sch->type, old_state);
353 goto out_unlock;
354 }
355
356
357 if (sch->type == SCTP_CID_INIT ||
358 sch->type == SCTP_CID_INIT_ACK) {
359 sctp_inithdr_t _inithdr, *ih;
360
361 ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
362 sizeof(_inithdr), &_inithdr);
363 if (ih == NULL)
364 goto out_unlock;
365 pr_debug("Setting vtag %x for dir %d\n",
366 ih->init_tag, !dir);
367 ct->proto.sctp.vtag[!dir] = ih->init_tag;
368 }
369
370 ct->proto.sctp.state = new_state;
371 if (old_state != new_state)
372 nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
373 }
374 write_unlock_bh(&sctp_lock);
375
376 nf_ct_refresh_acct(ct, ctinfo, skb, sctp_timeouts[new_state]);
377
378 if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED &&
379 dir == IP_CT_DIR_REPLY &&
380 new_state == SCTP_CONNTRACK_ESTABLISHED) {
381 pr_debug("Setting assured bit\n");
382 set_bit(IPS_ASSURED_BIT, &ct->status);
383 nf_conntrack_event_cache(IPCT_STATUS, ct);
384 }
385
386 return NF_ACCEPT;
387
388out_unlock:
389 write_unlock_bh(&sctp_lock);
390out:
391 return -NF_ACCEPT;
392}
393
394
395static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
396 unsigned int dataoff)
397{
398 enum sctp_conntrack new_state;
399 const struct sctphdr *sh;
400 struct sctphdr _sctph;
401 const struct sctp_chunkhdr *sch;
402 struct sctp_chunkhdr _sch;
403 u_int32_t offset, count;
404 unsigned long map[256 / sizeof(unsigned long)] = { 0 };
405
406 sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
407 if (sh == NULL)
408 return false;
409
410 if (do_basic_checks(ct, skb, dataoff, map) != 0)
411 return false;
412
413
414 if (test_bit(SCTP_CID_ABORT, map) ||
415 test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) ||
416 test_bit(SCTP_CID_COOKIE_ACK, map))
417 return false;
418
419 new_state = SCTP_CONNTRACK_MAX;
420 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
421
422 new_state = sctp_new_state(IP_CT_DIR_ORIGINAL,
423 SCTP_CONNTRACK_NONE, sch->type);
424
425
426 if (new_state == SCTP_CONNTRACK_NONE ||
427 new_state == SCTP_CONNTRACK_MAX) {
428 pr_debug("nf_conntrack_sctp: invalid new deleting.\n");
429 return false;
430 }
431
432
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),
438 sizeof(_inithdr), &_inithdr);
439 if (ih == NULL)
440 return false;
441
442 pr_debug("Setting vtag %x for new conn\n",
443 ih->init_tag);
444
445 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] =
446 ih->init_tag;
447 } else {
448
449 return false;
450 }
451 }
452
453
454 else {
455 pr_debug("Setting vtag %x for new conn OOTB\n",
456 sh->vtag);
457 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
458 }
459
460 ct->proto.sctp.state = new_state;
461 }
462
463 return true;
464}
465
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,
485 ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL]);
486
487 NLA_PUT_BE32(skb,
488 CTA_PROTOINFO_SCTP_VTAG_REPLY,
489 ct->proto.sctp.vtag[IP_CT_DIR_REPLY]);
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
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] =
533 nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]);
534 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] =
535 nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]);
536 write_unlock_bh(&sctp_lock);
537
538 return 0;
539}
540
541static int sctp_nlattr_size(void)
542{
543 return nla_total_size(0)
544 + nla_policy_len(sctp_nla_policy, CTA_PROTOINFO_SCTP_MAX + 1);
545}
546#endif
547
548#ifdef CONFIG_SYSCTL
549static unsigned int sctp_sysctl_table_users;
550static struct ctl_table_header *sctp_sysctl_header;
551static struct ctl_table sctp_sysctl_table[] = {
552 {
553 .procname = "nf_conntrack_sctp_timeout_closed",
554 .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
555 .maxlen = sizeof(unsigned int),
556 .mode = 0644,
557 .proc_handler = proc_dointvec_jiffies,
558 },
559 {
560 .procname = "nf_conntrack_sctp_timeout_cookie_wait",
561 .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
562 .maxlen = sizeof(unsigned int),
563 .mode = 0644,
564 .proc_handler = proc_dointvec_jiffies,
565 },
566 {
567 .procname = "nf_conntrack_sctp_timeout_cookie_echoed",
568 .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
569 .maxlen = sizeof(unsigned int),
570 .mode = 0644,
571 .proc_handler = proc_dointvec_jiffies,
572 },
573 {
574 .procname = "nf_conntrack_sctp_timeout_established",
575 .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
576 .maxlen = sizeof(unsigned int),
577 .mode = 0644,
578 .proc_handler = proc_dointvec_jiffies,
579 },
580 {
581 .procname = "nf_conntrack_sctp_timeout_shutdown_sent",
582 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
583 .maxlen = sizeof(unsigned int),
584 .mode = 0644,
585 .proc_handler = proc_dointvec_jiffies,
586 },
587 {
588 .procname = "nf_conntrack_sctp_timeout_shutdown_recd",
589 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
590 .maxlen = sizeof(unsigned int),
591 .mode = 0644,
592 .proc_handler = proc_dointvec_jiffies,
593 },
594 {
595 .procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent",
596 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
597 .maxlen = sizeof(unsigned int),
598 .mode = 0644,
599 .proc_handler = proc_dointvec_jiffies,
600 },
601 {
602 .ctl_name = 0
603 }
604};
605
606#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
607static struct ctl_table sctp_compat_sysctl_table[] = {
608 {
609 .procname = "ip_conntrack_sctp_timeout_closed",
610 .data = &sctp_timeouts[SCTP_CONNTRACK_CLOSED],
611 .maxlen = sizeof(unsigned int),
612 .mode = 0644,
613 .proc_handler = proc_dointvec_jiffies,
614 },
615 {
616 .procname = "ip_conntrack_sctp_timeout_cookie_wait",
617 .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_WAIT],
618 .maxlen = sizeof(unsigned int),
619 .mode = 0644,
620 .proc_handler = proc_dointvec_jiffies,
621 },
622 {
623 .procname = "ip_conntrack_sctp_timeout_cookie_echoed",
624 .data = &sctp_timeouts[SCTP_CONNTRACK_COOKIE_ECHOED],
625 .maxlen = sizeof(unsigned int),
626 .mode = 0644,
627 .proc_handler = proc_dointvec_jiffies,
628 },
629 {
630 .procname = "ip_conntrack_sctp_timeout_established",
631 .data = &sctp_timeouts[SCTP_CONNTRACK_ESTABLISHED],
632 .maxlen = sizeof(unsigned int),
633 .mode = 0644,
634 .proc_handler = proc_dointvec_jiffies,
635 },
636 {
637 .procname = "ip_conntrack_sctp_timeout_shutdown_sent",
638 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT],
639 .maxlen = sizeof(unsigned int),
640 .mode = 0644,
641 .proc_handler = proc_dointvec_jiffies,
642 },
643 {
644 .procname = "ip_conntrack_sctp_timeout_shutdown_recd",
645 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD],
646 .maxlen = sizeof(unsigned int),
647 .mode = 0644,
648 .proc_handler = proc_dointvec_jiffies,
649 },
650 {
651 .procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent",
652 .data = &sctp_timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT],
653 .maxlen = sizeof(unsigned int),
654 .mode = 0644,
655 .proc_handler = proc_dointvec_jiffies,
656 },
657 {
658 .ctl_name = 0
659 }
660};
661#endif
662#endif
663
664static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
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,
675#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
676 .to_nlattr = sctp_to_nlattr,
677 .nlattr_size = sctp_nlattr_size,
678 .from_nlattr = nlattr_to_sctp,
679 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
680 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
681 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
682 .nla_policy = nf_ct_port_nla_policy,
683#endif
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,
688#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
689 .ctl_compat_table = sctp_compat_sysctl_table,
690#endif
691#endif
692};
693
694static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
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,
705#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
706 .to_nlattr = sctp_to_nlattr,
707 .nlattr_size = sctp_nlattr_size,
708 .from_nlattr = nlattr_to_sctp,
709 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
710 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
711 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
712 .nla_policy = nf_ct_port_nla_policy,
713#endif
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,
718#endif
719};
720
721static int __init nf_conntrack_proto_sctp_init(void)
722{
723 int ret;
724
725 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp4);
726 if (ret) {
727 printk("nf_conntrack_l4proto_sctp4: protocol register failed\n");
728 goto out;
729 }
730 ret = nf_conntrack_l4proto_register(&nf_conntrack_l4proto_sctp6);
731 if (ret) {
732 printk("nf_conntrack_l4proto_sctp6: protocol register failed\n");
733 goto cleanup_sctp4;
734 }
735
736 return ret;
737
738 cleanup_sctp4:
739 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
740 out:
741 return ret;
742}
743
744static void __exit nf_conntrack_proto_sctp_fini(void)
745{
746 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
747 nf_conntrack_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
748}
749
750module_init(nf_conntrack_proto_sctp_init);
751module_exit(nf_conntrack_proto_sctp_fini);
752
753MODULE_LICENSE("GPL");
754MODULE_AUTHOR("Kiran Kumar Immidi");
755MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
756MODULE_ALIAS("ip_conntrack_proto_sctp");
757