diff options
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/Kconfig | 11 | ||||
-rw-r--r-- | net/ipv4/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_dccp.c | 176 |
3 files changed, 188 insertions, 0 deletions
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 2fa26a41fa47..9f5e1d769b5f 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -354,6 +354,17 @@ config IP_NF_MATCH_SCTP | |||
354 | If you want to compile it as a module, say M here and read | 354 | If you want to compile it as a module, say M here and read |
355 | <file:Documentation/modules.txt>. If unsure, say `N'. | 355 | <file:Documentation/modules.txt>. If unsure, say `N'. |
356 | 356 | ||
357 | config IP_NF_MATCH_DCCP | ||
358 | tristate 'DCCP protocol match support' | ||
359 | depends on IP_NF_IPTABLES | ||
360 | help | ||
361 | With this option enabled, you will be able to use the iptables | ||
362 | `dccp' match in order to match on DCCP source/destination ports | ||
363 | and DCCP flags. | ||
364 | |||
365 | If you want to compile it as a module, say M here and read | ||
366 | <file:Documentation/modules.txt>. If unsure, say `N'. | ||
367 | |||
357 | config IP_NF_MATCH_COMMENT | 368 | config IP_NF_MATCH_COMMENT |
358 | tristate 'comment match support' | 369 | tristate 'comment match support' |
359 | depends on IP_NF_IPTABLES | 370 | depends on IP_NF_IPTABLES |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index c2ae663b723f..58aa7c616e1f 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -42,6 +42,7 @@ obj-$(CONFIG_IP_NF_MATCH_HELPER) += ipt_helper.o | |||
42 | obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o | 42 | obj-$(CONFIG_IP_NF_MATCH_LIMIT) += ipt_limit.o |
43 | obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o | 43 | obj-$(CONFIG_IP_NF_MATCH_HASHLIMIT) += ipt_hashlimit.o |
44 | obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o | 44 | obj-$(CONFIG_IP_NF_MATCH_SCTP) += ipt_sctp.o |
45 | obj-$(CONFIG_IP_NF_MATCH_DCCP) += ipt_dccp.o | ||
45 | obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o | 46 | obj-$(CONFIG_IP_NF_MATCH_MARK) += ipt_mark.o |
46 | obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o | 47 | obj-$(CONFIG_IP_NF_MATCH_MAC) += ipt_mac.o |
47 | obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o | 48 | obj-$(CONFIG_IP_NF_MATCH_IPRANGE) += ipt_iprange.o |
diff --git a/net/ipv4/netfilter/ipt_dccp.c b/net/ipv4/netfilter/ipt_dccp.c new file mode 100644 index 000000000000..ad3278bba6c1 --- /dev/null +++ b/net/ipv4/netfilter/ipt_dccp.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* | ||
2 | * iptables module for DCCP protocol header matching | ||
3 | * | ||
4 | * (C) 2005 by Harald Welte <laforge@netfilter.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | #include <linux/spinlock.h> | ||
14 | #include <net/ip.h> | ||
15 | #include <linux/dccp.h> | ||
16 | |||
17 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
18 | #include <linux/netfilter_ipv4/ipt_dccp.h> | ||
19 | |||
20 | #define DCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ | ||
21 | || (!!((invflag) & (option)) ^ (cond))) | ||
22 | |||
23 | static unsigned char *dccp_optbuf; | ||
24 | static DEFINE_SPINLOCK(dccp_buflock); | ||
25 | |||
26 | static inline int | ||
27 | dccp_find_option(u_int8_t option, | ||
28 | const struct sk_buff *skb, | ||
29 | const struct dccp_hdr *dh, | ||
30 | int *hotdrop) | ||
31 | { | ||
32 | /* tcp.doff is only 4 bits, ie. max 15 * 4 bytes */ | ||
33 | unsigned char *op; | ||
34 | unsigned int optoff = __dccp_hdr_len(dh); | ||
35 | unsigned int optlen = dh->dccph_doff*4 - __dccp_hdr_len(dh); | ||
36 | unsigned int i; | ||
37 | |||
38 | if (dh->dccph_doff * 4 < __dccp_hdr_len(dh)) { | ||
39 | *hotdrop = 1; | ||
40 | return 0; | ||
41 | } | ||
42 | |||
43 | if (!optlen) | ||
44 | return 0; | ||
45 | |||
46 | spin_lock_bh(&dccp_buflock); | ||
47 | op = skb_header_pointer(skb, | ||
48 | skb->nh.iph->ihl*4 + optoff, | ||
49 | optlen, dccp_optbuf); | ||
50 | if (op == NULL) { | ||
51 | /* If we don't have the whole header, drop packet. */ | ||
52 | spin_unlock_bh(&dccp_buflock); | ||
53 | *hotdrop = 1; | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | for (i = 0; i < optlen; ) { | ||
58 | if (op[i] == option) { | ||
59 | spin_unlock_bh(&dccp_buflock); | ||
60 | return 1; | ||
61 | } | ||
62 | |||
63 | if (op[i] < 2) | ||
64 | i++; | ||
65 | else | ||
66 | i += op[i+1]?:1; | ||
67 | } | ||
68 | |||
69 | spin_unlock_bh(&dccp_buflock); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | |||
74 | static inline int | ||
75 | match_types(const struct dccp_hdr *dh, u_int16_t typemask) | ||
76 | { | ||
77 | return (typemask & (1 << dh->dccph_type)); | ||
78 | } | ||
79 | |||
80 | static inline int | ||
81 | match_option(u_int8_t option, const struct sk_buff *skb, | ||
82 | const struct dccp_hdr *dh, int *hotdrop) | ||
83 | { | ||
84 | return dccp_find_option(option, skb, dh, hotdrop); | ||
85 | } | ||
86 | |||
87 | static int | ||
88 | match(const struct sk_buff *skb, | ||
89 | const struct net_device *in, | ||
90 | const struct net_device *out, | ||
91 | const void *matchinfo, | ||
92 | int offset, | ||
93 | int *hotdrop) | ||
94 | { | ||
95 | const struct ipt_dccp_info *info = | ||
96 | (const struct ipt_dccp_info *)matchinfo; | ||
97 | struct dccp_hdr _dh, *dh; | ||
98 | |||
99 | if (offset) | ||
100 | return 0; | ||
101 | |||
102 | dh = skb_header_pointer(skb, skb->nh.iph->ihl*4, sizeof(_dh), &_dh); | ||
103 | if (dh == NULL) { | ||
104 | *hotdrop = 1; | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | return DCCHECK(((ntohs(dh->dccph_sport) >= info->spts[0]) | ||
109 | && (ntohs(dh->dccph_sport) <= info->spts[1])), | ||
110 | IPT_DCCP_SRC_PORTS, info->flags, info->invflags) | ||
111 | && DCCHECK(((ntohs(dh->dccph_dport) >= info->dpts[0]) | ||
112 | && (ntohs(dh->dccph_dport) <= info->dpts[1])), | ||
113 | IPT_DCCP_DEST_PORTS, info->flags, info->invflags) | ||
114 | && DCCHECK(match_types(dh, info->typemask), | ||
115 | IPT_DCCP_TYPE, info->flags, info->invflags) | ||
116 | && DCCHECK(match_option(info->option, skb, dh, hotdrop), | ||
117 | IPT_DCCP_OPTION, info->flags, info->invflags); | ||
118 | } | ||
119 | |||
120 | static int | ||
121 | checkentry(const char *tablename, | ||
122 | const struct ipt_ip *ip, | ||
123 | void *matchinfo, | ||
124 | unsigned int matchsize, | ||
125 | unsigned int hook_mask) | ||
126 | { | ||
127 | const struct ipt_dccp_info *info; | ||
128 | |||
129 | info = (const struct ipt_dccp_info *)matchinfo; | ||
130 | |||
131 | return ip->proto == IPPROTO_DCCP | ||
132 | && !(ip->invflags & IPT_INV_PROTO) | ||
133 | && matchsize == IPT_ALIGN(sizeof(struct ipt_dccp_info)) | ||
134 | && !(info->flags & ~IPT_DCCP_VALID_FLAGS) | ||
135 | && !(info->invflags & ~IPT_DCCP_VALID_FLAGS) | ||
136 | && !(info->invflags & ~info->flags); | ||
137 | } | ||
138 | |||
139 | static struct ipt_match dccp_match = | ||
140 | { | ||
141 | .name = "dccp", | ||
142 | .match = &match, | ||
143 | .checkentry = &checkentry, | ||
144 | .me = THIS_MODULE, | ||
145 | }; | ||
146 | |||
147 | static int __init init(void) | ||
148 | { | ||
149 | int ret; | ||
150 | |||
151 | /* doff is 8 bits, so the maximum option size is (4*256). Don't put | ||
152 | * this in BSS since DaveM is worried about locked TLB's for kernel | ||
153 | * BSS. */ | ||
154 | dccp_optbuf = kmalloc(256 * 4, GFP_KERNEL); | ||
155 | if (!dccp_optbuf) | ||
156 | return -ENOMEM; | ||
157 | ret = ipt_register_match(&dccp_match); | ||
158 | if (ret) | ||
159 | kfree(dccp_optbuf); | ||
160 | |||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | static void __exit fini(void) | ||
165 | { | ||
166 | ipt_unregister_match(&dccp_match); | ||
167 | kfree(dccp_optbuf); | ||
168 | } | ||
169 | |||
170 | module_init(init); | ||
171 | module_exit(fini); | ||
172 | |||
173 | MODULE_LICENSE("GPL"); | ||
174 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | ||
175 | MODULE_DESCRIPTION("Match for DCCP protocol packets"); | ||
176 | |||