1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Connection tracking protocol helper module for SCTP. |
4 | * |
5 | * Copyright (c) 2004 Kiran Kumar Immidi <immidi_kiran@yahoo.com> |
6 | * Copyright (c) 2004-2012 Patrick McHardy <kaber@trash.net> |
7 | * |
8 | * SCTP is defined in RFC 2960. References to various sections in this code |
9 | * are to this RFC. |
10 | */ |
11 | |
12 | #include <linux/types.h> |
13 | #include <linux/timer.h> |
14 | #include <linux/netfilter.h> |
15 | #include <linux/in.h> |
16 | #include <linux/ip.h> |
17 | #include <linux/sctp.h> |
18 | #include <linux/string.h> |
19 | #include <linux/seq_file.h> |
20 | #include <linux/spinlock.h> |
21 | #include <linux/interrupt.h> |
22 | #include <net/sctp/checksum.h> |
23 | |
24 | #include <net/netfilter/nf_log.h> |
25 | #include <net/netfilter/nf_conntrack.h> |
26 | #include <net/netfilter/nf_conntrack_l4proto.h> |
27 | #include <net/netfilter/nf_conntrack_ecache.h> |
28 | #include <net/netfilter/nf_conntrack_timeout.h> |
29 | |
30 | static const char *const sctp_conntrack_names[] = { |
31 | [SCTP_CONNTRACK_NONE] = "NONE" , |
32 | [SCTP_CONNTRACK_CLOSED] = "CLOSED" , |
33 | [SCTP_CONNTRACK_COOKIE_WAIT] = "COOKIE_WAIT" , |
34 | [SCTP_CONNTRACK_COOKIE_ECHOED] = "COOKIE_ECHOED" , |
35 | [SCTP_CONNTRACK_ESTABLISHED] = "ESTABLISHED" , |
36 | [SCTP_CONNTRACK_SHUTDOWN_SENT] = "SHUTDOWN_SENT" , |
37 | [SCTP_CONNTRACK_SHUTDOWN_RECD] = "SHUTDOWN_RECD" , |
38 | [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = "SHUTDOWN_ACK_SENT" , |
39 | [SCTP_CONNTRACK_HEARTBEAT_SENT] = "HEARTBEAT_SENT" , |
40 | }; |
41 | |
42 | #define SECS * HZ |
43 | #define MINS * 60 SECS |
44 | #define HOURS * 60 MINS |
45 | #define DAYS * 24 HOURS |
46 | |
47 | static const unsigned int sctp_timeouts[SCTP_CONNTRACK_MAX] = { |
48 | [SCTP_CONNTRACK_CLOSED] = 10 SECS, |
49 | [SCTP_CONNTRACK_COOKIE_WAIT] = 3 SECS, |
50 | [SCTP_CONNTRACK_COOKIE_ECHOED] = 3 SECS, |
51 | [SCTP_CONNTRACK_ESTABLISHED] = 210 SECS, |
52 | [SCTP_CONNTRACK_SHUTDOWN_SENT] = 3 SECS, |
53 | [SCTP_CONNTRACK_SHUTDOWN_RECD] = 3 SECS, |
54 | [SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = 3 SECS, |
55 | [SCTP_CONNTRACK_HEARTBEAT_SENT] = 30 SECS, |
56 | }; |
57 | |
58 | #define SCTP_FLAG_HEARTBEAT_VTAG_FAILED 1 |
59 | |
60 | #define sNO SCTP_CONNTRACK_NONE |
61 | #define sCL SCTP_CONNTRACK_CLOSED |
62 | #define sCW SCTP_CONNTRACK_COOKIE_WAIT |
63 | #define sCE SCTP_CONNTRACK_COOKIE_ECHOED |
64 | #define sES SCTP_CONNTRACK_ESTABLISHED |
65 | #define sSS SCTP_CONNTRACK_SHUTDOWN_SENT |
66 | #define sSR SCTP_CONNTRACK_SHUTDOWN_RECD |
67 | #define sSA SCTP_CONNTRACK_SHUTDOWN_ACK_SENT |
68 | #define sHS SCTP_CONNTRACK_HEARTBEAT_SENT |
69 | #define sIV SCTP_CONNTRACK_MAX |
70 | |
71 | /* |
72 | These are the descriptions of the states: |
73 | |
74 | NOTE: These state names are tantalizingly similar to the states of an |
75 | SCTP endpoint. But the interpretation of the states is a little different, |
76 | considering that these are the states of the connection and not of an end |
77 | point. Please note the subtleties. -Kiran |
78 | |
79 | NONE - Nothing so far. |
80 | COOKIE WAIT - We have seen an INIT chunk in the original direction, or also |
81 | an INIT_ACK chunk in the reply direction. |
82 | COOKIE ECHOED - We have seen a COOKIE_ECHO chunk in the original direction. |
83 | ESTABLISHED - We have seen a COOKIE_ACK in the reply direction. |
84 | SHUTDOWN_SENT - We have seen a SHUTDOWN chunk in the original direction. |
85 | SHUTDOWN_RECD - We have seen a SHUTDOWN chunk in the reply direction. |
86 | SHUTDOWN_ACK_SENT - We have seen a SHUTDOWN_ACK chunk in the direction opposite |
87 | to that of the SHUTDOWN chunk. |
88 | CLOSED - We have seen a SHUTDOWN_COMPLETE chunk in the direction of |
89 | the SHUTDOWN chunk. Connection is closed. |
90 | HEARTBEAT_SENT - We have seen a HEARTBEAT in a new flow. |
91 | */ |
92 | |
93 | /* TODO |
94 | - I have assumed that the first INIT is in the original direction. |
95 | This messes things when an INIT comes in the reply direction in CLOSED |
96 | state. |
97 | - Check the error type in the reply dir before transitioning from |
98 | cookie echoed to closed. |
99 | - Sec 5.2.4 of RFC 2960 |
100 | - Full Multi Homing support. |
101 | */ |
102 | |
103 | /* SCTP conntrack state transitions */ |
104 | static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { |
105 | { |
106 | /* ORIGINAL */ |
107 | /* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS */ |
108 | /* init */ {sCL, sCL, sCW, sCE, sES, sCL, sCL, sSA, sCW}, |
109 | /* init_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL}, |
110 | /* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, |
111 | /* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA, sCL}, |
112 | /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA}, |
113 | /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't have Stale cookie*/ |
114 | /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA, sCL},/* 5.2.4 - Big TODO */ |
115 | /* cookie_ack */ {sCL, sCL, sCW, sES, sES, sSS, sSR, sSA, sCL},/* Can't come in orig dir */ |
116 | /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL}, |
117 | /* heartbeat */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, |
118 | /* heartbeat_ack*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, |
119 | }, |
120 | { |
121 | /* REPLY */ |
122 | /* sNO, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS */ |
123 | /* init */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV},/* INIT in sCL Big TODO */ |
124 | /* init_ack */ {sIV, sCW, sCW, sCE, sES, sSS, sSR, sSA, sIV}, |
125 | /* abort */ {sIV, sCL, sCL, sCL, sCL, sCL, sCL, sCL, sIV}, |
126 | /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV}, |
127 | /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV}, |
128 | /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA, sIV}, |
129 | /* cookie_echo */ {sIV, sCL, sCE, sCE, sES, sSS, sSR, sSA, sIV},/* Can't come in reply dir */ |
130 | /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV}, |
131 | /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV}, |
132 | /* heartbeat */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, |
133 | /* heartbeat_ack*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sES}, |
134 | } |
135 | }; |
136 | |
137 | #ifdef CONFIG_NF_CONNTRACK_PROCFS |
138 | /* Print out the private part of the conntrack. */ |
139 | static void sctp_print_conntrack(struct seq_file *s, struct nf_conn *ct) |
140 | { |
141 | seq_printf(m: s, fmt: "%s " , sctp_conntrack_names[ct->proto.sctp.state]); |
142 | } |
143 | #endif |
144 | |
145 | /* do_basic_checks ensures sch->length > 0, do not use before */ |
146 | #define for_each_sctp_chunk(skb, sch, _sch, offset, dataoff, count) \ |
147 | for ((offset) = (dataoff) + sizeof(struct sctphdr), (count) = 0; \ |
148 | (offset) < (skb)->len && \ |
149 | ((sch) = skb_header_pointer((skb), (offset), sizeof(_sch), &(_sch))); \ |
150 | (offset) += (ntohs((sch)->length) + 3) & ~3, (count)++) |
151 | |
152 | /* Some validity checks to make sure the chunks are fine */ |
153 | static int do_basic_checks(struct nf_conn *ct, |
154 | const struct sk_buff *skb, |
155 | unsigned int dataoff, |
156 | unsigned long *map, |
157 | const struct nf_hook_state *state) |
158 | { |
159 | u_int32_t offset, count; |
160 | struct sctp_chunkhdr _sch, *sch; |
161 | int flag; |
162 | |
163 | flag = 0; |
164 | |
165 | for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) { |
166 | if (sch->type == SCTP_CID_INIT || |
167 | sch->type == SCTP_CID_INIT_ACK || |
168 | sch->type == SCTP_CID_SHUTDOWN_COMPLETE) |
169 | flag = 1; |
170 | |
171 | /* |
172 | * Cookie Ack/Echo chunks not the first OR |
173 | * Init / Init Ack / Shutdown compl chunks not the only chunks |
174 | * OR zero-length. |
175 | */ |
176 | if (((sch->type == SCTP_CID_COOKIE_ACK || |
177 | sch->type == SCTP_CID_COOKIE_ECHO || |
178 | flag) && |
179 | count != 0) || !sch->length) { |
180 | nf_ct_l4proto_log_invalid(skb, ct, state, |
181 | fmt: "%s failed. chunk num %d, type %d, len %d flag %d\n" , |
182 | __func__, count, sch->type, sch->length, flag); |
183 | return 1; |
184 | } |
185 | |
186 | if (map) |
187 | set_bit(nr: sch->type, addr: map); |
188 | } |
189 | |
190 | return count == 0; |
191 | } |
192 | |
193 | static int sctp_new_state(enum ip_conntrack_dir dir, |
194 | enum sctp_conntrack cur_state, |
195 | int chunk_type) |
196 | { |
197 | int i; |
198 | |
199 | switch (chunk_type) { |
200 | case SCTP_CID_INIT: |
201 | i = 0; |
202 | break; |
203 | case SCTP_CID_INIT_ACK: |
204 | i = 1; |
205 | break; |
206 | case SCTP_CID_ABORT: |
207 | i = 2; |
208 | break; |
209 | case SCTP_CID_SHUTDOWN: |
210 | i = 3; |
211 | break; |
212 | case SCTP_CID_SHUTDOWN_ACK: |
213 | i = 4; |
214 | break; |
215 | case SCTP_CID_ERROR: |
216 | i = 5; |
217 | break; |
218 | case SCTP_CID_COOKIE_ECHO: |
219 | i = 6; |
220 | break; |
221 | case SCTP_CID_COOKIE_ACK: |
222 | i = 7; |
223 | break; |
224 | case SCTP_CID_SHUTDOWN_COMPLETE: |
225 | i = 8; |
226 | break; |
227 | case SCTP_CID_HEARTBEAT: |
228 | i = 9; |
229 | break; |
230 | case SCTP_CID_HEARTBEAT_ACK: |
231 | i = 10; |
232 | break; |
233 | default: |
234 | /* Other chunks like DATA or SACK do not change the state */ |
235 | pr_debug("Unknown chunk type %d, Will stay in %s\n" , |
236 | chunk_type, sctp_conntrack_names[cur_state]); |
237 | return cur_state; |
238 | } |
239 | |
240 | return sctp_conntracks[dir][i][cur_state]; |
241 | } |
242 | |
243 | /* Don't need lock here: this conntrack not in circulation yet */ |
244 | static noinline bool |
245 | sctp_new(struct nf_conn *ct, const struct sk_buff *skb, |
246 | const struct sctphdr *sh, unsigned int dataoff) |
247 | { |
248 | enum sctp_conntrack new_state; |
249 | const struct sctp_chunkhdr *sch; |
250 | struct sctp_chunkhdr _sch; |
251 | u32 offset, count; |
252 | |
253 | memset(&ct->proto.sctp, 0, sizeof(ct->proto.sctp)); |
254 | new_state = SCTP_CONNTRACK_MAX; |
255 | for_each_sctp_chunk(skb, sch, _sch, offset, dataoff, count) { |
256 | new_state = sctp_new_state(dir: IP_CT_DIR_ORIGINAL, |
257 | cur_state: SCTP_CONNTRACK_NONE, chunk_type: sch->type); |
258 | |
259 | /* Invalid: delete conntrack */ |
260 | if (new_state == SCTP_CONNTRACK_NONE || |
261 | new_state == SCTP_CONNTRACK_MAX) { |
262 | pr_debug("nf_conntrack_sctp: invalid new deleting.\n" ); |
263 | return false; |
264 | } |
265 | |
266 | /* Copy the vtag into the state info */ |
267 | if (sch->type == SCTP_CID_INIT) { |
268 | struct sctp_inithdr _inithdr, *ih; |
269 | /* Sec 8.5.1 (A) */ |
270 | if (sh->vtag) |
271 | return false; |
272 | |
273 | ih = skb_header_pointer(skb, offset: offset + sizeof(_sch), |
274 | len: sizeof(_inithdr), buffer: &_inithdr); |
275 | if (!ih) |
276 | return false; |
277 | |
278 | pr_debug("Setting vtag %x for new conn\n" , |
279 | ih->init_tag); |
280 | |
281 | ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = ih->init_tag; |
282 | } else if (sch->type == SCTP_CID_HEARTBEAT) { |
283 | pr_debug("Setting vtag %x for secondary conntrack\n" , |
284 | sh->vtag); |
285 | ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = sh->vtag; |
286 | } else { |
287 | /* If it is a shutdown ack OOTB packet, we expect a return |
288 | shutdown complete, otherwise an ABORT Sec 8.4 (5) and (8) */ |
289 | pr_debug("Setting vtag %x for new conn OOTB\n" , |
290 | sh->vtag); |
291 | ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = sh->vtag; |
292 | } |
293 | |
294 | ct->proto.sctp.state = SCTP_CONNTRACK_NONE; |
295 | } |
296 | |
297 | return true; |
298 | } |
299 | |
300 | static bool sctp_error(struct sk_buff *skb, |
301 | unsigned int dataoff, |
302 | const struct nf_hook_state *state) |
303 | { |
304 | const struct sctphdr *sh; |
305 | const char *logmsg; |
306 | |
307 | if (skb->len < dataoff + sizeof(struct sctphdr)) { |
308 | logmsg = "nf_ct_sctp: short packet " ; |
309 | goto out_invalid; |
310 | } |
311 | if (state->hook == NF_INET_PRE_ROUTING && |
312 | state->net->ct.sysctl_checksum && |
313 | skb->ip_summed == CHECKSUM_NONE) { |
314 | if (skb_ensure_writable(skb, write_len: dataoff + sizeof(*sh))) { |
315 | logmsg = "nf_ct_sctp: failed to read header " ; |
316 | goto out_invalid; |
317 | } |
318 | sh = (const struct sctphdr *)(skb->data + dataoff); |
319 | if (sh->checksum != sctp_compute_cksum(skb, offset: dataoff)) { |
320 | logmsg = "nf_ct_sctp: bad CRC " ; |
321 | goto out_invalid; |
322 | } |
323 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
324 | } |
325 | return false; |
326 | out_invalid: |
327 | nf_l4proto_log_invalid(skb, state, IPPROTO_SCTP, fmt: "%s" , logmsg); |
328 | return true; |
329 | } |
330 | |
331 | /* Returns verdict for packet, or -NF_ACCEPT for invalid. */ |
332 | int nf_conntrack_sctp_packet(struct nf_conn *ct, |
333 | struct sk_buff *skb, |
334 | unsigned int dataoff, |
335 | enum ip_conntrack_info ctinfo, |
336 | const struct nf_hook_state *state) |
337 | { |
338 | enum sctp_conntrack new_state, old_state; |
339 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
340 | const struct sctphdr *sh; |
341 | struct sctphdr _sctph; |
342 | const struct sctp_chunkhdr *sch; |
343 | struct sctp_chunkhdr _sch; |
344 | u_int32_t offset, count; |
345 | unsigned int *timeouts; |
346 | unsigned long map[256 / sizeof(unsigned long)] = { 0 }; |
347 | bool ignore = false; |
348 | |
349 | if (sctp_error(skb, dataoff, state)) |
350 | return -NF_ACCEPT; |
351 | |
352 | sh = skb_header_pointer(skb, offset: dataoff, len: sizeof(_sctph), buffer: &_sctph); |
353 | if (sh == NULL) |
354 | goto out; |
355 | |
356 | if (do_basic_checks(ct, skb, dataoff, map, state) != 0) |
357 | goto out; |
358 | |
359 | if (!nf_ct_is_confirmed(ct)) { |
360 | /* If an OOTB packet has any of these chunks discard (Sec 8.4) */ |
361 | if (test_bit(SCTP_CID_ABORT, map) || |
362 | test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) || |
363 | test_bit(SCTP_CID_COOKIE_ACK, map)) |
364 | return -NF_ACCEPT; |
365 | |
366 | if (!sctp_new(ct, skb, sh, dataoff)) |
367 | return -NF_ACCEPT; |
368 | } |
369 | |
370 | /* Check the verification tag (Sec 8.5) */ |
371 | if (!test_bit(SCTP_CID_INIT, map) && |
372 | !test_bit(SCTP_CID_SHUTDOWN_COMPLETE, map) && |
373 | !test_bit(SCTP_CID_COOKIE_ECHO, map) && |
374 | !test_bit(SCTP_CID_ABORT, map) && |
375 | !test_bit(SCTP_CID_SHUTDOWN_ACK, map) && |
376 | !test_bit(SCTP_CID_HEARTBEAT, map) && |
377 | !test_bit(SCTP_CID_HEARTBEAT_ACK, map) && |
378 | sh->vtag != ct->proto.sctp.vtag[dir]) { |
379 | nf_ct_l4proto_log_invalid(skb, ct, state, |
380 | fmt: "verification tag check failed %x vs %x for dir %d" , |
381 | sh->vtag, ct->proto.sctp.vtag[dir], dir); |
382 | goto out; |
383 | } |
384 | |
385 | old_state = new_state = SCTP_CONNTRACK_NONE; |
386 | spin_lock_bh(lock: &ct->lock); |
387 | for_each_sctp_chunk (skb, sch, _sch, offset, dataoff, count) { |
388 | /* Special cases of Verification tag check (Sec 8.5.1) */ |
389 | if (sch->type == SCTP_CID_INIT) { |
390 | /* (A) vtag MUST be zero */ |
391 | if (sh->vtag != 0) |
392 | goto out_unlock; |
393 | } else if (sch->type == SCTP_CID_ABORT) { |
394 | /* (B) vtag MUST match own vtag if T flag is unset OR |
395 | * MUST match peer's vtag if T flag is set |
396 | */ |
397 | if ((!(sch->flags & SCTP_CHUNK_FLAG_T) && |
398 | sh->vtag != ct->proto.sctp.vtag[dir]) || |
399 | ((sch->flags & SCTP_CHUNK_FLAG_T) && |
400 | sh->vtag != ct->proto.sctp.vtag[!dir])) |
401 | goto out_unlock; |
402 | } else if (sch->type == SCTP_CID_SHUTDOWN_COMPLETE) { |
403 | /* (C) vtag MUST match own vtag if T flag is unset OR |
404 | * MUST match peer's vtag if T flag is set |
405 | */ |
406 | if ((!(sch->flags & SCTP_CHUNK_FLAG_T) && |
407 | sh->vtag != ct->proto.sctp.vtag[dir]) || |
408 | ((sch->flags & SCTP_CHUNK_FLAG_T) && |
409 | sh->vtag != ct->proto.sctp.vtag[!dir])) |
410 | goto out_unlock; |
411 | } else if (sch->type == SCTP_CID_COOKIE_ECHO) { |
412 | /* (D) vtag must be same as init_vtag as found in INIT_ACK */ |
413 | if (sh->vtag != ct->proto.sctp.vtag[dir]) |
414 | goto out_unlock; |
415 | } else if (sch->type == SCTP_CID_COOKIE_ACK) { |
416 | ct->proto.sctp.init[dir] = 0; |
417 | ct->proto.sctp.init[!dir] = 0; |
418 | } else if (sch->type == SCTP_CID_HEARTBEAT) { |
419 | if (ct->proto.sctp.vtag[dir] == 0) { |
420 | pr_debug("Setting %d vtag %x for dir %d\n" , sch->type, sh->vtag, dir); |
421 | ct->proto.sctp.vtag[dir] = sh->vtag; |
422 | } else if (sh->vtag != ct->proto.sctp.vtag[dir]) { |
423 | if (test_bit(SCTP_CID_DATA, map) || ignore) |
424 | goto out_unlock; |
425 | |
426 | ct->proto.sctp.flags |= SCTP_FLAG_HEARTBEAT_VTAG_FAILED; |
427 | ct->proto.sctp.last_dir = dir; |
428 | ignore = true; |
429 | continue; |
430 | } else if (ct->proto.sctp.flags & SCTP_FLAG_HEARTBEAT_VTAG_FAILED) { |
431 | ct->proto.sctp.flags &= ~SCTP_FLAG_HEARTBEAT_VTAG_FAILED; |
432 | } |
433 | } else if (sch->type == SCTP_CID_HEARTBEAT_ACK) { |
434 | if (ct->proto.sctp.vtag[dir] == 0) { |
435 | pr_debug("Setting vtag %x for dir %d\n" , |
436 | sh->vtag, dir); |
437 | ct->proto.sctp.vtag[dir] = sh->vtag; |
438 | } else if (sh->vtag != ct->proto.sctp.vtag[dir]) { |
439 | if (test_bit(SCTP_CID_DATA, map) || ignore) |
440 | goto out_unlock; |
441 | |
442 | if ((ct->proto.sctp.flags & SCTP_FLAG_HEARTBEAT_VTAG_FAILED) == 0 || |
443 | ct->proto.sctp.last_dir == dir) |
444 | goto out_unlock; |
445 | |
446 | ct->proto.sctp.flags &= ~SCTP_FLAG_HEARTBEAT_VTAG_FAILED; |
447 | ct->proto.sctp.vtag[dir] = sh->vtag; |
448 | ct->proto.sctp.vtag[!dir] = 0; |
449 | } else if (ct->proto.sctp.flags & SCTP_FLAG_HEARTBEAT_VTAG_FAILED) { |
450 | ct->proto.sctp.flags &= ~SCTP_FLAG_HEARTBEAT_VTAG_FAILED; |
451 | } |
452 | } |
453 | |
454 | old_state = ct->proto.sctp.state; |
455 | new_state = sctp_new_state(dir, cur_state: old_state, chunk_type: sch->type); |
456 | |
457 | /* Invalid */ |
458 | if (new_state == SCTP_CONNTRACK_MAX) { |
459 | nf_ct_l4proto_log_invalid(skb, ct, state, |
460 | fmt: "Invalid, old_state %d, dir %d, type %d" , |
461 | old_state, dir, sch->type); |
462 | |
463 | goto out_unlock; |
464 | } |
465 | |
466 | /* If it is an INIT or an INIT ACK note down the vtag */ |
467 | if (sch->type == SCTP_CID_INIT) { |
468 | struct sctp_inithdr _ih, *ih; |
469 | |
470 | ih = skb_header_pointer(skb, offset: offset + sizeof(_sch), len: sizeof(*ih), buffer: &_ih); |
471 | if (!ih) |
472 | goto out_unlock; |
473 | |
474 | if (ct->proto.sctp.init[dir] && ct->proto.sctp.init[!dir]) |
475 | ct->proto.sctp.init[!dir] = 0; |
476 | ct->proto.sctp.init[dir] = 1; |
477 | |
478 | pr_debug("Setting vtag %x for dir %d\n" , ih->init_tag, !dir); |
479 | ct->proto.sctp.vtag[!dir] = ih->init_tag; |
480 | |
481 | /* don't renew timeout on init retransmit so |
482 | * port reuse by client or NAT middlebox cannot |
483 | * keep entry alive indefinitely (incl. nat info). |
484 | */ |
485 | if (new_state == SCTP_CONNTRACK_CLOSED && |
486 | old_state == SCTP_CONNTRACK_CLOSED && |
487 | nf_ct_is_confirmed(ct)) |
488 | ignore = true; |
489 | } else if (sch->type == SCTP_CID_INIT_ACK) { |
490 | struct sctp_inithdr _ih, *ih; |
491 | __be32 vtag; |
492 | |
493 | ih = skb_header_pointer(skb, offset: offset + sizeof(_sch), len: sizeof(*ih), buffer: &_ih); |
494 | if (!ih) |
495 | goto out_unlock; |
496 | |
497 | vtag = ct->proto.sctp.vtag[!dir]; |
498 | if (!ct->proto.sctp.init[!dir] && vtag && vtag != ih->init_tag) |
499 | goto out_unlock; |
500 | /* collision */ |
501 | if (ct->proto.sctp.init[dir] && ct->proto.sctp.init[!dir] && |
502 | vtag != ih->init_tag) |
503 | goto out_unlock; |
504 | |
505 | pr_debug("Setting vtag %x for dir %d\n" , ih->init_tag, !dir); |
506 | ct->proto.sctp.vtag[!dir] = ih->init_tag; |
507 | } |
508 | |
509 | ct->proto.sctp.state = new_state; |
510 | if (old_state != new_state) { |
511 | nf_conntrack_event_cache(event: IPCT_PROTOINFO, ct); |
512 | if (new_state == SCTP_CONNTRACK_ESTABLISHED && |
513 | !test_and_set_bit(nr: IPS_ASSURED_BIT, addr: &ct->status)) |
514 | nf_conntrack_event_cache(event: IPCT_ASSURED, ct); |
515 | } |
516 | } |
517 | spin_unlock_bh(lock: &ct->lock); |
518 | |
519 | /* allow but do not refresh timeout */ |
520 | if (ignore) |
521 | return NF_ACCEPT; |
522 | |
523 | timeouts = nf_ct_timeout_lookup(ct); |
524 | if (!timeouts) |
525 | timeouts = nf_sctp_pernet(net: nf_ct_net(ct))->timeouts; |
526 | |
527 | nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies: timeouts[new_state]); |
528 | |
529 | return NF_ACCEPT; |
530 | |
531 | out_unlock: |
532 | spin_unlock_bh(lock: &ct->lock); |
533 | out: |
534 | return -NF_ACCEPT; |
535 | } |
536 | |
537 | static bool sctp_can_early_drop(const struct nf_conn *ct) |
538 | { |
539 | switch (ct->proto.sctp.state) { |
540 | case SCTP_CONNTRACK_SHUTDOWN_SENT: |
541 | case SCTP_CONNTRACK_SHUTDOWN_RECD: |
542 | case SCTP_CONNTRACK_SHUTDOWN_ACK_SENT: |
543 | return true; |
544 | default: |
545 | break; |
546 | } |
547 | |
548 | return false; |
549 | } |
550 | |
551 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
552 | |
553 | #include <linux/netfilter/nfnetlink.h> |
554 | #include <linux/netfilter/nfnetlink_conntrack.h> |
555 | |
556 | static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla, |
557 | struct nf_conn *ct, bool destroy) |
558 | { |
559 | struct nlattr *nest_parms; |
560 | |
561 | spin_lock_bh(lock: &ct->lock); |
562 | nest_parms = nla_nest_start(skb, attrtype: CTA_PROTOINFO_SCTP); |
563 | if (!nest_parms) |
564 | goto nla_put_failure; |
565 | |
566 | if (nla_put_u8(skb, attrtype: CTA_PROTOINFO_SCTP_STATE, value: ct->proto.sctp.state)) |
567 | goto nla_put_failure; |
568 | |
569 | if (destroy) |
570 | goto skip_state; |
571 | |
572 | if (nla_put_be32(skb, attrtype: CTA_PROTOINFO_SCTP_VTAG_ORIGINAL, |
573 | value: ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL]) || |
574 | nla_put_be32(skb, attrtype: CTA_PROTOINFO_SCTP_VTAG_REPLY, |
575 | value: ct->proto.sctp.vtag[IP_CT_DIR_REPLY])) |
576 | goto nla_put_failure; |
577 | |
578 | skip_state: |
579 | spin_unlock_bh(lock: &ct->lock); |
580 | nla_nest_end(skb, start: nest_parms); |
581 | |
582 | return 0; |
583 | |
584 | nla_put_failure: |
585 | spin_unlock_bh(lock: &ct->lock); |
586 | return -1; |
587 | } |
588 | |
589 | static const struct nla_policy sctp_nla_policy[CTA_PROTOINFO_SCTP_MAX+1] = { |
590 | [CTA_PROTOINFO_SCTP_STATE] = { .type = NLA_U8 }, |
591 | [CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] = { .type = NLA_U32 }, |
592 | [CTA_PROTOINFO_SCTP_VTAG_REPLY] = { .type = NLA_U32 }, |
593 | }; |
594 | |
595 | #define SCTP_NLATTR_SIZE ( \ |
596 | NLA_ALIGN(NLA_HDRLEN + 1) + \ |
597 | NLA_ALIGN(NLA_HDRLEN + 4) + \ |
598 | NLA_ALIGN(NLA_HDRLEN + 4)) |
599 | |
600 | static int nlattr_to_sctp(struct nlattr *cda[], struct nf_conn *ct) |
601 | { |
602 | struct nlattr *attr = cda[CTA_PROTOINFO_SCTP]; |
603 | struct nlattr *tb[CTA_PROTOINFO_SCTP_MAX+1]; |
604 | int err; |
605 | |
606 | /* updates may not contain the internal protocol info, skip parsing */ |
607 | if (!attr) |
608 | return 0; |
609 | |
610 | err = nla_parse_nested_deprecated(tb, CTA_PROTOINFO_SCTP_MAX, nla: attr, |
611 | policy: sctp_nla_policy, NULL); |
612 | if (err < 0) |
613 | return err; |
614 | |
615 | if (!tb[CTA_PROTOINFO_SCTP_STATE] || |
616 | !tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] || |
617 | !tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]) |
618 | return -EINVAL; |
619 | |
620 | spin_lock_bh(lock: &ct->lock); |
621 | ct->proto.sctp.state = nla_get_u8(nla: tb[CTA_PROTOINFO_SCTP_STATE]); |
622 | ct->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = |
623 | nla_get_be32(nla: tb[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]); |
624 | ct->proto.sctp.vtag[IP_CT_DIR_REPLY] = |
625 | nla_get_be32(nla: tb[CTA_PROTOINFO_SCTP_VTAG_REPLY]); |
626 | spin_unlock_bh(lock: &ct->lock); |
627 | |
628 | return 0; |
629 | } |
630 | #endif |
631 | |
632 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
633 | |
634 | #include <linux/netfilter/nfnetlink.h> |
635 | #include <linux/netfilter/nfnetlink_cttimeout.h> |
636 | |
637 | static int sctp_timeout_nlattr_to_obj(struct nlattr *tb[], |
638 | struct net *net, void *data) |
639 | { |
640 | unsigned int *timeouts = data; |
641 | struct nf_sctp_net *sn = nf_sctp_pernet(net); |
642 | int i; |
643 | |
644 | if (!timeouts) |
645 | timeouts = sn->timeouts; |
646 | |
647 | /* set default SCTP timeouts. */ |
648 | for (i=0; i<SCTP_CONNTRACK_MAX; i++) |
649 | timeouts[i] = sn->timeouts[i]; |
650 | |
651 | /* there's a 1:1 mapping between attributes and protocol states. */ |
652 | for (i=CTA_TIMEOUT_SCTP_UNSPEC+1; i<CTA_TIMEOUT_SCTP_MAX+1; i++) { |
653 | if (tb[i]) { |
654 | timeouts[i] = ntohl(nla_get_be32(tb[i])) * HZ; |
655 | } |
656 | } |
657 | |
658 | timeouts[CTA_TIMEOUT_SCTP_UNSPEC] = timeouts[CTA_TIMEOUT_SCTP_CLOSED]; |
659 | return 0; |
660 | } |
661 | |
662 | static int |
663 | sctp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) |
664 | { |
665 | const unsigned int *timeouts = data; |
666 | int i; |
667 | |
668 | for (i=CTA_TIMEOUT_SCTP_UNSPEC+1; i<CTA_TIMEOUT_SCTP_MAX+1; i++) { |
669 | if (nla_put_be32(skb, attrtype: i, htonl(timeouts[i] / HZ))) |
670 | goto nla_put_failure; |
671 | } |
672 | return 0; |
673 | |
674 | nla_put_failure: |
675 | return -ENOSPC; |
676 | } |
677 | |
678 | static const struct nla_policy |
679 | sctp_timeout_nla_policy[CTA_TIMEOUT_SCTP_MAX+1] = { |
680 | [CTA_TIMEOUT_SCTP_CLOSED] = { .type = NLA_U32 }, |
681 | [CTA_TIMEOUT_SCTP_COOKIE_WAIT] = { .type = NLA_U32 }, |
682 | [CTA_TIMEOUT_SCTP_COOKIE_ECHOED] = { .type = NLA_U32 }, |
683 | [CTA_TIMEOUT_SCTP_ESTABLISHED] = { .type = NLA_U32 }, |
684 | [CTA_TIMEOUT_SCTP_SHUTDOWN_SENT] = { .type = NLA_U32 }, |
685 | [CTA_TIMEOUT_SCTP_SHUTDOWN_RECD] = { .type = NLA_U32 }, |
686 | [CTA_TIMEOUT_SCTP_SHUTDOWN_ACK_SENT] = { .type = NLA_U32 }, |
687 | [CTA_TIMEOUT_SCTP_HEARTBEAT_SENT] = { .type = NLA_U32 }, |
688 | [CTA_TIMEOUT_SCTP_HEARTBEAT_ACKED] = { .type = NLA_U32 }, |
689 | }; |
690 | #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ |
691 | |
692 | void nf_conntrack_sctp_init_net(struct net *net) |
693 | { |
694 | struct nf_sctp_net *sn = nf_sctp_pernet(net); |
695 | int i; |
696 | |
697 | for (i = 0; i < SCTP_CONNTRACK_MAX; i++) |
698 | sn->timeouts[i] = sctp_timeouts[i]; |
699 | |
700 | /* timeouts[0] is unused, init it so ->timeouts[0] contains |
701 | * 'new' timeout, like udp or icmp. |
702 | */ |
703 | sn->timeouts[0] = sctp_timeouts[SCTP_CONNTRACK_CLOSED]; |
704 | } |
705 | |
706 | const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp = { |
707 | .l4proto = IPPROTO_SCTP, |
708 | #ifdef CONFIG_NF_CONNTRACK_PROCFS |
709 | .print_conntrack = sctp_print_conntrack, |
710 | #endif |
711 | .can_early_drop = sctp_can_early_drop, |
712 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
713 | .nlattr_size = SCTP_NLATTR_SIZE, |
714 | .to_nlattr = sctp_to_nlattr, |
715 | .from_nlattr = nlattr_to_sctp, |
716 | .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, |
717 | .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, |
718 | .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, |
719 | .nla_policy = nf_ct_port_nla_policy, |
720 | #endif |
721 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
722 | .ctnl_timeout = { |
723 | .nlattr_to_obj = sctp_timeout_nlattr_to_obj, |
724 | .obj_to_nlattr = sctp_timeout_obj_to_nlattr, |
725 | .nlattr_max = CTA_TIMEOUT_SCTP_MAX, |
726 | .obj_size = sizeof(unsigned int) * SCTP_CONNTRACK_MAX, |
727 | .nla_policy = sctp_timeout_nla_policy, |
728 | }, |
729 | #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ |
730 | }; |
731 | |