Blame view

net/netfilter/xt_sctp.c 4.97 KB
be91fd5e3   Jan Engelhardt   netfilter: xtable...
1
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
  #include <linux/module.h>
  #include <linux/skbuff.h>
  #include <net/ip.h>
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
5
  #include <net/ipv6.h>
2bf074825   Shan Wei   netfilter: xt_sct...
6
  #include <net/sctp/sctp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
  #include <linux/sctp.h>
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
8
9
  #include <linux/netfilter/x_tables.h>
  #include <linux/netfilter/xt_sctp.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
  #include <linux/netfilter_ipv4/ip_tables.h>
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
11
12
13
14
  #include <linux/netfilter_ipv6/ip6_tables.h>
  
  MODULE_LICENSE("GPL");
  MODULE_AUTHOR("Kiran Kumar Immidi");
2ae15b64e   Jan Engelhardt   [NETFILTER]: Upda...
15
  MODULE_DESCRIPTION("Xtables: SCTP protocol packet match");
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
16
  MODULE_ALIAS("ipt_sctp");
73aaf9355   Jan Engelhardt   [NETFILTER]: x_ta...
17
  MODULE_ALIAS("ip6t_sctp");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
  #define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
  					      || (!!((invflag) & (option)) ^ (cond)))
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
21
  static bool
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
22
  match_flags(const struct xt_sctp_flag_info *flag_info,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
24
25
26
27
  	    const int flag_count,
  	    u_int8_t chunktype,
  	    u_int8_t chunkflags)
  {
  	int i;
7c4e36bc1   Jan Engelhardt   [NETFILTER]: Remo...
28
29
  	for (i = 0; i < flag_count; i++)
  		if (flag_info[i].chunktype == chunktype)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
  			return (chunkflags & flag_info[i].flag_mask) == flag_info[i].flag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31

1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
32
  	return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
33
  }
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
34
  static inline bool
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  match_packet(const struct sk_buff *skb,
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
36
  	     unsigned int offset,
009e8c965   Li Zefan   [NETFILTER]: xt_s...
37
  	     const struct xt_sctp_info *info,
cff533ac1   Jan Engelhardt   [NETFILTER]: x_ta...
38
  	     bool *hotdrop)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
39
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  	u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
3cf93c96a   Jan Engelhardt   [NETFILTER]: anno...
41
42
  	const sctp_chunkhdr_t *sch;
  	sctp_chunkhdr_t _sch;
009e8c965   Li Zefan   [NETFILTER]: xt_s...
43
44
45
  	int chunk_match_type = info->chunk_match_type;
  	const struct xt_sctp_flag_info *flag_info = info->flag_info;
  	int flag_count = info->flag_count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46

be91fd5e3   Jan Engelhardt   netfilter: xtable...
47
  #ifdef DEBUG
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
  	int i = 0;
  #endif
7c4e36bc1   Jan Engelhardt   [NETFILTER]: Remo...
50
  	if (chunk_match_type == SCTP_CHUNK_MATCH_ALL)
009e8c965   Li Zefan   [NETFILTER]: xt_s...
51
  		SCTP_CHUNKMAP_COPY(chunkmapcopy, info->chunkmap);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
