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(net, nf_ct_l3num(ct), 0, skb, NULL, NULL,
460 NULL, "%s", msg);
461 return false;
462}
463
464static u64 dccp_ack_seq(const struct dccp_hdr *dh)
465{
466 const struct dccp_hdr_ack_bits *dhack;
467
468 dhack = (void *)dh + __dccp_basic_hdr_len(dh);
469 return ((u64)ntohs(dhack->dccph_ack_nr_high) << 32) +
470 ntohl(dhack->dccph_ack_nr_low);
471}
472
473static unsigned int *dccp_get_timeouts(struct net *net)
474{
475 return dccp_pernet(net)->dccp_timeout;
476}
477
478static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
479 unsigned int dataoff, enum ip_conntrack_info ctinfo,
480 u_int8_t pf, unsigned int hooknum,
481 unsigned int *timeouts)
482{
483 struct net *net = nf_ct_net(ct);
484 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
485 struct dccp_hdr _dh, *dh;
486 u_int8_t type, old_state, new_state;
487 enum ct_dccp_roles role;
488
489 dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
490 BUG_ON(dh == NULL);
491 type = dh->dccph_type;
492
493 if (type == DCCP_PKT_RESET &&
494 !test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
495
496 nf_ct_kill_acct(ct, ctinfo, skb);
497 return NF_ACCEPT;
498 }
499
500 spin_lock_bh(&ct->lock);
501
502 role = ct->proto.dccp.role[dir];
503 old_state = ct->proto.dccp.state;
504 new_state = dccp_state_table[role][type][old_state];
505
506 switch (new_state) {
507 case CT_DCCP_REQUEST:
508 if (old_state == CT_DCCP_TIMEWAIT &&
509 role == CT_DCCP_ROLE_SERVER) {
510
511
512 ct->proto.dccp.role[dir] = CT_DCCP_ROLE_CLIENT;
513 ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_SERVER;
514 }
515 break;
516 case CT_DCCP_RESPOND:
517 if (old_state == CT_DCCP_REQUEST)
518 ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh);
519 break;
520 case CT_DCCP_PARTOPEN:
521 if (old_state == CT_DCCP_RESPOND &&
522 type == DCCP_PKT_ACK &&
523 dccp_ack_seq(dh) == ct->proto.dccp.handshake_seq)
524 set_bit(IPS_ASSURED_BIT, &ct->status);
525 break;
526 case CT_DCCP_IGNORE:
527
528
529
530
531
532 if (ct->proto.dccp.last_dir == !dir &&
533 ct->proto.dccp.last_pkt == DCCP_PKT_REQUEST &&
534 type == DCCP_PKT_RESPONSE) {
535 ct->proto.dccp.role[!dir] = CT_DCCP_ROLE_CLIENT;
536 ct->proto.dccp.role[dir] = CT_DCCP_ROLE_SERVER;
537 ct->proto.dccp.handshake_seq = dccp_hdr_seq(dh);
538 new_state = CT_DCCP_RESPOND;
539 break;
540 }
541 ct->proto.dccp.last_dir = dir;
542 ct->proto.dccp.last_pkt = type;
543
544 spin_unlock_bh(&ct->lock);
545 if (LOG_INVALID(net, IPPROTO_DCCP))
546 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
547 "nf_ct_dccp: invalid packet ignored ");
548 return NF_ACCEPT;
549 case CT_DCCP_INVALID:
550 spin_unlock_bh(&ct->lock);
551 if (LOG_INVALID(net, IPPROTO_DCCP))
552 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL,
553 "nf_ct_dccp: invalid state transition ");
554 return -NF_ACCEPT;
555 }
556
557 ct->proto.dccp.last_dir = dir;
558 ct->proto.dccp.last_pkt = type;
559 ct->proto.dccp.state = new_state;
560 spin_unlock_bh(&ct->lock);
561
562 if (new_state != old_state)
563 nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
564
565 nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]);
566
567 return NF_ACCEPT;
568}
569
570static int dccp_error(struct net *net, struct nf_conn *tmpl,
571 struct sk_buff *skb, unsigned int dataoff,
572 enum ip_conntrack_info *ctinfo,
573 u_int8_t pf, unsigned int hooknum)
574{
575 struct dccp_hdr _dh, *dh;
576 unsigned int dccp_len = skb->len - dataoff;
577 unsigned int cscov;
578 const char *msg;
579
580 dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
581 if (dh == NULL) {
582 msg = "nf_ct_dccp: short packet ";
583 goto out_invalid;
584 }
585
586 if (dh->dccph_doff * 4 < sizeof(struct dccp_hdr) ||
587 dh->dccph_doff * 4 > dccp_len) {
588 msg = "nf_ct_dccp: truncated/malformed packet ";
589 goto out_invalid;
590 }
591
592 cscov = dccp_len;
593 if (dh->dccph_cscov) {
594 cscov = (dh->dccph_cscov - 1) * 4;
595 if (cscov > dccp_len) {
596 msg = "nf_ct_dccp: bad checksum coverage ";
597 goto out_invalid;
598 }
599 }
600
601 if (net->ct.sysctl_checksum && hooknum == NF_INET_PRE_ROUTING &&
602 nf_checksum_partial(skb, hooknum, dataoff, cscov, IPPROTO_DCCP,
603 pf)) {
604 msg = "nf_ct_dccp: bad checksum ";
605 goto out_invalid;
606 }
607
608 if (dh->dccph_type >= DCCP_PKT_INVALID) {
609 msg = "nf_ct_dccp: reserved packet type ";
610 goto out_invalid;
611 }
612
613 return NF_ACCEPT;
614
615out_invalid:
616 if (LOG_INVALID(net, IPPROTO_DCCP))
617 nf_log_packet(net, pf, 0, skb, NULL, NULL, NULL, "%s", msg);
618 return -NF_ACCEPT;
619}
620
621static void dccp_print_tuple(struct seq_file *s,
622 const struct nf_conntrack_tuple *tuple)
623{
624 seq_printf(s, "sport=%hu dport=%hu ",
625 ntohs(tuple->src.u.dccp.port),
626 ntohs(tuple->dst.u.dccp.port));
627}
628
629static void dccp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
630{
631 seq_printf(s, "%s ", dccp_state_names[ct->proto.dccp.state]);
632}
633
634#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
635static int dccp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
636 struct nf_conn *ct)
637{
638 struct nlattr *nest_parms;
639
640 spin_lock_bh(&ct->lock);
641 nest_parms = nla_nest_start(skb, CTA_PROTOINFO_DCCP | NLA_F_NESTED);
642 if (!nest_parms)
643 goto nla_put_failure;
644 if (nla_put_u8(skb, CTA_PROTOINFO_DCCP_STATE, ct->proto.dccp.state) ||
645 nla_put_u8(skb, CTA_PROTOINFO_DCCP_ROLE,
646 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL]) ||
647 nla_put_be64(skb, CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,
648 cpu_to_be64(ct->proto.dccp.handshake_seq)))
649 goto nla_put_failure;
650 nla_nest_end(skb, nest_parms);
651 spin_unlock_bh(&ct->lock);
652 return 0;
653
654nla_put_failure:
655 spin_unlock_bh(&ct->lock);
656 return -1;
657}
658
659static const struct nla_policy dccp_nla_policy[CTA_PROTOINFO_DCCP_MAX + 1] = {
660 [CTA_PROTOINFO_DCCP_STATE] = { .type = NLA_U8 },
661 [CTA_PROTOINFO_DCCP_ROLE] = { .type = NLA_U8 },
662 [CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ] = { .type = NLA_U64 },
663};
664
665static int nlattr_to_dccp(struct nlattr *cda[], struct nf_conn *ct)
666{
667 struct nlattr *attr = cda[CTA_PROTOINFO_DCCP];
668 struct nlattr *tb[CTA_PROTOINFO_DCCP_MAX + 1];
669 int err;
670
671 if (!attr)
672 return 0;
673
674 err = nla_parse_nested(tb, CTA_PROTOINFO_DCCP_MAX, attr,
675 dccp_nla_policy);
676 if (err < 0)
677 return err;
678
679 if (!tb[CTA_PROTOINFO_DCCP_STATE] ||
680 !tb[CTA_PROTOINFO_DCCP_ROLE] ||
681 nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) > CT_DCCP_ROLE_MAX ||
682 nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]) >= CT_DCCP_IGNORE) {
683 return -EINVAL;
684 }
685
686 spin_lock_bh(&ct->lock);
687 ct->proto.dccp.state = nla_get_u8(tb[CTA_PROTOINFO_DCCP_STATE]);
688 if (nla_get_u8(tb[CTA_PROTOINFO_DCCP_ROLE]) == CT_DCCP_ROLE_CLIENT) {
689 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_CLIENT;
690 ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_SERVER;
691 } else {
692 ct->proto.dccp.role[IP_CT_DIR_ORIGINAL] = CT_DCCP_ROLE_SERVER;
693 ct->proto.dccp.role[IP_CT_DIR_REPLY] = CT_DCCP_ROLE_CLIENT;
694 }
695 if (tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]) {
696 ct->proto.dccp.handshake_seq =
697 be64_to_cpu(nla_get_be64(tb[CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ]));
698 }
699 spin_unlock_bh(&ct->lock);
700 return 0;
701}
702
703static int dccp_nlattr_size(void)
704{
705 return nla_total_size(0)
706 + nla_policy_len(dccp_nla_policy, CTA_PROTOINFO_DCCP_MAX + 1);
707}
708
709#endif
710
711#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
712
713#include <linux/netfilter/nfnetlink.h>
714#include <linux/netfilter/nfnetlink_cttimeout.h>
715
716static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[],
717 struct net *net, void *data)
718{
719 struct dccp_net *dn = dccp_pernet(net);
720 unsigned int *timeouts = data;
721 int i;
722
723
724 for (i=0; i<CT_DCCP_MAX; i++)
725 timeouts[i] = dn->dccp_timeout[i];
726
727
728 for (i=CTA_TIMEOUT_DCCP_UNSPEC+1; i<CTA_TIMEOUT_DCCP_MAX+1; i++) {
729 if (tb[i]) {
730 timeouts[i] = ntohl(nla_get_be32(tb[i])) * HZ;
731 }
732 }
733 return 0;
734}
735
736static int
737dccp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data)
738{
739 const unsigned int *timeouts = data;
740 int i;
741
742 for (i=CTA_TIMEOUT_DCCP_UNSPEC+1; i<CTA_TIMEOUT_DCCP_MAX+1; i++) {
743 if (nla_put_be32(skb, i, htonl(timeouts[i] / HZ)))
744 goto nla_put_failure;
745 }
746 return 0;
747
748nla_put_failure:
749 return -ENOSPC;
750}
751
752static const struct nla_policy
753dccp_timeout_nla_policy[CTA_TIMEOUT_DCCP_MAX+1] = {
754 [CTA_TIMEOUT_DCCP_REQUEST] = { .type = NLA_U32 },
755 [CTA_TIMEOUT_DCCP_RESPOND] = { .type = NLA_U32 },
756 [CTA_TIMEOUT_DCCP_PARTOPEN] = { .type = NLA_U32 },
757 [CTA_TIMEOUT_DCCP_OPEN] = { .type = NLA_U32 },
758 [CTA_TIMEOUT_DCCP_CLOSEREQ] = { .type = NLA_U32 },
759 [CTA_TIMEOUT_DCCP_CLOSING] = { .type = NLA_U32 },
760 [CTA_TIMEOUT_DCCP_TIMEWAIT] = { .type = NLA_U32 },
761};
762#endif
763
764#ifdef CONFIG_SYSCTL
765
766static struct ctl_table dccp_sysctl_table[] = {
767 {
768 .procname = "nf_conntrack_dccp_timeout_request",
769 .maxlen = sizeof(unsigned int),
770 .mode = 0644,
771 .proc_handler = proc_dointvec_jiffies,
772 },
773 {
774 .procname = "nf_conntrack_dccp_timeout_respond",
775 .maxlen = sizeof(unsigned int),
776 .mode = 0644,
777 .proc_handler = proc_dointvec_jiffies,
778 },
779 {
780 .procname = "nf_conntrack_dccp_timeout_partopen",
781 .maxlen = sizeof(unsigned int),
782 .mode = 0644,
783 .proc_handler = proc_dointvec_jiffies,
784 },
785 {
786 .procname = "nf_conntrack_dccp_timeout_open",
787 .maxlen = sizeof(unsigned int),
788 .mode = 0644,
789 .proc_handler = proc_dointvec_jiffies,
790 },
791 {
792 .procname = "nf_conntrack_dccp_timeout_closereq",
793 .maxlen = sizeof(unsigned int),
794 .mode = 0644,
795 .proc_handler = proc_dointvec_jiffies,
796 },
797 {
798 .procname = "nf_conntrack_dccp_timeout_closing",
799 .maxlen = sizeof(unsigned int),
800 .mode = 0644,
801 .proc_handler = proc_dointvec_jiffies,
802 },
803 {
804 .procname = "nf_conntrack_dccp_timeout_timewait",
805 .maxlen = sizeof(unsigned int),
806 .mode = 0644,
807 .proc_handler = proc_dointvec_jiffies,
808 },
809 {
810 .procname = "nf_conntrack_dccp_loose",
811 .maxlen = sizeof(int),
812 .mode = 0644,
813 .proc_handler = proc_dointvec,
814 },
815 { }
816};
817#endif
818
819static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn,
820 struct dccp_net *dn)
821{
822#ifdef CONFIG_SYSCTL
823 if (pn->ctl_table)
824 return 0;
825
826 pn->ctl_table = kmemdup(dccp_sysctl_table,
827 sizeof(dccp_sysctl_table),
828 GFP_KERNEL);
829 if (!pn->ctl_table)
830 return -ENOMEM;
831
832 pn->ctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST];
833 pn->ctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND];
834 pn->ctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN];
835 pn->ctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN];
836 pn->ctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ];
837 pn->ctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING];
838 pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT];
839 pn->ctl_table[7].data = &dn->dccp_loose;
840
841
842 if (net->user_ns != &init_user_ns)
843 pn->ctl_table[0].procname = NULL;
844#endif
845 return 0;
846}
847
848static int dccp_init_net(struct net *net, u_int16_t proto)
849{
850 struct dccp_net *dn = dccp_pernet(net);
851 struct nf_proto_net *pn = &dn->pn;
852
853 if (!pn->users) {
854
855 dn->dccp_loose = 1;
856 dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL;
857 dn->dccp_timeout[CT_DCCP_RESPOND] = 4 * DCCP_MSL;
858 dn->dccp_timeout[CT_DCCP_PARTOPEN] = 4 * DCCP_MSL;
859 dn->dccp_timeout[CT_DCCP_OPEN] = 12 * 3600 * HZ;
860 dn->dccp_timeout[CT_DCCP_CLOSEREQ] = 64 * HZ;
861 dn->dccp_timeout[CT_DCCP_CLOSING] = 64 * HZ;
862 dn->dccp_timeout[CT_DCCP_TIMEWAIT] = 2 * DCCP_MSL;
863 }
864
865 return dccp_kmemdup_sysctl_table(net, pn, dn);
866}
867
868static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
869 .l3proto = AF_INET,
870 .l4proto = IPPROTO_DCCP,
871 .name = "dccp",
872 .pkt_to_tuple = dccp_pkt_to_tuple,
873 .invert_tuple = dccp_invert_tuple,
874 .new = dccp_new,
875 .packet = dccp_packet,
876 .get_timeouts = dccp_get_timeouts,
877 .error = dccp_error,
878 .print_tuple = dccp_print_tuple,
879 .print_conntrack = dccp_print_conntrack,
880#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
881 .to_nlattr = dccp_to_nlattr,
882 .nlattr_size = dccp_nlattr_size,
883 .from_nlattr = nlattr_to_dccp,
884 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
885 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
886 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
887 .nla_policy = nf_ct_port_nla_policy,
888#endif
889#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
890 .ctnl_timeout = {
891 .nlattr_to_obj = dccp_timeout_nlattr_to_obj,
892 .obj_to_nlattr = dccp_timeout_obj_to_nlattr,
893 .nlattr_max = CTA_TIMEOUT_DCCP_MAX,
894 .obj_size = sizeof(unsigned int) * CT_DCCP_MAX,
895 .nla_policy = dccp_timeout_nla_policy,
896 },
897#endif
898 .net_id = &dccp_net_id,
899 .init_net = dccp_init_net,
900};
901
902static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
903 .l3proto = AF_INET6,
904 .l4proto = IPPROTO_DCCP,
905 .name = "dccp",
906 .pkt_to_tuple = dccp_pkt_to_tuple,
907 .invert_tuple = dccp_invert_tuple,
908 .new = dccp_new,
909 .packet = dccp_packet,
910 .get_timeouts = dccp_get_timeouts,
911 .error = dccp_error,
912 .print_tuple = dccp_print_tuple,
913 .print_conntrack = dccp_print_conntrack,
914#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
915 .to_nlattr = dccp_to_nlattr,
916 .nlattr_size = dccp_nlattr_size,
917 .from_nlattr = nlattr_to_dccp,
918 .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
919 .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
920 .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
921 .nla_policy = nf_ct_port_nla_policy,
922#endif
923#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
924 .ctnl_timeout = {
925 .nlattr_to_obj = dccp_timeout_nlattr_to_obj,
926 .obj_to_nlattr = dccp_timeout_obj_to_nlattr,
927 .nlattr_max = CTA_TIMEOUT_DCCP_MAX,
928 .obj_size = sizeof(unsigned int) * CT_DCCP_MAX,
929 .nla_policy = dccp_timeout_nla_policy,
930 },
931#endif
932 .net_id = &dccp_net_id,
933 .init_net = dccp_init_net,
934};
935
936static __net_init int dccp_net_init(struct net *net)
937{
938 int ret = 0;
939 ret = nf_ct_l4proto_pernet_register(net, &dccp_proto4);
940 if (ret < 0) {
941 pr_err("nf_conntrack_dccp4: pernet registration failed.\n");
942 goto out;
943 }
944 ret = nf_ct_l4proto_pernet_register(net, &dccp_proto6);
945 if (ret < 0) {
946 pr_err("nf_conntrack_dccp6: pernet registration failed.\n");
947 goto cleanup_dccp4;
948 }
949 return 0;
950cleanup_dccp4:
951 nf_ct_l4proto_pernet_unregister(net, &dccp_proto4);
952out:
953 return ret;
954}
955
956static __net_exit void dccp_net_exit(struct net *net)
957{
958 nf_ct_l4proto_pernet_unregister(net, &dccp_proto6);
959 nf_ct_l4proto_pernet_unregister(net, &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 int ret;
972
973 ret = register_pernet_subsys(&dccp_net_ops);
974 if (ret < 0)
975 goto out_pernet;
976
977 ret = nf_ct_l4proto_register(&dccp_proto4);
978 if (ret < 0)
979 goto out_dccp4;
980
981 ret = nf_ct_l4proto_register(&dccp_proto6);
982 if (ret < 0)
983 goto out_dccp6;
984
985 return 0;
986out_dccp6:
987 nf_ct_l4proto_unregister(&dccp_proto4);
988out_dccp4:
989 unregister_pernet_subsys(&dccp_net_ops);
990out_pernet:
991 return ret;
992}
993
994static void __exit nf_conntrack_proto_dccp_fini(void)
995{
996 nf_ct_l4proto_unregister(&dccp_proto6);
997 nf_ct_l4proto_unregister(&dccp_proto4);
998 unregister_pernet_subsys(&dccp_net_ops);
999}
1000
1001module_init(nf_conntrack_proto_dccp_init);
1002module_exit(nf_conntrack_proto_dccp_fini);
1003
1004MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
1005MODULE_DESCRIPTION("DCCP connection tracking protocol helper");
1006MODULE_LICENSE("GPL");
1007