Blame view

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

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

1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
33
  	return true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  }
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
35
  static inline bool
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
  match_packet(const struct sk_buff *skb,
2e4e6a17a   Harald Welte   [NETFILTER] x_tab...
37
  	     unsigned int offset,
009e8c965   Li Zefan   [NETFILTER]: xt_s...
38
  	     const struct xt_sctp_info *info,
cff533ac1   Jan Engelhardt   [NETFILTER]: x_ta...
39
  	     bool *hotdrop)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  	u_int32_t chunkmapcopy[256 / sizeof (u_int32_t)];
922dbc5be   Xin Long   sctp: remove the ...
42
43
  	const struct sctp_chunkhdr *sch;
  	struct sctp_chunkhdr _sch;
009e8c965   Li Zefan   [NETFILTER]: xt_s...
44
45
46
  	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
47

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

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
  	do {
  		sch = skb_header_pointer(skb, offset, sizeof(_sch), &_sch);
d3dcd4efe   Patrick McHardy   [NETFILTER]: xt_s...
56
  		if (sch == NULL || sch->length == 0) {
be91fd5e3   Jan Engelhardt   netfilter: xtable...
57
58
  			pr_debug("Dropping invalid SCTP packet.
  ");
cff533ac1   Jan Engelhardt   [NETFILTER]: x_ta...
59
  			*hotdrop = true;
1d93a9cba   Jan Engelhardt   [NETFILTER]: x_ta...
60
  			return false;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
61
  		}
be91fd5e3   Jan Engelhardt   netfilter: xtable...
62
63
64
65
66
67
68
  #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
e2f036a97   Marcelo Ricardo Leitner   sctp: rename WORD...
69
  		offset += SCTP_PAD4(ntohs(sch->length));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70

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

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

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

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

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

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

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