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_dccp;
389}
390
391static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
392 struct nf_conntrack_tuple *tuple)
393{
394 struct dccp_hdr _hdr, *dh;
395
396 dh = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr);
397 if (dh == NULL)
398 return false;
399
400 tuple->src.u.dccp.port = dh->dccph_sport;
401 tuple->dst.u.dccp.port = dh->dccph_dport;
402 return true;
403}
404
405static bool dccp_invert_tuple(struct nf_conntrack_tuple *inv,
406 const struct nf_conntrack_tuple *tuple)
407{
408 inv->src.u.dccp.port = tuple->dst.u.dccp.port;
409 inv->dst.u.dccp.port = tuple->src.u.dccp.port;
410 return true;
411}
412
413static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
414 unsigned int dataoff, unsigned int *timeouts)
415{
416 struct net *net = nf_ct_net(ct);
417 struct nf_dccp_net *dn;
418 struct dccp_hdr _dh, *dh;
419 const char *msg;
420 u_int8_t state;
421
422 dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
423 BUG_ON(dh == NULL);
424
425 state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE];
426 switch (state) {
427 default:
428 dn = dccp_pernet(net);
429 if (dn->dccp_loose == 0) {
430 msg = "nf_ct_dccp: not picking up existing connection ";
431 goto out_invalid;
432 }
433 case CT_DCCP_REQUEST:
434 break;
435 case CT_DCCP_INVALID:
436 msg = "nf_ct_dccp: invalid state transition ";
437 goto out_invalid;
438 }
439
440 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT;
441 ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER;
442 ct->proto.dccp.state = CT_DCCP_NONE;
443 ct->proto.dccp.last_pkt = DCCP_PKT_REQUEST;
444 ct->proto.dccp.last_dir = IP_CT_DIR_ORIGINAL;
445 ct->proto.dccp.handshake_seq = 0;
446 return true;
447
448out_invalid:
449 if (LOG_INVALID(net, IPPROTO_DCCP))
450 nf_log_packet(net, nf_ct_l3num(ct), 0, skb, NULL, NULL,
451 NULL, msg);
452 return false;
453}
454
455static u64 dccp_ack_seq(const struct dccp_hdr *dh)
456{
457 const struct dccp_hdr_ack_bits *dhack;
458
459 dhack = (void *)dh + __dccp_basic_hdr_len(dh);
460 return ((u64)ntohs(dhack->dccph_ack_nr_high) << 32) +
461 ntohl(dhack->dccph_ack_nr_low);
462}
463
464static unsigned int *dccp_get_timeouts(struct net *net)
465{
466 return dccp_pernet(net)->dccp_timeout;
467}
468
469static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
470 unsigned int dataoff, enum ip_conntrack_info ctinfo,
471 u_int8_t pf, unsigned int hooknum,
472 unsigned int *timeouts)
473{
474 struct net *net = nf_ct_net(ct);
475 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
476 struct dccp_hdr _dh, *dh;
477 u_int8_t type, old_state, new_state;
478 enum ct_dccp_roles role;
479
480 dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
481 BUG_ON(dh == NULL);
482 type = dh->dccph_type;
483
484 if (type == DCCP_PKT_RESET &&
485 !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
486
487 nf_ct_kill_acct(ct, ctinfo, skb);
488 return NF_ACCEPT;
489 }
490
491 spin_lock_bh(&ct->lock);
492
493 role = ct->proto.dccp.role[dir];
494 old_state = ct->proto.dccp.state;
495 new_state = dccp_state_table[role][type][old_state];
496
497 switch (new_state) {
498 case CT_DCCP_REQUEST:
499 if (old_state == CT_DCCP_TIMEWAIT &&
500 role == CT_DCCP_ROLE_SERVER) {
501
502
503 ct->proto.dccp.role[dir] = CT_DCCP_ROLE_CLIENT;
504 ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_SERVER;
505 }
506 break;
507 case CT_DCCP_RESPOND:
508 if (old_state == CT_DCCP_REQUEST)
509 ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh);
510 break;
511 case CT_DCCP_PARTOPEN:
512 if (old_state == CT_DCCP_RESPOND &&
513 type == DCCP_PKT_ACK &&
514 dccp_ack_seq(dh) == ct->proto.dccp.handshake_seq)
515 set_bit(IPS_ASSURED_BIT, &ct->status);
516 break;
517 case CT_DCCP_IGNORE:
518
519
520
521
522
523 if (ct->proto.dccp.last_dir == !dir &&
524 ct->proto.dccp.last_pkt == DCCP_PKT_REQUEST &&
525 type == DCCP_PKT_RESPONSE) {
526 ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_CLIENT;
527 ct->proto.dccp.role[dir] = CT_DCCP_ROLE_SERVER;
528 ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh);
529 new_state = CT_DCCP_RESPOND;
530 break;
531 }
532 ct->proto.dccp.last_dir = dir;
533 ct->proto.dccp.last_pkt = type;
534
535 spin_unlock_bh(&ct->lock);
536 if (LOG_INVALID(net, IPPROTO_DCCP))
537 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
538 "nf_ct_dccp: invalid packet ignored ");
539 return NF_ACCEPT;
540 case CT_DCCP_INVALID:
541 spin_unlock_bh(&ct->lock);
542 if (LOG_INVALID(net, IPPROTO_DCCP))
543 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
544 "nf_ct_dccp: invalid state transition ");
545 return -NF_ACCEPT;
546 }
547
548 ct->proto.dccp.last_dir = dir;
549 ct->proto.dccp.last_pkt = type;
550 ct->proto.dccp.state = new_state;
551 spin_unlock_bh(&ct->lock);
552
553 if (new_state != old_state)
554 nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
555
556 nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]);
557
558 return NF_ACCEPT;
559}
560
561static int dccp_error(struct net *net, struct nf_conn *tmpl,
562 struct sk_buff *skb, unsigned int dataoff,
563 enum ip_conntrack_info *ctinfo,
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, msg);
609 return -NF_ACCEPT;
610}
611
612static int dccp_print_tuple(struct seq_file *s,
613 const struct nf_conntrack_tuple *tuple)
614{
615 return seq_printf(s, "sport=%hu dport=%hu ",
616 ntohs(tuple->src.u.dccp.port),
617 ntohs(tuple->dst.u.dccp.port));
618}
619
620static int dccp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
621{
622 return seq_printf(s, "%s ", dccp_state_names[ct->proto.dccp.state]);
623}
624
625#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
626static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
627 struct nf_conn *ct)
628{
629 struct nlattr *nest_parms;
630
631 spin_lock_bh(&ct->lock);
632 nest_parms = nla_nest_start(skb, CTA_PROTOINFO_DCCP | NLA_F_NESTED);
633 if (!nest_parms)
634 goto nla_put_failure;
635 if (nla_put_u8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state) ||
636 nla_put_u8(skb, CTA_PROTOINFO_DCCP_ROLE,
637 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL]) ||
638 nla_put_be64(skb, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,
639 cpu_to_be64(ct->proto.dccp.handshake_seq),
640 CTA_PROTOINFO_DCCP_PAD))
641 goto nla_put_failure;
642 nla_nest_end(skb, nest_parms);
643 spin_unlock_bh(&ct->lock);
644 return 0;
645
646nla_put_failure:
647 spin_unlock_bh(&ct->lock);
648 return -1;
649}
650
651static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = {
652 [CTA_PROTOINFO_DCCP_STATE] = { .type = NLA_U8 },
653 [CTA_PROTOINFO_DCCP_ROLE] = { .type = NLA_U8 },
654 [CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ] = { .type = NLA_U64 },
655 [CTA_PROTOINFO_DCCP_PAD] = { .type = NLA_UNSPEC },
656};
657
658static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
659{
660 struct nlattr *attr = cda[CTA_PROTOINFO_DCCP];
661 struct nlattr *tb[CTA_PROTOINFO_DCCP_MAX + 1];
662 int err;
663
664 if (!attr)
665 return 0;
666
667 err = nla_parse_nested(tb, CTA_PROTOINFO_DCCP_MAX, attr,
668 dccp_nla_policy);
669 if (err < 0)
670 return err;
671
672 if (!tb[CTA_PROTOINFO_DCCP_STATE] ||
673 !tb[CTA_PROTOINFO_DCCP_ROLE] ||
674 nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) > CT_DCCP_ROLE_MAX ||
675 nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE) {
676 return -EINVAL;
677 }
678
679 spin_lock_bh(&ct->lock);
680 ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]);
681 if (nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) == CT_DCCP_ROLE_CLIENT) {
682 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT;
683 ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER;
684 } else {
685 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_SERVER;
686 ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_CLIENT;
687 }
688 if (tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]) {
689 ct->proto.dccp.handshake_seq =
690 be64_to_cpu(nla_get_be64(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]));
691 }
692 spin_unlock_bh(&ct->lock);
693 return 0;
694}
695
696static int dccp_nlattr_size(void)
697{
698 return nla_total_size(0)
699 + nla_policy_len(dccp_nla_policy, CTA_PROTOINFO_DCCP_MAX + 1);
700}
701
702#endif
703
704#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
705
706#include <linux/netfilter/nfnetlink.h>
707#include <linux/netfilter/nfnetlink_cttimeout.h>
708
709static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[],
710 struct net *net, void *data)
711{
712 struct nf_dccp_net *dn = dccp_pernet(net);
713 unsigned int *timeouts = data;
714 int i;
715
716
717 for (i=0; i<CT_DCCP_MAX; i++)
718 timeouts[i] = dn->dccp_timeout[i];
719
720
721 for (i=CTA_TIMEOUT_DCCP_UNSPEC+1; i<CTA_TIMEOUT_DCCP_MAX+1; i++) {
722 if (tb[i]) {
723 timeouts[i] = ntohl(nla_get_be32(tb[i])) * HZ;
724 }
725 }
726 return 0;
727}
728
729static int
730dccp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
731{
732 const unsigned int *timeouts = data;
733 int i;
734
735 for (i=CTA_TIMEOUT_DCCP_UNSPEC+1; i<CTA_TIMEOUT_DCCP_MAX+1; i++) {
736 if (nla_put_be32(skb, i, htonl(timeouts[i] / HZ)))
737 goto nla_put_failure;
738 }
739 return 0;
740
741nla_put_failure:
742 return -ENOSPC;
743}
744
745static const struct nla_policy
746dccp_timeout_nla_policy[CTA_TIMEOUT_DCCP_MAX+1] = {
747 [CTA_TIMEOUT_DCCP_REQUEST] = { .type = NLA_U32 },
748 [CTA_TIMEOUT_DCCP_RESPOND] = { .type = NLA_U32 },
749 [CTA_TIMEOUT_DCCP_PARTOPEN] = { .type = NLA_U32 },
750 [CTA_TIMEOUT_DCCP_OPEN] = { .type = NLA_U32 },
751 [CTA_TIMEOUT_DCCP_CLOSEREQ] = { .type = NLA_U32 },
752 [CTA_TIMEOUT_DCCP_CLOSING] = { .type = NLA_U32 },
753 [CTA_TIMEOUT_DCCP_TIMEWAIT] = { .type = NLA_U32 },
754};
755#endif
756
757#ifdef CONFIG_SYSCTL
758
759static struct ctl_table dccp_sysctl_table[] = {
760 {
761 .procname = "nf_conntrack_dccp_timeout_request",
762 .maxlen = sizeof(unsigned int),
763 .mode = 0644,
764 .proc_handler = proc_dointvec_jiffies,
765 },
766 {
767 .procname = "nf_conntrack_dccp_timeout_respond",
768 .maxlen = sizeof(unsigned int),
769 .mode = 0644,
770 .proc_handler = proc_dointvec_jiffies,
771 },
772 {
773 .procname = "nf_conntrack_dccp_timeout_partopen",
774 .maxlen = sizeof(unsigned int),
775 .mode = 0644,
776 .proc_handler = proc_dointvec_jiffies,
777 },
778 {
779 .procname = "nf_conntrack_dccp_timeout_open",
780 .maxlen = sizeof(unsigned int),
781 .mode = 0644,
782 .proc_handler = proc_dointvec_jiffies,
783 },
784 {
785 .procname = "nf_conntrack_dccp_timeout_closereq",
786 .maxlen = sizeof(unsigned int),
787 .mode = 0644,
788 .proc_handler = proc_dointvec_jiffies,
789 },
790 {
791 .procname = "nf_conntrack_dccp_timeout_closing",
792 .maxlen = sizeof(unsigned int),
793 .mode = 0644,
794 .proc_handler = proc_dointvec_jiffies,
795 },
796 {
797 .procname = "nf_conntrack_dccp_timeout_timewait",
798 .maxlen = sizeof(unsigned int),
799 .mode = 0644,
800 .proc_handler = proc_dointvec_jiffies,
801 },
802 {
803 .procname = "nf_conntrack_dccp_loose",
804 .maxlen = sizeof(int),
805 .mode = 0644,
806 .proc_handler = proc_dointvec,
807 },
808 { }
809};
810#endif
811
812static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn,
813 struct nf_dccp_net *dn)
814{
815#ifdef CONFIG_SYSCTL
816 if (pn->ctl_table)
817 return 0;
818
819 pn->ctl_table = kmemdup(dccp_sysctl_table,
820 sizeof(dccp_sysctl_table),
821 GFP_KERNEL);
822 if (!pn->ctl_table)
823 return -ENOMEM;
824
825 pn->ctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST];
826 pn->ctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND];
827 pn->ctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN];
828 pn->ctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN];
829 pn->ctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ];
830 pn->ctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING];
831 pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT];
832 pn->ctl_table[7].data = &dn->dccp_loose;
833
834
835 if (net->user_ns != &init_user_ns)
836 pn->ctl_table[0].procname = NULL;
837#endif
838 return 0;
839}
840
841static int dccp_init_net(struct net *net, u_int16_t proto)
842{
843 struct nf_dccp_net *dn = dccp_pernet(net);
844 struct nf_proto_net *pn = &dn->pn;
845
846 if (!pn->users) {
847
848 dn->dccp_loose = 1;
849 dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL;
850 dn->dccp_timeout[CT_DCCP_RESPOND] = 4 * DCCP_MSL;
851 dn->dccp_timeout[CT_DCCP_PARTOPEN] = 4 * DCCP_MSL;
852 dn->dccp_timeout[CT_DCCP_OPEN] = 12 * 3600 * HZ;
853 dn->dccp_timeout[CT_DCCP_CLOSEREQ] = 64 * HZ;
854 dn->dccp_timeout[CT_DCCP_CLOSING] = 64 * HZ;
855 dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL;
856 }
857
858 return dccp_kmemdup_sysctl_table(net, pn, dn);
859}
860
861static struct nf_proto_net *dccp_get_net_proto(struct net *net)
862{
863 return &net->ct_dccp.pn;
864}
865
866struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 __read_mostly = {
867 .l3proto = AF_INET,
868 .l4proto = IPPROTO_DCCP,
869 .name = "dccp",
870 .pkt_to_tuple = dccp_pkt_to_tuple,
871 .invert_tuple = dccp_invert_tuple,
872 .new = dccp_new,
873 .packet = dccp_packet,
874 .get_timeouts = dccp_get_timeouts,
875 .error = dccp_error,
876 .print_tuple = dccp_print_tuple,
877 .print_conntrack = dccp_print_conntrack,
878#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
879 .to_nlattr = dccp_to_nlattr,
880 .nlattr_size = dccp_nlattr_size,
881 .from_nlattr = nlattr_to_dccp,
882 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
883 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
884 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
885 .nla_policy = nf_ct_port_nla_policy,
886#endif
887#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
888 .ctnl_timeout = {
889 .nlattr_to_obj = dccp_timeout_nlattr_to_obj,
890 .obj_to_nlattr = dccp_timeout_obj_to_nlattr,
891 .nlattr_max = CTA_TIMEOUT_DCCP_MAX,
892 .obj_size = sizeof(unsigned int) * CT_DCCP_MAX,
893 .nla_policy = dccp_timeout_nla_policy,
894 },
895#endif
896 .init_net = dccp_init_net,
897 .get_net_proto = dccp_get_net_proto,
898};
899EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp4);
900
901struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 __read_mostly = {
902 .l3proto = AF_INET6,
903 .l4proto = IPPROTO_DCCP,
904 .name = "dccp",
905 .pkt_to_tuple = dccp_pkt_to_tuple,
906 .invert_tuple = dccp_invert_tuple,
907 .new = dccp_new,
908 .packet = dccp_packet,
909 .get_timeouts = dccp_get_timeouts,
910 .error = dccp_error,
911 .print_tuple = dccp_print_tuple,
912 .print_conntrack = dccp_print_conntrack,
913#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
914 .to_nlattr = dccp_to_nlattr,
915 .nlattr_size = dccp_nlattr_size,
916 .from_nlattr = nlattr_to_dccp,
917 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
918 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
919 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
920 .nla_policy = nf_ct_port_nla_policy,
921#endif
922#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
923 .ctnl_timeout = {
924 .nlattr_to_obj = dccp_timeout_nlattr_to_obj,
925 .obj_to_nlattr = dccp_timeout_obj_to_nlattr,
926 .nlattr_max = CTA_TIMEOUT_DCCP_MAX,
927 .obj_size = sizeof(unsigned int) * CT_DCCP_MAX,
928 .nla_policy = dccp_timeout_nla_policy,
929 },
930#endif
931 .init_net = dccp_init_net,
932 .get_net_proto = dccp_get_net_proto,
933};
934EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp6);
935