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