1
2
3
4
5
6
7
8
9
10
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/sysctl.h>
14#include <linux/spinlock.h>
15#include <linux/skbuff.h>
16#include <linux/dccp.h>
17#include <linux/slab.h>
18
19#include <net/net_namespace.h>
20#include <net/netns/generic.h>
21
22#include <linux/netfilter/nfnetlink_conntrack.h>
23#include <net/netfilter/nf_conntrack.h>
24#include <net/netfilter/nf_conntrack_l4proto.h>
25#include <net/netfilter/nf_conntrack_ecache.h>
26#include <net/netfilter/nf_log.h>
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73#define DCCP_MSL (2 * 60 * HZ)
74
75static const char * const dccp_state_names[] = {
76 [CT_DCCP_NONE] = "NONE",
77 [CT_DCCP_REQUEST] = "REQUEST",
78 [CT_DCCP_RESPOND] = "RESPOND",
79 [CT_DCCP_PARTOPEN] = "PARTOPEN",
80 [CT_DCCP_OPEN] = "OPEN",
81 [CT_DCCP_CLOSEREQ] = "CLOSEREQ",
82 [CT_DCCP_CLOSING] = "CLOSING",
83 [CT_DCCP_TIMEWAIT] = "TIMEWAIT",
84 [CT_DCCP_IGNORE] = "IGNORE",
85 [CT_DCCP_INVALID] = "INVALID",
86};
87
88#define sNO CT_DCCP_NONE
89#define sRQ CT_DCCP_REQUEST
90#define sRS CT_DCCP_RESPOND
91#define sPO CT_DCCP_PARTOPEN
92#define sOP CT_DCCP_OPEN
93#define sCR CT_DCCP_CLOSEREQ
94#define sCG CT_DCCP_CLOSING
95#define sTW CT_DCCP_TIMEWAIT
96#define sIG CT_DCCP_IGNORE
97#define sIV CT_DCCP_INVALID
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131static const u_int8_t
132dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = {
133 [CT_DCCP_ROLE_CLIENT] = {
134 [DCCP_PKT_REQUEST] = {
135
136
137
138
139
140
141
142
143
144
145
146
147 sRQ, sRQ, sRS, sIG, sIG, sIG, sIG, sRQ,
148 },
149 [DCCP_PKT_RESPONSE] = {
150
151
152
153
154
155
156
157
158
159
160
161
162 sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIV,
163 },
164 [DCCP_PKT_ACK] = {
165
166
167
168
169
170
171
172
173
174
175
176 sIV, sIV, sPO, sPO, sOP, sCR, sCG, sIV
177 },
178 [DCCP_PKT_DATA] = {
179
180
181
182
183
184
185
186
187
188
189
190 sIV, sIV, sIV, sIV, sOP, sCR, sCG, sIV,
191 },
192 [DCCP_PKT_DATAACK] = {
193
194
195
196
197
198
199
200
201
202
203
204 sIV, sIV, sPO, sPO, sOP, sCR, sCG, sIV
205 },
206 [DCCP_PKT_CLOSEREQ] = {
207
208
209
210
211 sIV, sIV, sIV, sIV, sIV, sIV, sIV, sIV
212 },
213 [DCCP_PKT_CLOSE] = {
214
215
216
217
218
219
220
221
222
223
224
225 sIV, sIV, sIV, sCG, sCG, sCG, sIV, sIV
226 },
227 [DCCP_PKT_RESET] = {
228
229
230
231
232
233
234
235
236
237
238
239 sIV, sTW, sTW, sTW, sTW, sTW, sTW, sIG
240 },
241 [DCCP_PKT_SYNC] = {
242
243
244
245
246 sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
247 },
248 [DCCP_PKT_SYNCACK] = {
249
250
251
252
253 sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
254 },
255 },
256 [CT_DCCP_ROLE_SERVER] = {
257 [DCCP_PKT_REQUEST] = {
258
259
260
261
262
263
264
265
266
267
268
269 sIV, sIG, sIG, sIG, sIG, sIG, sIG, sRQ
270 },
271 [DCCP_PKT_RESPONSE] = {
272
273
274
275
276
277
278
279
280
281
282
283 sIV, sRS, sRS, sIG, sIG, sIG, sIG, sIV
284 },
285 [DCCP_PKT_ACK] = {
286
287
288
289
290
291
292
293
294
295
296
297 sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV
298 },
299 [DCCP_PKT_DATA] = {
300
301
302
303
304
305
306
307
308
309
310
311 sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV
312 },
313 [DCCP_PKT_DATAACK] = {
314
315
316
317
318
319
320
321
322
323
324
325 sIV, sIV, sIV, sOP, sOP, sIV, sCG, sIV
326 },
327 [DCCP_PKT_CLOSEREQ] = {
328
329
330
331
332
333
334
335
336
337
338
339 sIV, sIV, sIV, sCR, sCR, sCR, sCR, sIV
340 },
341 [DCCP_PKT_CLOSE] = {
342
343
344
345
346
347
348
349
350
351
352
353 sIV, sIV, sIV, sCG, sCG, sIV, sCG, sIV
354 },
355 [DCCP_PKT_RESET] = {
356
357
358
359
360
361
362
363
364
365
366
367 sIV, sTW, sTW, sTW, sTW, sTW, sTW, sTW, sIG
368 },
369 [DCCP_PKT_SYNC] = {
370
371
372
373
374 sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
375 },
376 [DCCP_PKT_SYNCACK] = {
377
378
379
380
381 sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG,
382 },
383 },
384};
385
386static inline struct nf_dccp_net *dccp_pernet(struct net *net)
387{
388 return &net->ct.nf_ct_proto.dccp;
389}
390
391static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
392 struct net *net, struct nf_conntrack_tuple *tuple)
393{
394 struct dccp_hdr _hdr, *dh;
395
396
397 dh = skb_header_pointer(skb, dataoff, 4, &_hdr);
398 if (dh == NULL)
399 return false;
400
401 tuple->src.u.dccp.port = dh->dccph_sport;
402 tuple->dst.u.dccp.port = dh->dccph_dport;
403 return true;
404}
405
406static bool dccp_invert_tuple(struct nf_conntrack_tuple *inv,
407 const struct nf_conntrack_tuple *tuple)
408{
409 inv->src.u.dccp.port = tuple->dst.u.dccp.port;
410 inv->dst.u.dccp.port = tuple->src.u.dccp.port;
411 return true;
412}
413
414static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
415 unsigned int dataoff, unsigned int *timeouts)
416{
417 struct net *net = nf_ct_net(ct);
418 struct nf_dccp_net *dn;
419 struct dccp_hdr _dh, *dh;
420 const char *msg;
421 u_int8_t state;
422
423 dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
424 BUG_ON(dh == NULL);
425
426 state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE];
427 switch (state) {
428 default:
429 dn = dccp_pernet(net);
430 if (dn->dccp_loose == 0) {
431 msg = "nf_ct_dccp: not picking up existing connection ";
432 goto out_invalid;
433 }
434 case CT_DCCP_REQUEST:
435 break;
436 case CT_DCCP_INVALID:
437 msg = "nf_ct_dccp: invalid state transition ";
438 goto out_invalid;
439 }
440
441 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT;
442 ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER;
443 ct->proto.dccp.state = CT_DCCP_NONE;
444 ct->proto.dccp.last_pkt = DCCP_PKT_REQUEST;
445 ct->proto.dccp.last_dir = IP_CT_DIR_ORIGINAL;
446 ct->proto.dccp.handshake_seq = 0;
447 return true;
448
449out_invalid:
450 if (LOG_INVALID(net, IPPROTO_DCCP))
451 nf_log_packet(net, nf_ct_l3num(ct), 0, skb, NULL, NULL,
452 NULL, "%s", msg);
453 return false;
454}
455
456static u64 dccp_ack_seq(const struct dccp_hdr *dh)
457{
458 const struct dccp_hdr_ack_bits *dhack;
459
460 dhack = (void *)dh + __dccp_basic_hdr_len(dh);
461 return ((u64)ntohs(dhack->dccph_ack_nr_high) << 32) +
462 ntohl(dhack->dccph_ack_nr_low);
463}
464
465static unsigned int *dccp_get_timeouts(struct net *net)
466{
467 return dccp_pernet(net)->dccp_timeout;
468}
469
470static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
471 unsigned int dataoff, enum ip_conntrack_info ctinfo,
472 u_int8_t pf, unsigned int hooknum,
473 unsigned int *timeouts)
474{
475 struct net *net = nf_ct_net(ct);
476 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
477 struct dccp_hdr _dh, *dh;
478 u_int8_t type, old_state, new_state;
479 enum ct_dccp_roles role;
480
481 dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
482 BUG_ON(dh == NULL);
483 type = dh->dccph_type;
484
485 if (type == DCCP_PKT_RESET &&
486 !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
487
488 nf_ct_kill_acct(ct, ctinfo, skb);
489 return NF_ACCEPT;
490 }
491
492 spin_lock_bh(&ct->lock);
493
494 role = ct->proto.dccp.role[dir];
495 old_state = ct->proto.dccp.state;
496 new_state = dccp_state_table[role][type][old_state];
497
498 switch (new_state) {
499 case CT_DCCP_REQUEST:
500 if (old_state == CT_DCCP_TIMEWAIT &&
501 role == CT_DCCP_ROLE_SERVER) {
502
503
504 ct->proto.dccp.role[dir] = CT_DCCP_ROLE_CLIENT;
505 ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_SERVER;
506 }
507 break;
508 case CT_DCCP_RESPOND:
509 if (old_state == CT_DCCP_REQUEST)
510 ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh);
511 break;
512 case CT_DCCP_PARTOPEN:
513 if (old_state == CT_DCCP_RESPOND &&
514 type == DCCP_PKT_ACK &&
515 dccp_ack_seq(dh) == ct->proto.dccp.handshake_seq)
516 set_bit(IPS_ASSURED_BIT, &ct->status);
517 break;
518 case CT_DCCP_IGNORE:
519
520
521
522
523
524 if (ct->proto.dccp.last_dir == !dir &&
525 ct->proto.dccp.last_pkt == DCCP_PKT_REQUEST &&
526 type == DCCP_PKT_RESPONSE) {
527 ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_CLIENT;
528 ct->proto.dccp.role[dir] = CT_DCCP_ROLE_SERVER;
529 ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh);
530 new_state = CT_DCCP_RESPOND;
531 break;
532 }
533 ct->proto.dccp.last_dir = dir;
534 ct->proto.dccp.last_pkt = type;
535
536 spin_unlock_bh(&ct->lock);
537 if (LOG_INVALID(net, IPPROTO_DCCP))
538 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
539 "nf_ct_dccp: invalid packet ignored ");
540 return NF_ACCEPT;
541 case CT_DCCP_INVALID:
542 spin_unlock_bh(&ct->lock);
543 if (LOG_INVALID(net, IPPROTO_DCCP))
544 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
545 "nf_ct_dccp: invalid state transition ");
546 return -NF_ACCEPT;
547 }
548
549 ct->proto.dccp.last_dir = dir;
550 ct->proto.dccp.last_pkt = type;
551 ct->proto.dccp.state = new_state;
552 spin_unlock_bh(&ct->lock);
553
554 if (new_state != old_state)
555 nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
556
557 nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]);
558
559 return NF_ACCEPT;
560}
561
562static int dccp_error(struct net *net, struct nf_conn *tmpl,
563 struct sk_buff *skb, unsigned int dataoff,
564 u_int8_t pf, unsigned int hooknum)
565{
566 struct dccp_hdr _dh, *dh;
567 unsigned int dccp_len = skb->len - dataoff;
568 unsigned int cscov;
569 const char *msg;
570
571 dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
572 if (dh == NULL) {
573 msg = "nf_ct_dccp: short packet ";
574 goto out_invalid;
575 }
576
577 if (dh->dccph_doff * 4 < sizeof(struct dccp_hdr) ||
578 dh->dccph_doff * 4 > dccp_len) {
579 msg = "nf_ct_dccp: truncated/malformed packet ";
580 goto out_invalid;
581 }
582
583 cscov = dccp_len;
584 if (dh->dccph_cscov) {
585 cscov = (dh->dccph_cscov - 1) * 4;
586 if (cscov > dccp_len) {
587 msg = "nf_ct_dccp: bad checksum coverage ";
588 goto out_invalid;
589 }
590 }
591
592 if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
593 nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_DCCP,
594 pf)) {
595 msg = "nf_ct_dccp: bad checksum ";
596 goto out_invalid;
597 }
598
599 if (dh->dccph_type >= DCCP_PKT_INVALID) {
600 msg = "nf_ct_dccp: reserved packet type ";
601 goto out_invalid;
602 }
603
604 return NF_ACCEPT;
605
606out_invalid:
607 if (LOG_INVALID(net, IPPROTO_DCCP))
608 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "%s", msg);
609 return -NF_ACCEPT;
610}
611
612static bool dccp_can_early_drop(const struct nf_conn *ct)
613{
614 switch (ct->proto.dccp.state) {
615 case CT_DCCP_CLOSEREQ:
616 case CT_DCCP_CLOSING:
617 case CT_DCCP_TIMEWAIT:
618 return true;
619 default:
620 break;
621 }
622
623 return false;
624}
625
626static void dccp_print_tuple(struct seq_file *s,
627 const struct nf_conntrack_tuple *tuple)
628{
629 seq_printf(s, "sport=%hu dport=%hu ",
630 ntohs(tuple->src.u.dccp.port),
631 ntohs(tuple->dst.u.dccp.port));
632}
633
634static void dccp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
635{
636 seq_printf(s, "%s ", dccp_state_names[ct->proto.dccp.state]);
637}
638
639#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
640static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
641 struct nf_conn *ct)
642{
643 struct nlattr *nest_parms;
644
645 spin_lock_bh(&ct->lock);
646 nest_parms = nla_nest_start(skb, CTA_PROTOINFO_DCCP | NLA_F_NESTED);
647 if (!nest_parms)
648 goto nla_put_failure;
649 if (nla_put_u8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state) ||
650 nla_put_u8(skb, CTA_PROTOINFO_DCCP_ROLE,
651 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL]) ||
652 nla_put_be64(skb, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,
653 cpu_to_be64(ct->proto.dccp.handshake_seq),
654 CTA_PROTOINFO_DCCP_PAD))
655 goto nla_put_failure;
656 nla_nest_end(skb, nest_parms);
657 spin_unlock_bh(&ct->lock);
658 return 0;
659
660nla_put_failure:
661 spin_unlock_bh(&ct->lock);
662 return -1;
663}
664
665static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = {
666 [CTA_PROTOINFO_DCCP_STATE] = { .type = NLA_U8 },
667 [CTA_PROTOINFO_DCCP_ROLE] = { .type = NLA_U8 },
668 [CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ] = { .type = NLA_U64 },
669 [CTA_PROTOINFO_DCCP_PAD] = { .type = NLA_UNSPEC },
670};
671
672static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
673{
674 struct nlattr *attr = cda[CTA_PROTOINFO_DCCP];
675 struct nlattr *tb[CTA_PROTOINFO_DCCP_MAX + 1];
676 int err;
677
678 if (!attr)
679 return 0;
680
681 err = nla_parse_nested(tb, CTA_PROTOINFO_DCCP_MAX, attr,
682 dccp_nla_policy, NULL);
683 if (err < 0)
684 return err;
685
686 if (!tb[CTA_PROTOINFO_DCCP_STATE] ||
687 !tb[CTA_PROTOINFO_DCCP_ROLE] ||
688 nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) > CT_DCCP_ROLE_MAX ||
689 nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE) {
690 return -EINVAL;
691 }
692
693 spin_lock_bh(&ct->lock);
694 ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]);
695 if (nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) == CT_DCCP_ROLE_CLIENT) {
696 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT;
697 ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER;
698 } else {
699 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_SERVER;
700 ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_CLIENT;
701 }
702 if (tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]) {
703 ct->proto.dccp.handshake_seq =
704 be64_to_cpu(nla_get_be64(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]));
705 }
706 spin_unlock_bh(&ct->lock);
707 return 0;
708}
709
710static int dccp_nlattr_size(void)
711{
712 return nla_total_size(0)
713 + nla_policy_len(dccp_nla_policy, CTA_PROTOINFO_DCCP_MAX + 1);
714}
715
716#endif
717
718#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
719
720#include <linux/netfilter/nfnetlink.h>
721#include <linux/netfilter/nfnetlink_cttimeout.h>
722
723static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[],
724 struct net *net, void *data)
725{
726 struct nf_dccp_net *dn = dccp_pernet(net);
727 unsigned int *timeouts = data;
728 int i;
729
730
731 for (i=0; i<CT_DCCP_MAX; i++)
732 timeouts[i] = dn->dccp_timeout[i];
733
734
735 for (i=CTA_TIMEOUT_DCCP_UNSPEC+1; i<CTA_TIMEOUT_DCCP_MAX+1; i++) {
736 if (tb[i]) {
737 timeouts[i] = ntohl(nla_get_be32(tb[i])) * HZ;
738 }
739 }
740 return 0;
741}
742
743static int
744dccp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
745{
746 const unsigned int *timeouts = data;
747 int i;
748
749 for (i=CTA_TIMEOUT_DCCP_UNSPEC+1; i<CTA_TIMEOUT_DCCP_MAX+1; i++) {
750 if (nla_put_be32(skb, i, htonl(timeouts[i] / HZ)))
751 goto nla_put_failure;
752 }
753 return 0;
754
755nla_put_failure:
756 return -ENOSPC;
757}
758
759static const struct nla_policy
760dccp_timeout_nla_policy[CTA_TIMEOUT_DCCP_MAX+1] = {
761 [CTA_TIMEOUT_DCCP_REQUEST] = { .type = NLA_U32 },
762 [CTA_TIMEOUT_DCCP_RESPOND] = { .type = NLA_U32 },
763 [CTA_TIMEOUT_DCCP_PARTOPEN] = { .type = NLA_U32 },
764 [CTA_TIMEOUT_DCCP_OPEN] = { .type = NLA_U32 },
765 [CTA_TIMEOUT_DCCP_CLOSEREQ] = { .type = NLA_U32 },
766 [CTA_TIMEOUT_DCCP_CLOSING] = { .type = NLA_U32 },
767 [CTA_TIMEOUT_DCCP_TIMEWAIT] = { .type = NLA_U32 },
768};
769#endif
770
771#ifdef CONFIG_SYSCTL
772
773static struct ctl_table dccp_sysctl_table[] = {
774 {
775 .procname = "nf_conntrack_dccp_timeout_request",
776 .maxlen = sizeof(unsigned int),
777 .mode = 0644,
778 .proc_handler = proc_dointvec_jiffies,
779 },
780 {
781 .procname = "nf_conntrack_dccp_timeout_respond",
782 .maxlen = sizeof(unsigned int),
783 .mode = 0644,
784 .proc_handler = proc_dointvec_jiffies,
785 },
786 {
787 .procname = "nf_conntrack_dccp_timeout_partopen",
788 .maxlen = sizeof(unsigned int),
789 .mode = 0644,
790 .proc_handler = proc_dointvec_jiffies,
791 },
792 {
793 .procname = "nf_conntrack_dccp_timeout_open",
794 .maxlen = sizeof(unsigned int),
795 .mode = 0644,
796 .proc_handler = proc_dointvec_jiffies,
797 },
798 {
799 .procname = "nf_conntrack_dccp_timeout_closereq",
800 .maxlen = sizeof(unsigned int),
801 .mode = 0644,
802 .proc_handler = proc_dointvec_jiffies,
803 },
804 {
805 .procname = "nf_conntrack_dccp_timeout_closing",
806 .maxlen = sizeof(unsigned int),
807 .mode = 0644,
808 .proc_handler = proc_dointvec_jiffies,
809 },
810 {
811 .procname = "nf_conntrack_dccp_timeout_timewait",
812 .maxlen = sizeof(unsigned int),
813 .mode = 0644,
814 .proc_handler = proc_dointvec_jiffies,
815 },
816 {
817 .procname = "nf_conntrack_dccp_loose",
818 .maxlen = sizeof(int),
819 .mode = 0644,
820 .proc_handler = proc_dointvec,
821 },
822 { }
823};
824#endif
825
826static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn,
827 struct nf_dccp_net *dn)
828{
829#ifdef CONFIG_SYSCTL
830 if (pn->ctl_table)
831 return 0;
832
833 pn->ctl_table = kmemdup(dccp_sysctl_table,
834 sizeof(dccp_sysctl_table),
835 GFP_KERNEL);
836 if (!pn->ctl_table)
837 return -ENOMEM;
838
839 pn->ctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST];
840 pn->ctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND];
841 pn->ctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN];
842 pn->ctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN];
843 pn->ctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ];
844 pn->ctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING];
845 pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT];
846 pn->ctl_table[7].data = &dn->dccp_loose;
847
848
849 if (net->user_ns != &init_user_ns)
850 pn->ctl_table[0].procname = NULL;
851#endif
852 return 0;
853}
854
855static int dccp_init_net(struct net *net, u_int16_t proto)
856{
857 struct nf_dccp_net *dn = dccp_pernet(net);
858 struct nf_proto_net *pn = &dn->pn;
859
860 if (!pn->users) {
861
862 dn->dccp_loose = 1;
863 dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL;
864 dn->dccp_timeout[CT_DCCP_RESPOND] = 4 * DCCP_MSL;
865 dn->dccp_timeout[CT_DCCP_PARTOPEN] = 4 * DCCP_MSL;
866 dn->dccp_timeout[CT_DCCP_OPEN] = 12 * 3600 * HZ;
867 dn->dccp_timeout[CT_DCCP_CLOSEREQ] = 64 * HZ;
868 dn->dccp_timeout[CT_DCCP_CLOSING] = 64 * HZ;
869 dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL;
870 }
871
872 return dccp_kmemdup_sysctl_table(net, pn, dn);
873}
874
875static struct nf_proto_net *dccp_get_net_proto(struct net *net)
876{
877 return &net->ct.nf_ct_proto.dccp.pn;
878}
879
880struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 __read_mostly = {
881 .l3proto = AF_INET,
882 .l4proto = IPPROTO_DCCP,
883 .name = "dccp",
884 .pkt_to_tuple = dccp_pkt_to_tuple,
885 .invert_tuple = dccp_invert_tuple,
886 .new = dccp_new,
887 .packet = dccp_packet,
888 .get_timeouts = dccp_get_timeouts,
889 .error = dccp_error,
890 .can_early_drop = dccp_can_early_drop,
891 .print_tuple = dccp_print_tuple,
892 .print_conntrack = dccp_print_conntrack,
893#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
894 .to_nlattr = dccp_to_nlattr,
895 .nlattr_size = dccp_nlattr_size,
896 .from_nlattr = nlattr_to_dccp,
897 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
898 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
899 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
900 .nla_policy = nf_ct_port_nla_policy,
901#endif
902#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
903 .ctnl_timeout = {
904 .nlattr_to_obj = dccp_timeout_nlattr_to_obj,
905 .obj_to_nlattr = dccp_timeout_obj_to_nlattr,
906 .nlattr_max = CTA_TIMEOUT_DCCP_MAX,
907 .obj_size = sizeof(unsigned int) * CT_DCCP_MAX,
908 .nla_policy = dccp_timeout_nla_policy,
909 },
910#endif
911 .init_net = dccp_init_net,
912 .get_net_proto = dccp_get_net_proto,
913};
914EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp4);
915
916struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 __read_mostly = {
917 .l3proto = AF_INET6,
918 .l4proto = IPPROTO_DCCP,
919 .name = "dccp",
920 .pkt_to_tuple = dccp_pkt_to_tuple,
921 .invert_tuple = dccp_invert_tuple,
922 .new = dccp_new,
923 .packet = dccp_packet,
924 .get_timeouts = dccp_get_timeouts,
925 .error = dccp_error,
926 .can_early_drop = dccp_can_early_drop,
927 .print_tuple = dccp_print_tuple,
928 .print_conntrack = dccp_print_conntrack,
929#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
930 .to_nlattr = dccp_to_nlattr,
931 .nlattr_size = dccp_nlattr_size,
932 .from_nlattr = nlattr_to_dccp,
933 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
934 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
935 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
936 .nla_policy = nf_ct_port_nla_policy,
937#endif
938#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
939 .ctnl_timeout = {
940 .nlattr_to_obj = dccp_timeout_nlattr_to_obj,
941 .obj_to_nlattr = dccp_timeout_obj_to_nlattr,
942 .nlattr_max = CTA_TIMEOUT_DCCP_MAX,
943 .obj_size = sizeof(unsigned int) * CT_DCCP_MAX,
944 .nla_policy = dccp_timeout_nla_policy,
945 },
946#endif
947 .init_net = dccp_init_net,
948 .get_net_proto = dccp_get_net_proto,
949};
950EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp6);
951