1 #include <linux/module.h>
2 #include <linux/skbuff.h>
5 #include <linux/sctp.h>
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>
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");
19 #define duprintf(format, args...) printk(format , ## args)
21 #define duprintf(format, args...)
24 #define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
25 || (!!((invflag) & (option)) ^ (cond)))
28 match_flags(const struct xt_sctp_flag_info
*flag_info
,
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
;
43 match_packet(const struct sk_buff
*skb
,
45 const struct xt_sctp_info
*info
,
48 u_int32_t chunkmapcopy
[256 / sizeof (u_int32_t
)];
49 const 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
;
59 if (chunk_match_type
== SCTP_CHUNK_MATCH_ALL
)
60 SCTP_CHUNKMAP_COPY(chunkmapcopy
, info
->chunkmap
);
63 sch
= skb_header_pointer(skb
, offset
, sizeof(_sch
), &_sch
);
64 if (sch
== NULL
|| sch
->length
== 0) {
65 duprintf("Dropping invalid SCTP packet.\n");
70 duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
71 ++i
, offset
, sch
->type
, htons(sch
->length
), sch
->flags
);
73 offset
+= (ntohs(sch
->length
) + 3) & ~3;
75 duprintf("skb->len: %d\toffset: %d\n", skb
->len
, offset
);
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
)) {
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
);
92 case SCTP_CHUNK_MATCH_ONLY
:
93 if (!match_flags(flag_info
, flag_count
,
94 sch
->type
, sch
->flags
))
99 switch (chunk_match_type
) {
100 case SCTP_CHUNK_MATCH_ONLY
:
104 } while (offset
< skb
->len
);
106 switch (chunk_match_type
) {
107 case SCTP_CHUNK_MATCH_ALL
:
108 return SCTP_CHUNKMAP_IS_CLEAR(info
->chunkmap
);
109 case SCTP_CHUNK_MATCH_ANY
:
111 case SCTP_CHUNK_MATCH_ONLY
:
115 /* This will never be reached, but required to stop compiler whine */
120 sctp_mt(const struct sk_buff
*skb
, const struct net_device
*in
,
121 const struct net_device
*out
, const struct xt_match
*match
,
122 const void *matchinfo
, int offset
, unsigned int protoff
, bool *hotdrop
)
124 const struct xt_sctp_info
*info
= matchinfo
;
125 const sctp_sctphdr_t
*sh
;
129 duprintf("Dropping non-first fragment.. FIXME\n");
133 sh
= skb_header_pointer(skb
, protoff
, sizeof(_sh
), &_sh
);
135 duprintf("Dropping evil TCP offset=0 tinygram.\n");
139 duprintf("spt: %d\tdpt: %d\n", ntohs(sh
->source
), ntohs(sh
->dest
));
141 return SCCHECK(ntohs(sh
->source
) >= info
->spts
[0]
142 && ntohs(sh
->source
) <= info
->spts
[1],
143 XT_SCTP_SRC_PORTS
, info
->flags
, info
->invflags
)
144 && SCCHECK(ntohs(sh
->dest
) >= info
->dpts
[0]
145 && ntohs(sh
->dest
) <= info
->dpts
[1],
146 XT_SCTP_DEST_PORTS
, info
->flags
, info
->invflags
)
147 && SCCHECK(match_packet(skb
, protoff
+ sizeof (sctp_sctphdr_t
),
149 XT_SCTP_CHUNK_TYPES
, info
->flags
, info
->invflags
);
153 sctp_mt_check(const char *tablename
, const void *inf
,
154 const struct xt_match
*match
, void *matchinfo
,
155 unsigned int hook_mask
)
157 const struct xt_sctp_info
*info
= matchinfo
;
159 return !(info
->flags
& ~XT_SCTP_VALID_FLAGS
)
160 && !(info
->invflags
& ~XT_SCTP_VALID_FLAGS
)
161 && !(info
->invflags
& ~info
->flags
)
162 && ((!(info
->flags
& XT_SCTP_CHUNK_TYPES
)) ||
163 (info
->chunk_match_type
&
164 (SCTP_CHUNK_MATCH_ALL
165 | SCTP_CHUNK_MATCH_ANY
166 | SCTP_CHUNK_MATCH_ONLY
)));
169 static struct xt_match sctp_mt_reg
[] __read_mostly
= {
173 .checkentry
= sctp_mt_check
,
175 .matchsize
= sizeof(struct xt_sctp_info
),
176 .proto
= IPPROTO_SCTP
,
182 .checkentry
= sctp_mt_check
,
184 .matchsize
= sizeof(struct xt_sctp_info
),
185 .proto
= IPPROTO_SCTP
,
190 static int __init
sctp_mt_init(void)
192 return xt_register_matches(sctp_mt_reg
, ARRAY_SIZE(sctp_mt_reg
));
195 static void __exit
sctp_mt_exit(void)
197 xt_unregister_matches(sctp_mt_reg
, ARRAY_SIZE(sctp_mt_reg
));
200 module_init(sctp_mt_init
);
201 module_exit(sctp_mt_exit
);