Root/
1 | #include <linux/module.h> |
2 | #include <linux/skbuff.h> |
3 | #include <net/ip.h> |
4 | #include <net/ipv6.h> |
5 | #include <linux/sctp.h> |
6 | |
7 | #include <linux/netfilter/x_tables.h> |
8 | #include <linux/netfilter/xt_sctp.h> |
9 | #include <linux/netfilter_ipv4/ip_tables.h> |
10 | #include <linux/netfilter_ipv6/ip6_tables.h> |
11 | |
12 | MODULE_LICENSE("GPL"); |
13 | MODULE_AUTHOR("Kiran Kumar Immidi"); |
14 | MODULE_DESCRIPTION("Xtables: SCTP protocol packet match"); |
15 | MODULE_ALIAS("ipt_sctp"); |
16 | MODULE_ALIAS("ip6t_sctp"); |
17 | |
18 | #ifdef DEBUG_SCTP |
19 | #define duprintf(format, args...) printk(format , ## args) |
20 | #else |
21 | #define duprintf(format, args...) |
22 | #endif |
23 | |
24 | #define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \ |
25 | || (!!((invflag) & (option)) ^ (cond))) |
26 | |
27 | static bool |
28 | match_flags(const struct xt_sctp_flag_info *flag_info, |
29 | const int flag_count, |
30 | u_int8_t chunktype, |
31 | u_int8_t chunkflags) |
32 | { |
33 | int i; |
34 | |
35 | for (i = 0; i < flag_count; i++) |
36 | if (flag_info[i].chunktype == chunktype) |
37 | return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag; |
38 | |
39 | return true; |
40 | } |
41 | |
42 | static inline bool |
43 | match_packet(const struct sk_buff *skb, |
44 | unsigned int offset, |
45 | const struct xt_sctp_info *info, |
46 | bool *hotdrop) |
47 | { |
48 | u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)]; |
49 | const sctp_chunkhdr_t *sch; |
50 | sctp_chunkhdr_t _sch; |
51 | int chunk_match_type = info->chunk_match_type; |
52 | const struct xt_sctp_flag_info *flag_info = info->flag_info; |
53 | int flag_count = info->flag_count; |
54 | |
55 | #ifdef DEBUG_SCTP |
56 | int i = 0; |
57 | #endif |
58 | |
59 | if (chunk_match_type == SCTP_CHUNK_MATCH_ALL) |
60 | SCTP_CHUNKMAP_COPY(chunkmapcopy, info->chunkmap); |
61 | |
62 | do { |
63 | sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch); |
64 | if (sch == NULL || sch->length == 0) { |
65 | duprintf("Dropping invalid SCTP packet.\n"); |
66 | *hotdrop = true; |
67 | return false; |
68 | } |
69 | |
70 | duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n", |
71 | ++i, offset, sch->type, htons(sch->length), sch->flags); |
72 | |
73 | offset += (ntohs(sch->length) + 3) & ~3; |
74 | |
75 | duprintf("skb->len: %d\toffset: %d\n", skb->len, offset); |
76 | |
77 | if (SCTP_CHUNKMAP_IS_SET(info->chunkmap, sch->type)) { |
78 | switch (chunk_match_type) { |
79 | case SCTP_CHUNK_MATCH_ANY: |
80 | if (match_flags(flag_info, flag_count, |
81 | sch->type, sch->flags)) { |
82 | return true; |
83 | } |
84 | break; |
85 | |
86 | case SCTP_CHUNK_MATCH_ALL: |
87 | if (match_flags(flag_info, flag_count, |
88 | sch->type, sch->flags)) |
89 | SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch->type); |
90 | break; |
91 | |
92 | case SCTP_CHUNK_MATCH_ONLY: |
93 | if (!match_flags(flag_info, flag_count, |
94 | sch->type, sch->flags)) |
95 | return false; |
96 | break; |
97 | } |
98 | } else { |
99 | switch (chunk_match_type) { |
100 | case SCTP_CHUNK_MATCH_ONLY: |
101 | return false; |
102 | } |
103 | } |
104 | } while (offset < skb->len); |
105 | |
106 | switch (chunk_match_type) { |
107 | case SCTP_CHUNK_MATCH_ALL: |
108 | return SCTP_CHUNKMAP_IS_CLEAR(chunkmapcopy); |
109 | case SCTP_CHUNK_MATCH_ANY: |
110 | return false; |
111 | case SCTP_CHUNK_MATCH_ONLY: |
112 | return true; |
113 | } |
114 | |
115 | /* This will never be reached, but required to stop compiler whine */ |
116 | return false; |
117 | } |
118 | |
119 | static bool |
120 | sctp_mt(const struct sk_buff *skb, const struct xt_match_param *par) |
121 | { |
122 | const struct xt_sctp_info *info = par->matchinfo; |
123 | const sctp_sctphdr_t *sh; |
124 | sctp_sctphdr_t _sh; |
125 | |
126 | if (par->fragoff != 0) { |
127 | duprintf("Dropping non-first fragment.. FIXME\n"); |
128 | return false; |
129 | } |
130 | |
131 | sh = skb_header_pointer(skb, par->thoff, sizeof(_sh), &_sh); |
132 | if (sh == NULL) { |
133 | duprintf("Dropping evil TCP offset=0 tinygram.\n"); |
134 | *par->hotdrop = true; |
135 | return false; |
136 | } |
137 | duprintf("spt: %d\tdpt: %d\n", ntohs(sh->source), ntohs(sh->dest)); |
138 | |
139 | return SCCHECK(ntohs(sh->source) >= info->spts[0] |
140 | && ntohs(sh->source) <= info->spts[1], |
141 | XT_SCTP_SRC_PORTS, info->flags, info->invflags) |
142 | && SCCHECK(ntohs(sh->dest) >= info->dpts[0] |
143 | && ntohs(sh->dest) <= info->dpts[1], |
144 | XT_SCTP_DEST_PORTS, info->flags, info->invflags) |
145 | && SCCHECK(match_packet(skb, par->thoff + sizeof(sctp_sctphdr_t), |
146 | info, par->hotdrop), |
147 | XT_SCTP_CHUNK_TYPES, info->flags, info->invflags); |
148 | } |
149 | |
150 | static bool sctp_mt_check(const struct xt_mtchk_param *par) |
151 | { |
152 | const struct xt_sctp_info *info = par->matchinfo; |
153 | |
154 | return !(info->flags & ~XT_SCTP_VALID_FLAGS) |
155 | && !(info->invflags & ~XT_SCTP_VALID_FLAGS) |
156 | && !(info->invflags & ~info->flags) |
157 | && ((!(info->flags & XT_SCTP_CHUNK_TYPES)) || |
158 | (info->chunk_match_type & |
159 | (SCTP_CHUNK_MATCH_ALL |
160 | | SCTP_CHUNK_MATCH_ANY |
161 | | SCTP_CHUNK_MATCH_ONLY))); |
162 | } |
163 | |
164 | static struct xt_match sctp_mt_reg[] __read_mostly = { |
165 | { |
166 | .name = "sctp", |
167 | .family = NFPROTO_IPV4, |
168 | .checkentry = sctp_mt_check, |
169 | .match = sctp_mt, |
170 | .matchsize = sizeof(struct xt_sctp_info), |
171 | .proto = IPPROTO_SCTP, |
172 | .me = THIS_MODULE |
173 | }, |
174 | { |
175 | .name = "sctp", |
176 | .family = NFPROTO_IPV6, |
177 | .checkentry = sctp_mt_check, |
178 | .match = sctp_mt, |
179 | .matchsize = sizeof(struct xt_sctp_info), |
180 | .proto = IPPROTO_SCTP, |
181 | .me = THIS_MODULE |
182 | }, |
183 | }; |
184 | |
185 | static int __init sctp_mt_init(void) |
186 | { |
187 | return xt_register_matches(sctp_mt_reg, ARRAY_SIZE(sctp_mt_reg)); |
188 | } |
189 | |
190 | static void __exit sctp_mt_exit(void) |
191 | { |
192 | xt_unregister_matches(sctp_mt_reg, ARRAY_SIZE(sctp_mt_reg)); |
193 | } |
194 | |
195 | module_init(sctp_mt_init); |
196 | module_exit(sctp_mt_exit); |
197 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9