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