Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[deliverable/linux.git] / net / netfilter / nf_conntrack_proto_sctp.c
CommitLineData
9fb9cbb1
YK
1/*
2 * Connection tracking protocol helper module for SCTP.
601e68e1 3 *
f229f6ce
PM
4 * Copyright (c) 2004 Kiran Kumar Immidi <immidi_kiran@yahoo.com>
5 * Copyright (c) 2004-2012 Patrick McHardy <kaber@trash.net>
6 *
601e68e1 7 * SCTP is defined in RFC 2960. References to various sections in this code
9fb9cbb1 8 * are to this RFC.
601e68e1 9 *
9fb9cbb1
YK
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
9fb9cbb1
YK
13 */
14
15#include <linux/types.h>
9fb9cbb1
YK
16#include <linux/timer.h>
17#include <linux/netfilter.h>
18#include <linux/module.h>
19#include <linux/in.h>
20#include <linux/ip.h>
21#include <linux/sctp.h>
22#include <linux/string.h>
23#include <linux/seq_file.h>
40a839fd
YK
24#include <linux/spinlock.h>
25#include <linux/interrupt.h>
9fb9cbb1
YK
26
27#include <net/netfilter/nf_conntrack.h>
605dcad6 28#include <net/netfilter/nf_conntrack_l4proto.h>
f6180121 29#include <net/netfilter/nf_conntrack_ecache.h>
9fb9cbb1 30
9fb9cbb1 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",
d7ee3519
MK
45 "HEARTBEAT_SENT",
46 "HEARTBEAT_ACKED",
9fb9cbb1
YK
47};
48
49#define SECS * HZ
50#define MINS * 60 SECS
51#define HOURS * 60 MINS
52#define DAYS * 24 HOURS
53
86c0bf40
PM
54static unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX] __read_mostly = {
55 [SCTP_CONNTRACK_CLOSED] = 10 SECS,
56 [SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS,
57 [SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS,
58 [SCTP_CONNTRACK_ESTABLISHED] = 5 DAYS,
59 [SCTP_CONNTRACK_SHUTDOWN_SENT] = 300 SECS / 1000,
60 [SCTP_CONNTRACK_SHUTDOWN_RECD] = 300 SECS / 1000,
61 [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS,
d7ee3519
MK
62 [SCTP_CONNTRACK_HEARTBEAT_SENT] = 30 SECS,
63 [SCTP_CONNTRACK_HEARTBEAT_ACKED] = 210 SECS,
86c0bf40 64};
9fb9cbb1
YK
65
66#define sNO SCTP_CONNTRACK_NONE
67#define sCL SCTP_CONNTRACK_CLOSED
68#define sCW SCTP_CONNTRACK_COOKIE_WAIT
69#define sCE SCTP_CONNTRACK_COOKIE_ECHOED
70#define sES SCTP_CONNTRACK_ESTABLISHED
71#define sSS SCTP_CONNTRACK_SHUTDOWN_SENT
72#define sSR SCTP_CONNTRACK_SHUTDOWN_RECD
73#define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT
d7ee3519
MK
74#define sHS SCTP_CONNTRACK_HEARTBEAT_SENT
75#define sHA SCTP_CONNTRACK_HEARTBEAT_ACKED
9fb9cbb1
YK
76#define sIV SCTP_CONNTRACK_MAX
77
601e68e1 78/*
9fb9cbb1
YK
79 These are the descriptions of the states:
80
601e68e1 81NOTE: These state names are tantalizingly similar to the states of an
9fb9cbb1 82SCTP endpoint. But the interpretation of the states is a little different,
601e68e1 83considering that these are the states of the connection and not of an end
9fb9cbb1
YK
84point. Please note the subtleties. -Kiran
85
86NONE - Nothing so far.
601e68e1
YH
87COOKIE WAIT - We have seen an INIT chunk in the original direction, or also
88 an INIT_ACK chunk in the reply direction.
9fb9cbb1
YK
89COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction.
90ESTABLISHED - We have seen a COOKIE_ACK in the reply direction.
91SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction.
92SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply directoin.
93SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite
601e68e1
YH
94 to that of the SHUTDOWN chunk.
95CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of
96 the SHUTDOWN chunk. Connection is closed.
d7ee3519
MK
97HEARTBEAT_SENT - We have seen a HEARTBEAT in a new flow.
98HEARTBEAT_ACKED - We have seen a HEARTBEAT-ACK in the direction opposite to
99 that of the HEARTBEAT chunk. Secondary connection is
100 established.
9fb9cbb1
YK
101*/
102
103/* TODO
601e68e1 104 - I have assumed that the first INIT is in the original direction.
9fb9cbb1
YK
105 This messes things when an INIT comes in the reply direction in CLOSED
106 state.
601e68e1 107 - Check the error type in the reply dir before transitioning from
9fb9cbb1
YK
108cookie echoed to closed.
109 - Sec 5.2.4 of RFC 2960
d7ee3519 110 - Full Multi Homing support.
9fb9cbb1
YK
111*/
112
113/* SCTP conntrack state transitions */
d7ee3519 114static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = {
9fb9cbb1
YK
115 {
116/* ORIGINAL */
d7ee3519
MK
117/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA */
118/* init */ {sCW, sCW, sCW, sCE, sES, sSS, sSR, sSA, sCW, sHA},
119/* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL, sHA},
120/* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL},
121/* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA, sCL, sSS},
122/* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA, sHA},
123/* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL, sHA},/* Can't have Stale cookie*/
124/* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA, sCL, sHA},/* 5.2.4 - Big TODO */
125/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL, sHA},/* Can't come in orig dir */
126/* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL, sHA},
127/* heartbeat */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA},
128/* heartbeat_ack*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA}
9fb9cbb1
YK
129 },
130 {
131/* REPLY */
d7ee3519
MK
132/* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA */
133/* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV, sHA},/* INIT in sCL Big TODO */
134/* init_ack */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV, sHA},
135/* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV, sCL},
136/* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV, sSR},
137/* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV, sHA},
138/* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA, sIV, sHA},
139/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV, sHA},/* Can't come in reply dir */
140/* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV, sHA},
141/* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV, sHA},
142/* heartbeat */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS, sHA},
143/* heartbeat_ack*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHA, sHA}
9fb9cbb1
YK
144 }
145};
146
49d485a3
G
147static int sctp_net_id __read_mostly;
148struct sctp_net {
149 struct nf_proto_net pn;
150 unsigned int timeouts[SCTP_CONNTRACK_MAX];
151};
152
153static inline struct sctp_net *sctp_pernet(struct net *net)
154{
155 return net_generic(net, sctp_net_id);
156}
157
09f263cd 158static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
a31f1adc 159 struct net *net, struct nf_conntrack_tuple *tuple)
9fb9cbb1 160{
12c33aa2
JE
161 const struct sctphdr *hp;
162 struct sctphdr _hdr;
9fb9cbb1 163
9fb9cbb1
YK
164 /* Actually only need first 8 bytes. */
165 hp = skb_header_pointer(skb, dataoff, 8, &_hdr);
166 if (hp == NULL)
09f263cd 167 return false;
9fb9cbb1
YK
168
169 tuple->src.u.sctp.port = hp->source;
170 tuple->dst.u.sctp.port = hp->dest;
09f263cd 171 return true;
9fb9cbb1
YK
172}
173
09f263cd
JE
174static bool sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
175 const struct nf_conntrack_tuple *orig)
9fb9cbb1 176{
9fb9cbb1
YK
177 tuple->src.u.sctp.port = orig->dst.u.sctp.port;
178 tuple->dst.u.sctp.port = orig->src.u.sctp.port;
09f263cd 179 return true;
9fb9cbb1
YK
180}
181
182/* Print out the per-protocol part of the tuple. */
824f1fbe
JP
183static void sctp_print_tuple(struct seq_file *s,
184 const struct nf_conntrack_tuple *tuple)
9fb9cbb1 185{
824f1fbe
JP
186 seq_printf(s, "sport=%hu dport=%hu ",
187 ntohs(tuple->src.u.sctp.port),
188 ntohs(tuple->dst.u.sctp.port));
9fb9cbb1
YK
189}
190
191/* Print out the private part of the conntrack. */
37246a58 192static void sctp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
9fb9cbb1
YK
193{
194 enum sctp_conntrack state;
195
440f0d58 196 spin_lock_bh(&ct->lock);
112f35c9 197 state = ct->proto.sctp.state;
440f0d58 198 spin_unlock_bh(&ct->lock);
9fb9cbb1 199
37246a58 200 seq_printf(s, "%s ", sctp_conntrack_names[state]);
9fb9cbb1
YK
201}
202
203#define for_each_sctp_chunk(skb, sch, _sch, offset, dataoff, count) \
e79ec50b
JE
204for ((offset) = (dataoff) + sizeof(sctp_sctphdr_t), (count) = 0; \
205 (offset) < (skb)->len && \
206 ((sch) = skb_header_pointer((skb), (offset), sizeof(_sch), &(_sch))); \
207 (offset) += (ntohs((sch)->length) + 3) & ~3, (count)++)
9fb9cbb1
YK
208
209/* Some validity checks to make sure the chunks are fine */
112f35c9 210static int do_basic_checks(struct nf_conn *ct,
9fb9cbb1
YK
211 const struct sk_buff *skb,
212 unsigned int dataoff,
35c6d3cb 213 unsigned long *map)
9fb9cbb1
YK
214{
215 u_int32_t offset, count;
216 sctp_chunkhdr_t _sch, *sch;
217 int flag;
218
9fb9cbb1
YK
219 flag = 0;
220
221 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
0d53778e 222 pr_debug("Chunk Num: %d Type: %d\n", count, sch->type);
9fb9cbb1 223
5447d477
PM
224 if (sch->type == SCTP_CID_INIT ||
225 sch->type == SCTP_CID_INIT_ACK ||
226 sch->type == SCTP_CID_SHUTDOWN_COMPLETE)
9fb9cbb1 227 flag = 1;
9fb9cbb1 228
e17df688
PM
229 /*
230 * Cookie Ack/Echo chunks not the first OR
231 * Init / Init Ack / Shutdown compl chunks not the only chunks
232 * OR zero-length.
233 */
5447d477
PM
234 if (((sch->type == SCTP_CID_COOKIE_ACK ||
235 sch->type == SCTP_CID_COOKIE_ECHO ||
236 flag) &&
237 count != 0) || !sch->length) {
0d53778e 238 pr_debug("Basic checks failed\n");
9fb9cbb1
YK
239 return 1;
240 }
241
5447d477 242 if (map)
35c6d3cb 243 set_bit(sch->type, map);
9fb9cbb1
YK
244 }
245
0d53778e 246 pr_debug("Basic checks passed\n");
dd7271fe 247 return count == 0;
9fb9cbb1
YK
248}
249
efe9f68a
PM
250static int sctp_new_state(enum ip_conntrack_dir dir,
251 enum sctp_conntrack cur_state,
252 int chunk_type)
9fb9cbb1
YK
253{
254 int i;
255
0d53778e 256 pr_debug("Chunk type: %d\n", chunk_type);
9fb9cbb1
YK
257
258 switch (chunk_type) {
5447d477
PM
259 case SCTP_CID_INIT:
260 pr_debug("SCTP_CID_INIT\n");
261 i = 0;
262 break;
263 case SCTP_CID_INIT_ACK:
264 pr_debug("SCTP_CID_INIT_ACK\n");
265 i = 1;
266 break;
267 case SCTP_CID_ABORT:
268 pr_debug("SCTP_CID_ABORT\n");
269 i = 2;
270 break;
271 case SCTP_CID_SHUTDOWN:
272 pr_debug("SCTP_CID_SHUTDOWN\n");
273 i = 3;
274 break;
275 case SCTP_CID_SHUTDOWN_ACK:
276 pr_debug("SCTP_CID_SHUTDOWN_ACK\n");
277 i = 4;
278 break;
279 case SCTP_CID_ERROR:
280 pr_debug("SCTP_CID_ERROR\n");
281 i = 5;
282 break;
283 case SCTP_CID_COOKIE_ECHO:
284 pr_debug("SCTP_CID_COOKIE_ECHO\n");
285 i = 6;
286 break;
287 case SCTP_CID_COOKIE_ACK:
288 pr_debug("SCTP_CID_COOKIE_ACK\n");
289 i = 7;
290 break;
291 case SCTP_CID_SHUTDOWN_COMPLETE:
292 pr_debug("SCTP_CID_SHUTDOWN_COMPLETE\n");
293 i = 8;
294 break;
d7ee3519
MK
295 case SCTP_CID_HEARTBEAT:
296 pr_debug("SCTP_CID_HEARTBEAT");
297 i = 9;
298 break;
299 case SCTP_CID_HEARTBEAT_ACK:
300 pr_debug("SCTP_CID_HEARTBEAT_ACK");
301 i = 10;
302 break;
5447d477 303 default:
d7ee3519 304 /* Other chunks like DATA or SACK do not change the state */
5447d477
PM
305 pr_debug("Unknown chunk type, Will stay in %s\n",
306 sctp_conntrack_names[cur_state]);
307 return cur_state;
9fb9cbb1
YK
308 }
309
0d53778e
PM
310 pr_debug("dir: %d cur_state: %s chunk_type: %d new_state: %s\n",
311 dir, sctp_conntrack_names[cur_state], chunk_type,
312 sctp_conntrack_names[sctp_conntracks[dir][i][cur_state]]);
9fb9cbb1
YK
313
314 return sctp_conntracks[dir][i][cur_state];
315}
316
2c8503f5
PNA
317static unsigned int *sctp_get_timeouts(struct net *net)
318{
49d485a3 319 return sctp_pernet(net)->timeouts;
2c8503f5
PNA
320}
321
b37e933a 322/* Returns verdict for packet, or -NF_ACCEPT for invalid. */
112f35c9 323static int sctp_packet(struct nf_conn *ct,
9fb9cbb1
YK
324 const struct sk_buff *skb,
325 unsigned int dataoff,
326 enum ip_conntrack_info ctinfo,
76108cea 327 u_int8_t pf,
2c8503f5
PNA
328 unsigned int hooknum,
329 unsigned int *timeouts)
9fb9cbb1 330{
efe9f68a 331 enum sctp_conntrack new_state, old_state;
8528819a 332 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
12c33aa2
JE
333 const struct sctphdr *sh;
334 struct sctphdr _sctph;
335 const struct sctp_chunkhdr *sch;
336 struct sctp_chunkhdr _sch;
9fb9cbb1 337 u_int32_t offset, count;
35c6d3cb 338 unsigned long map[256 / sizeof(unsigned long)] = { 0 };
9fb9cbb1 339
9fb9cbb1
YK
340 sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
341 if (sh == NULL)
b37e933a 342 goto out;
9fb9cbb1 343
112f35c9 344 if (do_basic_checks(ct, skb, dataoff, map) != 0)
b37e933a 345 goto out;
9fb9cbb1
YK
346
347 /* Check the verification tag (Sec 8.5) */
35c6d3cb
PM
348 if (!test_bit(SCTP_CID_INIT, map) &&
349 !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) &&
350 !test_bit(SCTP_CID_COOKIE_ECHO, map) &&
351 !test_bit(SCTP_CID_ABORT, map) &&
352 !test_bit(SCTP_CID_SHUTDOWN_ACK, map) &&
d7ee3519
MK
353 !test_bit(SCTP_CID_HEARTBEAT, map) &&
354 !test_bit(SCTP_CID_HEARTBEAT_ACK, map) &&
8528819a 355 sh->vtag != ct->proto.sctp.vtag[dir]) {
0d53778e 356 pr_debug("Verification tag check failed\n");
b37e933a 357 goto out;
9fb9cbb1
YK
358 }
359
328bd899 360 old_state = new_state = SCTP_CONNTRACK_NONE;
440f0d58 361 spin_lock_bh(&ct->lock);
9fb9cbb1 362 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
9fb9cbb1
YK
363 /* Special cases of Verification tag check (Sec 8.5.1) */
364 if (sch->type == SCTP_CID_INIT) {
365 /* Sec 8.5.1 (A) */
b37e933a
PM
366 if (sh->vtag != 0)
367 goto out_unlock;
9fb9cbb1
YK
368 } else if (sch->type == SCTP_CID_ABORT) {
369 /* Sec 8.5.1 (B) */
8528819a 370 if (sh->vtag != ct->proto.sctp.vtag[dir] &&
b37e933a
PM
371 sh->vtag != ct->proto.sctp.vtag[!dir])
372 goto out_unlock;
9fb9cbb1
YK
373 } else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) {
374 /* Sec 8.5.1 (C) */
8528819a
PM
375 if (sh->vtag != ct->proto.sctp.vtag[dir] &&
376 sh->vtag != ct->proto.sctp.vtag[!dir] &&
9b1c2cfd 377 sch->flags & SCTP_CHUNK_FLAG_T)
b37e933a 378 goto out_unlock;
9fb9cbb1
YK
379 } else if (sch->type == SCTP_CID_COOKIE_ECHO) {
380 /* Sec 8.5.1 (D) */
b37e933a
PM
381 if (sh->vtag != ct->proto.sctp.vtag[dir])
382 goto out_unlock;
d7ee3519
MK
383 } else if (sch->type == SCTP_CID_HEARTBEAT ||
384 sch->type == SCTP_CID_HEARTBEAT_ACK) {
385 if (ct->proto.sctp.vtag[dir] == 0) {
386 pr_debug("Setting vtag %x for dir %d\n",
387 sh->vtag, dir);
388 ct->proto.sctp.vtag[dir] = sh->vtag;
389 } else if (sh->vtag != ct->proto.sctp.vtag[dir]) {
390 pr_debug("Verification tag check failed\n");
391 goto out_unlock;
392 }
9fb9cbb1
YK
393 }
394
efe9f68a
PM
395 old_state = ct->proto.sctp.state;
396 new_state = sctp_new_state(dir, old_state, sch->type);
9fb9cbb1
YK
397
398 /* Invalid */
efe9f68a 399 if (new_state == SCTP_CONNTRACK_MAX) {
0d53778e
PM
400 pr_debug("nf_conntrack_sctp: Invalid dir=%i ctype=%u "
401 "conntrack=%u\n",
efe9f68a 402 dir, sch->type, old_state);
b37e933a 403 goto out_unlock;
9fb9cbb1
YK
404 }
405
406 /* If it is an INIT or an INIT ACK note down the vtag */
5447d477
PM
407 if (sch->type == SCTP_CID_INIT ||
408 sch->type == SCTP_CID_INIT_ACK) {
9fb9cbb1
YK
409 sctp_inithdr_t _inithdr, *ih;
410
411 ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
601e68e1 412 sizeof(_inithdr), &_inithdr);
b37e933a
PM
413 if (ih == NULL)
414 goto out_unlock;
0d53778e 415 pr_debug("Setting vtag %x for dir %d\n",
8528819a
PM
416 ih->init_tag, !dir);
417 ct->proto.sctp.vtag[!dir] = ih->init_tag;
9fb9cbb1
YK
418 }
419
efe9f68a
PM
420 ct->proto.sctp.state = new_state;
421 if (old_state != new_state)
a71996fc 422 nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
9fb9cbb1 423 }
440f0d58 424 spin_unlock_bh(&ct->lock);
9fb9cbb1 425
2c8503f5 426 nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]);
9fb9cbb1 427
efe9f68a 428 if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED &&
8528819a 429 dir == IP_CT_DIR_REPLY &&
efe9f68a 430 new_state == SCTP_CONNTRACK_ESTABLISHED) {
0d53778e 431 pr_debug("Setting assured bit\n");
112f35c9 432 set_bit(IPS_ASSURED_BIT, &ct->status);
858b3133 433 nf_conntrack_event_cache(IPCT_ASSURED, ct);
9fb9cbb1
YK
434 }
435
436 return NF_ACCEPT;
b37e933a
PM
437
438out_unlock:
440f0d58 439 spin_unlock_bh(&ct->lock);
b37e933a
PM
440out:
441 return -NF_ACCEPT;
9fb9cbb1
YK
442}
443
444/* Called when a new connection for this protocol found. */
09f263cd 445static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
2c8503f5 446 unsigned int dataoff, unsigned int *timeouts)
9fb9cbb1 447{
efe9f68a 448 enum sctp_conntrack new_state;
12c33aa2
JE
449 const struct sctphdr *sh;
450 struct sctphdr _sctph;
451 const struct sctp_chunkhdr *sch;
452 struct sctp_chunkhdr _sch;
9fb9cbb1 453 u_int32_t offset, count;
35c6d3cb 454 unsigned long map[256 / sizeof(unsigned long)] = { 0 };
9fb9cbb1 455
9fb9cbb1
YK
456 sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
457 if (sh == NULL)
09f263cd 458 return false;
9fb9cbb1 459
112f35c9 460 if (do_basic_checks(ct, skb, dataoff, map) != 0)
09f263cd 461 return false;
9fb9cbb1
YK
462
463 /* If an OOTB packet has any of these chunks discard (Sec 8.4) */
35c6d3cb
PM
464 if (test_bit(SCTP_CID_ABORT, map) ||
465 test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) ||
466 test_bit(SCTP_CID_COOKIE_ACK, map))
09f263cd 467 return false;
9fb9cbb1 468
e5fc9e7a 469 memset(&ct->proto.sctp, 0, sizeof(ct->proto.sctp));
efe9f68a 470 new_state = SCTP_CONNTRACK_MAX;
9fb9cbb1
YK
471 for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) {
472 /* Don't need lock here: this conntrack not in circulation yet */
efe9f68a
PM
473 new_state = sctp_new_state(IP_CT_DIR_ORIGINAL,
474 SCTP_CONNTRACK_NONE, sch->type);
9fb9cbb1
YK
475
476 /* Invalid: delete conntrack */
efe9f68a
PM
477 if (new_state == SCTP_CONNTRACK_NONE ||
478 new_state == SCTP_CONNTRACK_MAX) {
0d53778e 479 pr_debug("nf_conntrack_sctp: invalid new deleting.\n");
09f263cd 480 return false;
9fb9cbb1
YK
481 }
482
483 /* Copy the vtag into the state info */
484 if (sch->type == SCTP_CID_INIT) {
485 if (sh->vtag == 0) {
486 sctp_inithdr_t _inithdr, *ih;
487
488 ih = skb_header_pointer(skb, offset + sizeof(sctp_chunkhdr_t),
601e68e1 489 sizeof(_inithdr), &_inithdr);
9fb9cbb1 490 if (ih == NULL)
09f263cd 491 return false;
9fb9cbb1 492
0d53778e
PM
493 pr_debug("Setting vtag %x for new conn\n",
494 ih->init_tag);
9fb9cbb1 495
112f35c9 496 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] =
9fb9cbb1
YK
497 ih->init_tag;
498 } else {
499 /* Sec 8.5.1 (A) */
09f263cd 500 return false;
9fb9cbb1 501 }
d7ee3519
MK
502 } else if (sch->type == SCTP_CID_HEARTBEAT) {
503 pr_debug("Setting vtag %x for secondary conntrack\n",
504 sh->vtag);
505 ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = sh->vtag;
9fb9cbb1
YK
506 }
507 /* If it is a shutdown ack OOTB packet, we expect a return
508 shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */
509 else {
0d53778e
PM
510 pr_debug("Setting vtag %x for new conn OOTB\n",
511 sh->vtag);
112f35c9 512 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag;
9fb9cbb1
YK
513 }
514
efe9f68a 515 ct->proto.sctp.state = new_state;
9fb9cbb1
YK
516 }
517
09f263cd 518 return true;
9fb9cbb1
YK
519}
520
c0cd1156 521#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
a258860e
PNA
522
523#include <linux/netfilter/nfnetlink.h>
524#include <linux/netfilter/nfnetlink_conntrack.h>
525
526static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
440f0d58 527 struct nf_conn *ct)
a258860e
PNA
528{
529 struct nlattr *nest_parms;
530
440f0d58 531 spin_lock_bh(&ct->lock);
a258860e
PNA
532 nest_parms = nla_nest_start(skb, CTA_PROTOINFO_SCTP | NLA_F_NESTED);
533 if (!nest_parms)
534 goto nla_put_failure;
535
5e8d1eb5
DM
536 if (nla_put_u8(skb, CTA_PROTOINFO_SCTP_STATE, ct->proto.sctp.state) ||
537 nla_put_be32(skb, CTA_PROTOINFO_SCTP_VTAG_ORIGINAL,
538 ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL]) ||
539 nla_put_be32(skb, CTA_PROTOINFO_SCTP_VTAG_REPLY,
540 ct->proto.sctp.vtag[IP_CT_DIR_REPLY]))
541 goto nla_put_failure;
a258860e 542
440f0d58 543 spin_unlock_bh(&ct->lock);
a258860e
PNA
544
545 nla_nest_end(skb, nest_parms);
546
547 return 0;
548
549nla_put_failure:
440f0d58 550 spin_unlock_bh(&ct->lock);
a258860e
PNA
551 return -1;
552}
553
554static const struct nla_policy sctp_nla_policy[CTA_PROTOINFO_SCTP_MAX+1] = {
555 [CTA_PROTOINFO_SCTP_STATE] = { .type = NLA_U8 },
556 [CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] = { .type = NLA_U32 },
557 [CTA_PROTOINFO_SCTP_VTAG_REPLY] = { .type = NLA_U32 },
558};
559
560static int nlattr_to_sctp(struct nlattr *cda[], struct nf_conn *ct)
561{
562 struct nlattr *attr = cda[CTA_PROTOINFO_SCTP];
563 struct nlattr *tb[CTA_PROTOINFO_SCTP_MAX+1];
564 int err;
565
566 /* updates may not contain the internal protocol info, skip parsing */
567 if (!attr)
568 return 0;
569
570 err = nla_parse_nested(tb,
571 CTA_PROTOINFO_SCTP_MAX,
572 attr,
573 sctp_nla_policy);
574 if (err < 0)
575 return err;
576
577 if (!tb[CTA_PROTOINFO_SCTP_STATE] ||
578 !tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] ||
579 !tb[CTA_PROTOINFO_SCTP_VTAG_REPLY])
580 return -EINVAL;
581
440f0d58 582 spin_lock_bh(&ct->lock);
a258860e
PNA
583 ct->proto.sctp.state = nla_get_u8(tb[CTA_PROTOINFO_SCTP_STATE]);
584 ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] =
5547cd0a 585 nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]);
a258860e 586 ct->proto.sctp.vtag[IP_CT_DIR_REPLY] =
5547cd0a 587 nla_get_be32(tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]);
440f0d58 588 spin_unlock_bh(&ct->lock);
a258860e
PNA
589
590 return 0;
591}
a400c30e
HE
592
593static int sctp_nlattr_size(void)
594{
595 return nla_total_size(0) /* CTA_PROTOINFO_SCTP */
596 + nla_policy_len(sctp_nla_policy, CTA_PROTOINFO_SCTP_MAX + 1);
597}
a258860e
PNA
598#endif
599
50978462
PNA
600#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
601
602#include <linux/netfilter/nfnetlink.h>
603#include <linux/netfilter/nfnetlink_cttimeout.h>
604
8264deb8
G
605static int sctp_timeout_nlattr_to_obj(struct nlattr *tb[],
606 struct net *net, void *data)
50978462
PNA
607{
608 unsigned int *timeouts = data;
8264deb8 609 struct sctp_net *sn = sctp_pernet(net);
50978462
PNA
610 int i;
611
612 /* set default SCTP timeouts. */
613 for (i=0; i<SCTP_CONNTRACK_MAX; i++)
8264deb8 614 timeouts[i] = sn->timeouts[i];
50978462
PNA
615
616 /* there's a 1:1 mapping between attributes and protocol states. */
617 for (i=CTA_TIMEOUT_SCTP_UNSPEC+1; i<CTA_TIMEOUT_SCTP_MAX+1; i++) {
618 if (tb[i]) {
619 timeouts[i] = ntohl(nla_get_be32(tb[i])) * HZ;
620 }
621 }
622 return 0;
623}
624
625static int
626sctp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
627{
628 const unsigned int *timeouts = data;
629 int i;
630
5e8d1eb5
DM
631 for (i=CTA_TIMEOUT_SCTP_UNSPEC+1; i<CTA_TIMEOUT_SCTP_MAX+1; i++) {
632 if (nla_put_be32(skb, i, htonl(timeouts[i] / HZ)))
633 goto nla_put_failure;
634 }
50978462
PNA
635 return 0;
636
637nla_put_failure:
638 return -ENOSPC;
639}
640
641static const struct nla_policy
642sctp_timeout_nla_policy[CTA_TIMEOUT_SCTP_MAX+1] = {
643 [CTA_TIMEOUT_SCTP_CLOSED] = { .type = NLA_U32 },
644 [CTA_TIMEOUT_SCTP_COOKIE_WAIT] = { .type = NLA_U32 },
645 [CTA_TIMEOUT_SCTP_COOKIE_ECHOED] = { .type = NLA_U32 },
646 [CTA_TIMEOUT_SCTP_ESTABLISHED] = { .type = NLA_U32 },
647 [CTA_TIMEOUT_SCTP_SHUTDOWN_SENT] = { .type = NLA_U32 },
648 [CTA_TIMEOUT_SCTP_SHUTDOWN_RECD] = { .type = NLA_U32 },
649 [CTA_TIMEOUT_SCTP_SHUTDOWN_ACK_SENT] = { .type = NLA_U32 },
d7ee3519
MK
650 [CTA_TIMEOUT_SCTP_HEARTBEAT_SENT] = { .type = NLA_U32 },
651 [CTA_TIMEOUT_SCTP_HEARTBEAT_ACKED] = { .type = NLA_U32 },
50978462
PNA
652};
653#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
654
655
9fb9cbb1 656#ifdef CONFIG_SYSCTL
933a41e7 657static struct ctl_table sctp_sysctl_table[] = {
9fb9cbb1 658 {
9fb9cbb1 659 .procname = "nf_conntrack_sctp_timeout_closed",
9fb9cbb1
YK
660 .maxlen = sizeof(unsigned int),
661 .mode = 0644,
6d9f239a 662 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1
YK
663 },
664 {
9fb9cbb1 665 .procname = "nf_conntrack_sctp_timeout_cookie_wait",
9fb9cbb1
YK
666 .maxlen = sizeof(unsigned int),
667 .mode = 0644,
6d9f239a 668 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1
YK
669 },
670 {
9fb9cbb1 671 .procname = "nf_conntrack_sctp_timeout_cookie_echoed",
9fb9cbb1
YK
672 .maxlen = sizeof(unsigned int),
673 .mode = 0644,
6d9f239a 674 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1
YK
675 },
676 {
9fb9cbb1 677 .procname = "nf_conntrack_sctp_timeout_established",
9fb9cbb1
YK
678 .maxlen = sizeof(unsigned int),
679 .mode = 0644,
6d9f239a 680 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1
YK
681 },
682 {
9fb9cbb1 683 .procname = "nf_conntrack_sctp_timeout_shutdown_sent",
9fb9cbb1
YK
684 .maxlen = sizeof(unsigned int),
685 .mode = 0644,
6d9f239a 686 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1
YK
687 },
688 {
9fb9cbb1 689 .procname = "nf_conntrack_sctp_timeout_shutdown_recd",
9fb9cbb1
YK
690 .maxlen = sizeof(unsigned int),
691 .mode = 0644,
6d9f239a 692 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1
YK
693 },
694 {
9fb9cbb1 695 .procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent",
9fb9cbb1
YK
696 .maxlen = sizeof(unsigned int),
697 .mode = 0644,
6d9f239a 698 .proc_handler = proc_dointvec_jiffies,
9fb9cbb1 699 },
d7ee3519
MK
700 {
701 .procname = "nf_conntrack_sctp_timeout_heartbeat_sent",
702 .maxlen = sizeof(unsigned int),
703 .mode = 0644,
704 .proc_handler = proc_dointvec_jiffies,
705 },
706 {
707 .procname = "nf_conntrack_sctp_timeout_heartbeat_acked",
708 .maxlen = sizeof(unsigned int),
709 .mode = 0644,
710 .proc_handler = proc_dointvec_jiffies,
711 },
f8572d8f 712 { }
9fb9cbb1 713};
a999e683
PM
714
715#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
716static struct ctl_table sctp_compat_sysctl_table[] = {
717 {
a999e683 718 .procname = "ip_conntrack_sctp_timeout_closed",
a999e683
PM
719 .maxlen = sizeof(unsigned int),
720 .mode = 0644,
6d9f239a 721 .proc_handler = proc_dointvec_jiffies,
a999e683
PM
722 },
723 {
a999e683 724 .procname = "ip_conntrack_sctp_timeout_cookie_wait",
a999e683
PM
725 .maxlen = sizeof(unsigned int),
726 .mode = 0644,
6d9f239a 727 .proc_handler = proc_dointvec_jiffies,
a999e683
PM
728 },
729 {
a999e683 730 .procname = "ip_conntrack_sctp_timeout_cookie_echoed",
a999e683
PM
731 .maxlen = sizeof(unsigned int),
732 .mode = 0644,
6d9f239a 733 .proc_handler = proc_dointvec_jiffies,
a999e683
PM
734 },
735 {
a999e683 736 .procname = "ip_conntrack_sctp_timeout_established",
a999e683
PM
737 .maxlen = sizeof(unsigned int),
738 .mode = 0644,
6d9f239a 739 .proc_handler = proc_dointvec_jiffies,
a999e683
PM
740 },
741 {
a999e683 742 .procname = "ip_conntrack_sctp_timeout_shutdown_sent",
a999e683
PM
743 .maxlen = sizeof(unsigned int),
744 .mode = 0644,
6d9f239a 745 .proc_handler = proc_dointvec_jiffies,
a999e683
PM
746 },
747 {
a999e683 748 .procname = "ip_conntrack_sctp_timeout_shutdown_recd",
a999e683
PM
749 .maxlen = sizeof(unsigned int),
750 .mode = 0644,
6d9f239a 751 .proc_handler = proc_dointvec_jiffies,
a999e683
PM
752 },
753 {
a999e683 754 .procname = "ip_conntrack_sctp_timeout_shutdown_ack_sent",
a999e683
PM
755 .maxlen = sizeof(unsigned int),
756 .mode = 0644,
6d9f239a 757 .proc_handler = proc_dointvec_jiffies,
a999e683 758 },
f8572d8f 759 { }
a999e683
PM
760};
761#endif /* CONFIG_NF_CONNTRACK_PROC_COMPAT */
933a41e7 762#endif
9fb9cbb1 763
f42c4183
G
764static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn,
765 struct sctp_net *sn)
49d485a3
G
766{
767#ifdef CONFIG_SYSCTL
49d485a3
G
768 if (pn->ctl_table)
769 return 0;
770
771 pn->ctl_table = kmemdup(sctp_sysctl_table,
772 sizeof(sctp_sysctl_table),
773 GFP_KERNEL);
774 if (!pn->ctl_table)
775 return -ENOMEM;
776
777 pn->ctl_table[0].data = &sn->timeouts[SCTP_CONNTRACK_CLOSED];
778 pn->ctl_table[1].data = &sn->timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
779 pn->ctl_table[2].data = &sn->timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
780 pn->ctl_table[3].data = &sn->timeouts[SCTP_CONNTRACK_ESTABLISHED];
781 pn->ctl_table[4].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
782 pn->ctl_table[5].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
783 pn->ctl_table[6].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];
d7ee3519
MK
784 pn->ctl_table[7].data = &sn->timeouts[SCTP_CONNTRACK_HEARTBEAT_SENT];
785 pn->ctl_table[8].data = &sn->timeouts[SCTP_CONNTRACK_HEARTBEAT_ACKED];
49d485a3
G
786#endif
787 return 0;
788}
789
f42c4183
G
790static int sctp_kmemdup_compat_sysctl_table(struct nf_proto_net *pn,
791 struct sctp_net *sn)
49d485a3
G
792{
793#ifdef CONFIG_SYSCTL
794#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT
49d485a3
G
795 pn->ctl_compat_table = kmemdup(sctp_compat_sysctl_table,
796 sizeof(sctp_compat_sysctl_table),
797 GFP_KERNEL);
798 if (!pn->ctl_compat_table)
799 return -ENOMEM;
800
801 pn->ctl_compat_table[0].data = &sn->timeouts[SCTP_CONNTRACK_CLOSED];
802 pn->ctl_compat_table[1].data = &sn->timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
803 pn->ctl_compat_table[2].data = &sn->timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
804 pn->ctl_compat_table[3].data = &sn->timeouts[SCTP_CONNTRACK_ESTABLISHED];
805 pn->ctl_compat_table[4].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
806 pn->ctl_compat_table[5].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
807 pn->ctl_compat_table[6].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];
808#endif
809#endif
810 return 0;
811}
812
f42c4183 813static int sctp_init_net(struct net *net, u_int16_t proto)
49d485a3
G
814{
815 int ret;
816 struct sctp_net *sn = sctp_pernet(net);
f42c4183 817 struct nf_proto_net *pn = &sn->pn;
49d485a3 818
f42c4183
G
819 if (!pn->users) {
820 int i;
49d485a3 821
f42c4183
G
822 for (i = 0; i < SCTP_CONNTRACK_MAX; i++)
823 sn->timeouts[i] = sctp_timeouts[i];
824 }
49d485a3 825
f42c4183
G
826 if (proto == AF_INET) {
827 ret = sctp_kmemdup_compat_sysctl_table(pn, sn);
828 if (ret < 0)
829 return ret;
49d485a3 830
f42c4183
G
831 ret = sctp_kmemdup_sysctl_table(pn, sn);
832 if (ret < 0)
833 nf_ct_kfree_compat_sysctl_table(pn);
834 } else
835 ret = sctp_kmemdup_sysctl_table(pn, sn);
49d485a3 836
49d485a3
G
837 return ret;
838}
839
61075af5 840static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
933a41e7
PM
841 .l3proto = PF_INET,
842 .l4proto = IPPROTO_SCTP,
843 .name = "sctp",
844 .pkt_to_tuple = sctp_pkt_to_tuple,
845 .invert_tuple = sctp_invert_tuple,
846 .print_tuple = sctp_print_tuple,
847 .print_conntrack = sctp_print_conntrack,
848 .packet = sctp_packet,
2c8503f5 849 .get_timeouts = sctp_get_timeouts,
933a41e7
PM
850 .new = sctp_new,
851 .me = THIS_MODULE,
c0cd1156 852#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
a258860e 853 .to_nlattr = sctp_to_nlattr,
a400c30e 854 .nlattr_size = sctp_nlattr_size,
a258860e 855 .from_nlattr = nlattr_to_sctp,
c7212e9d 856 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
a400c30e 857 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
c7212e9d
PNA
858 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
859 .nla_policy = nf_ct_port_nla_policy,
860#endif
50978462
PNA
861#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
862 .ctnl_timeout = {
863 .nlattr_to_obj = sctp_timeout_nlattr_to_obj,
864 .obj_to_nlattr = sctp_timeout_obj_to_nlattr,
865 .nlattr_max = CTA_TIMEOUT_SCTP_MAX,
866 .obj_size = sizeof(unsigned int) * SCTP_CONNTRACK_MAX,
867 .nla_policy = sctp_timeout_nla_policy,
868 },
869#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
49d485a3 870 .net_id = &sctp_net_id,
f42c4183 871 .init_net = sctp_init_net,
9fb9cbb1
YK
872};
873
61075af5 874static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
933a41e7
PM
875 .l3proto = PF_INET6,
876 .l4proto = IPPROTO_SCTP,
877 .name = "sctp",
878 .pkt_to_tuple = sctp_pkt_to_tuple,
879 .invert_tuple = sctp_invert_tuple,
880 .print_tuple = sctp_print_tuple,
881 .print_conntrack = sctp_print_conntrack,
882 .packet = sctp_packet,
2c8503f5 883 .get_timeouts = sctp_get_timeouts,
933a41e7
PM
884 .new = sctp_new,
885 .me = THIS_MODULE,
c0cd1156 886#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
a258860e 887 .to_nlattr = sctp_to_nlattr,
a400c30e 888 .nlattr_size = sctp_nlattr_size,
a258860e 889 .from_nlattr = nlattr_to_sctp,
c7212e9d 890 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
a400c30e 891 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
c7212e9d
PNA
892 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
893 .nla_policy = nf_ct_port_nla_policy,
50978462
PNA
894#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
895 .ctnl_timeout = {
896 .nlattr_to_obj = sctp_timeout_nlattr_to_obj,
897 .obj_to_nlattr = sctp_timeout_obj_to_nlattr,
898 .nlattr_max = CTA_TIMEOUT_SCTP_MAX,
899 .obj_size = sizeof(unsigned int) * SCTP_CONNTRACK_MAX,
900 .nla_policy = sctp_timeout_nla_policy,
901 },
902#endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
9fb9cbb1 903#endif
49d485a3 904 .net_id = &sctp_net_id,
f42c4183 905 .init_net = sctp_init_net,
933a41e7 906};
9fb9cbb1 907
49d485a3 908static int sctp_net_init(struct net *net)
9fb9cbb1 909{
49d485a3 910 int ret = 0;
9fb9cbb1 911
c296bb4d 912 ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_sctp4);
49d485a3 913 if (ret < 0) {
c296bb4d 914 pr_err("nf_conntrack_sctp4: pernet registration failed.\n");
9fb9cbb1
YK
915 goto out;
916 }
c296bb4d 917 ret = nf_ct_l4proto_pernet_register(net, &nf_conntrack_l4proto_sctp6);
49d485a3 918 if (ret < 0) {
c296bb4d 919 pr_err("nf_conntrack_sctp6: pernet registration failed.\n");
9fb9cbb1
YK
920 goto cleanup_sctp4;
921 }
49d485a3 922 return 0;
9fb9cbb1 923
49d485a3 924cleanup_sctp4:
c296bb4d 925 nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_sctp4);
49d485a3 926out:
9fb9cbb1 927 return ret;
49d485a3 928}
9fb9cbb1 929
49d485a3
G
930static void sctp_net_exit(struct net *net)
931{
c296bb4d
G
932 nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_sctp6);
933 nf_ct_l4proto_pernet_unregister(net, &nf_conntrack_l4proto_sctp4);
49d485a3
G
934}
935
936static struct pernet_operations sctp_net_ops = {
937 .init = sctp_net_init,
938 .exit = sctp_net_exit,
939 .id = &sctp_net_id,
940 .size = sizeof(struct sctp_net),
941};
942
943static int __init nf_conntrack_proto_sctp_init(void)
944{
c296bb4d
G
945 int ret;
946
0d98da5d
G
947 ret = register_pernet_subsys(&sctp_net_ops);
948 if (ret < 0)
949 goto out_pernet;
950
c296bb4d
G
951 ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_sctp4);
952 if (ret < 0)
953 goto out_sctp4;
954
955 ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_sctp6);
956 if (ret < 0)
957 goto out_sctp6;
958
c296bb4d 959 return 0;
c296bb4d
G
960out_sctp6:
961 nf_ct_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
962out_sctp4:
0d98da5d
G
963 unregister_pernet_subsys(&sctp_net_ops);
964out_pernet:
c296bb4d 965 return ret;
9fb9cbb1
YK
966}
967
2f0d2f10 968static void __exit nf_conntrack_proto_sctp_fini(void)
9fb9cbb1 969{
c296bb4d
G
970 nf_ct_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
971 nf_ct_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
49d485a3 972 unregister_pernet_subsys(&sctp_net_ops);
9fb9cbb1
YK
973}
974
65b4b4e8
AM
975module_init(nf_conntrack_proto_sctp_init);
976module_exit(nf_conntrack_proto_sctp_fini);
9fb9cbb1
YK
977
978MODULE_LICENSE("GPL");
979MODULE_AUTHOR("Kiran Kumar Immidi");
980MODULE_DESCRIPTION("Netfilter connection tracking protocol helper for SCTP");
d2483dde 981MODULE_ALIAS("ip_conntrack_proto_sctp");
This page took 0.870165 seconds and 5 git commands to generate.