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