54
  	do {
  		sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
d3dcd4efe   Patrick McHardy   [NETFILTER]: xt_s...
55
  		if (sch == NULL || sch->length == 0) {
be91fd5e3   Jan Engelhardt   netfilter: xtable...
56
57
  			pr_debug("Dropping invalid SCTP packet.
  ");
cff533ac1   Jan Engelhardt   [NETFILTER]: x_ta...
58
  			*hotdrop = true;
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
59
  			return false;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
60
  		}
be91fd5e3   Jan Engelhardt   netfilter: xtable...
61
62
63
64
65
66
67
  #ifdef DEBUG
  		pr_debug("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d"
  			 "\tflags: %x
  ",
  			 ++i, offset, sch->type, htons(sch->length),
  			 sch->flags);
  #endif
2bf074825   Shan Wei   netfilter: xt_sct...
68
  		offset += WORD_ROUND(ntohs(sch->length));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69

be91fd5e3   Jan Engelhardt   netfilter: xtable...
70
71
  		pr_debug("skb->len: %d\toffset: %d
  ", skb->len, offset);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72

009e8c965   Li Zefan   [NETFILTER]: xt_s...
73
  		if (SCTP_CHUNKMAP_IS_SET(info->chunkmap, sch->type)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
74
75
  			switch (chunk_match_type) {
  			case SCTP_CHUNK_MATCH_ANY:
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
76
  				if (match_flags(flag_info, flag_count,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
  					sch->type, sch->flags)) {
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
78
  					return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
79
80
81
82
  				}
  				break;
  
  			case SCTP_CHUNK_MATCH_ALL:
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
83
  				if (match_flags(flag_info, flag_count,
7c4e36bc1   Jan Engelhardt   [NETFILTER]: Remo...
84
  				    sch->type, sch->flags))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
  					SCTP_CHUNKMAP_CLEAR(chunkmapcopy, sch->type);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
  				break;
  
  			case SCTP_CHUNK_MATCH_ONLY:
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
89
  				if (!match_flags(flag_info, flag_count,
7c4e36bc1   Jan Engelhardt   [NETFILTER]: Remo...
90
  				    sch->type, sch->flags))
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
91
  					return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
95
96
  				break;
  			}
  		} else {
  			switch (chunk_match_type) {
  			case SCTP_CHUNK_MATCH_ONLY:
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
97
  				return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
101
102
103
  			}
  		}
  	} while (offset < skb->len);
  
  	switch (chunk_match_type) {
  	case SCTP_CHUNK_MATCH_ALL:
d4e2675a6   Qu Haoran   netfilter: xt_sct...
104
  		return SCTP_CHUNKMAP_IS_CLEAR(chunkmapcopy);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105
  	case SCTP_CHUNK_MATCH_ANY:
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
106
  		return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  	case SCTP_CHUNK_MATCH_ONLY:
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
108
  		return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
  	}
  
  	/* This will never be reached, but required to stop compiler whine */
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
112
  	return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
  }
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
114
  static bool
62fc80510   Jan Engelhardt   netfilter: xtable...
115
  sctp_mt(const struct sk_buff *skb, struct xt_action_param *par)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116
  {
f7108a20d   Jan Engelhardt   netfilter: xtable...
117
  	const struct xt_sctp_info *info = par->matchinfo;
3cf93c96a   Jan Engelhardt   [NETFILTER]: anno...
118
119
  	const sctp_sctphdr_t *sh;
  	sctp_sctphdr_t _sh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120

f7108a20d   Jan Engelhardt   netfilter: xtable...
121
  	if (par->fragoff != 0) {
be91fd5e3   Jan Engelhardt   netfilter: xtable...
122
123
  		pr_debug("Dropping non-first fragment.. FIXME
  ");
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
124
  		return false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
125
  	}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
126

f7108a20d   Jan Engelhardt   netfilter: xtable...
127
  	sh = skb_header_pointer(skb, par->thoff, sizeof(_sh), &_sh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128
  	if (sh == NULL) {
be91fd5e3   Jan Engelhardt   netfilter: xtable...
129
130
  		pr_debug("Dropping evil TCP offset=0 tinygram.
  ");
b4ba26119   Jan Engelhardt   netfilter: xtable...
131
  		par->hotdrop = true;
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
132
  		return false;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
133
  	}
be91fd5e3   Jan Engelhardt   netfilter: xtable...
134
135
  	pr_debug("spt: %d\tdpt: %d
  ", ntohs(sh->source), ntohs(sh->dest));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136

7c4e36bc1   Jan Engelhardt   [NETFILTER]: Remo...
137
138
  	return  SCCHECK(ntohs(sh->source) >= info->spts[0]
  			&& ntohs(sh->source) <= info->spts[1],
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
139
  			XT_SCTP_SRC_PORTS, info->flags, info->invflags)
7c4e36bc1   Jan Engelhardt   [NETFILTER]: Remo...
140
141
  		&& SCCHECK(ntohs(sh->dest) >= info->dpts[0]
  			&& ntohs(sh->dest) <= info->dpts[1],
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
142
  			XT_SCTP_DEST_PORTS, info->flags, info->invflags)
f7108a20d   Jan Engelhardt   netfilter: xtable...
143
  		&& SCCHECK(match_packet(skb, par->thoff + sizeof(sctp_sctphdr_t),
b4ba26119   Jan Engelhardt   netfilter: xtable...
144
  					info, &par->hotdrop),
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
145
  			   XT_SCTP_CHUNK_TYPES, info->flags, info->invflags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
  }
b0f38452f   Jan Engelhardt   netfilter: xtable...
147
  static int sctp_mt_check(const struct xt_mtchk_param *par)
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
148
  {
9b4fce7a3   Jan Engelhardt   netfilter: xtable...
149
  	const struct xt_sctp_info *info = par->matchinfo;
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
150

9f5673174   Jan Engelhardt   netfilter: xtable...
151
  	if (info->flags & ~XT_SCTP_VALID_FLAGS)
bd414ee60   Jan Engelhardt   netfilter: xtable...
152
  		return -EINVAL;
9f5673174   Jan Engelhardt   netfilter: xtable...
153
  	if (info->invflags & ~XT_SCTP_VALID_FLAGS)
bd414ee60   Jan Engelhardt   netfilter: xtable...
154
  		return -EINVAL;
9f5673174   Jan Engelhardt   netfilter: xtable...
155
  	if (info->invflags & ~info->flags)
bd414ee60   Jan Engelhardt   netfilter: xtable...
156
  		return -EINVAL;
9f5673174   Jan Engelhardt   netfilter: xtable...
157
  	if (!(info->flags & XT_SCTP_CHUNK_TYPES))
bd414ee60   Jan Engelhardt   netfilter: xtable...
158
  		return 0;
9f5673174   Jan Engelhardt   netfilter: xtable...
159
160
  	if (info->chunk_match_type & (SCTP_CHUNK_MATCH_ALL |
  	    SCTP_CHUNK_MATCH_ANY | SCTP_CHUNK_MATCH_ONLY))
bd414ee60   Jan Engelhardt   netfilter: xtable...
161
162
  		return 0;
  	return -EINVAL;
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
163
  }
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
164
  static struct xt_match sctp_mt_reg[] __read_mostly = {
4470bbc74   Patrick McHardy   [NETFILTER]: x_ta...
165
166
  	{
  		.name		= "sctp",
ee999d8b9   Jan Engelhardt   netfilter: x_tabl...
167
  		.family		= NFPROTO_IPV4,
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
168
169
  		.checkentry	= sctp_mt_check,
  		.match		= sctp_mt,
4470bbc74   Patrick McHardy   [NETFILTER]: x_ta...
170
171
172
173
174
175
  		.matchsize	= sizeof(struct xt_sctp_info),
  		.proto		= IPPROTO_SCTP,
  		.me		= THIS_MODULE
  	},
  	{
  		.name		= "sctp",
ee999d8b9   Jan Engelhardt   netfilter: x_tabl...
176
  		.family		= NFPROTO_IPV6,
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
177
178
  		.checkentry	= sctp_mt_check,
  		.match		= sctp_mt,
4470bbc74   Patrick McHardy   [NETFILTER]: x_ta...
179
180
181
182
  		.matchsize	= sizeof(struct xt_sctp_info),
  		.proto		= IPPROTO_SCTP,
  		.me		= THIS_MODULE
  	},
5d04bff09   Patrick McHardy   [NETFILTER]: Conv...
183
  };
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
184

d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
185
  static int __init sctp_mt_init(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
  {
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
187
  	return xt_register_matches(sctp_mt_reg, ARRAY_SIZE(sctp_mt_reg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188
  }
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
189
  static void __exit sctp_mt_exit(void)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
190
  {
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
191
  	xt_unregister_matches(sctp_mt_reg, ARRAY_SIZE(sctp_mt_reg));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
  }
d3c5ee6d5   Jan Engelhardt   [NETFILTER]: x_ta...
193
194
  module_init(sctp_mt_init);
  module_exit(sctp_mt_exit);