1 #include <linux/module.h>
2 #include <linux/skbuff.h>
4 #include <linux/sctp.h>
6 #include <linux/netfilter_ipv4/ip_tables.h>
7 #include <linux/netfilter_ipv4/ipt_sctp.h>
10 #define duprintf(format, args...) printk(format , ## args)
12 #define duprintf(format, args...)
15 #define SCCHECK(cond, option, flag, invflag) (!((flag) & (option)) \
16 || (!!((invflag) & (option)) ^ (cond)))
19 match_flags(const struct ipt_sctp_flag_info
*flag_info
,
26 for (i
= 0; i
< flag_count
; i
++) {
27 if (flag_info
[i
].chunktype
== chunktype
) {
28 return (chunkflags
& flag_info
[i
].flag_mask
) == flag_info
[i
].flag
;
36 match_packet(const struct sk_buff
*skb
,
37 const u_int32_t
*chunkmap
,
39 const struct ipt_sctp_flag_info
*flag_info
,
44 u_int32_t chunkmapcopy
[256 / sizeof (u_int32_t
)];
45 sctp_chunkhdr_t _sch
, *sch
;
51 if (chunk_match_type
== SCTP_CHUNK_MATCH_ALL
) {
52 SCTP_CHUNKMAP_COPY(chunkmapcopy
, chunkmap
);
55 offset
= skb
->nh
.iph
->ihl
* 4 + sizeof (sctp_sctphdr_t
);
57 sch
= skb_header_pointer(skb
, offset
, sizeof(_sch
), &_sch
);
59 duprintf("Dropping invalid SCTP packet.\n");
64 duprintf("Chunk num: %d\toffset: %d\ttype: %d\tlength: %d\tflags: %x\n",
65 ++i
, offset
, sch
->type
, htons(sch
->length
), sch
->flags
);
67 offset
+= (htons(sch
->length
) + 3) & ~3;
69 duprintf("skb->len: %d\toffset: %d\n", skb
->len
, offset
);
71 if (SCTP_CHUNKMAP_IS_SET(chunkmap
, sch
->type
)) {
72 switch (chunk_match_type
) {
73 case SCTP_CHUNK_MATCH_ANY
:
74 if (match_flags(flag_info
, flag_count
,
75 sch
->type
, sch
->flags
)) {
80 case SCTP_CHUNK_MATCH_ALL
:
81 if (match_flags(flag_info
, flag_count
,
82 sch
->type
, sch
->flags
)) {
83 SCTP_CHUNKMAP_CLEAR(chunkmapcopy
, sch
->type
);
87 case SCTP_CHUNK_MATCH_ONLY
:
88 if (!match_flags(flag_info
, flag_count
,
89 sch
->type
, sch
->flags
)) {
95 switch (chunk_match_type
) {
96 case SCTP_CHUNK_MATCH_ONLY
:
100 } while (offset
< skb
->len
);
102 switch (chunk_match_type
) {
103 case SCTP_CHUNK_MATCH_ALL
:
104 return SCTP_CHUNKMAP_IS_CLEAR(chunkmap
);
105 case SCTP_CHUNK_MATCH_ANY
:
107 case SCTP_CHUNK_MATCH_ONLY
:
111 /* This will never be reached, but required to stop compiler whine */
116 match(const struct sk_buff
*skb
,
117 const struct net_device
*in
,
118 const struct net_device
*out
,
119 const void *matchinfo
,
123 const struct ipt_sctp_info
*info
;
124 sctp_sctphdr_t _sh
, *sh
;
126 info
= (const struct ipt_sctp_info
*)matchinfo
;
129 duprintf("Dropping non-first fragment.. FIXME\n");
133 sh
= skb_header_pointer(skb
, skb
->nh
.iph
->ihl
*4, 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 IPT_SCTP_SRC_PORTS
, info
->flags
, info
->invflags
)
144 && SCCHECK(((ntohs(sh
->dest
) >= info
->dpts
[0])
145 && (ntohs(sh
->dest
) <= info
->dpts
[1])),
146 IPT_SCTP_DEST_PORTS
, info
->flags
, info
->invflags
)
147 && SCCHECK(match_packet(skb
, info
->chunkmap
, info
->chunk_match_type
,
148 info
->flag_info
, info
->flag_count
,
150 IPT_SCTP_CHUNK_TYPES
, info
->flags
, info
->invflags
);
154 checkentry(const char *tablename
,
155 const struct ipt_ip
*ip
,
157 unsigned int matchsize
,
158 unsigned int hook_mask
)
160 const struct ipt_sctp_info
*info
;
162 info
= (const struct ipt_sctp_info
*)matchinfo
;
164 return ip
->proto
== IPPROTO_SCTP
165 && !(ip
->invflags
& IPT_INV_PROTO
)
166 && matchsize
== IPT_ALIGN(sizeof(struct ipt_sctp_info
))
167 && !(info
->flags
& ~IPT_SCTP_VALID_FLAGS
)
168 && !(info
->invflags
& ~IPT_SCTP_VALID_FLAGS
)
169 && !(info
->invflags
& ~info
->flags
)
170 && ((!(info
->flags
& IPT_SCTP_CHUNK_TYPES
)) ||
171 (info
->chunk_match_type
&
172 (SCTP_CHUNK_MATCH_ALL
173 | SCTP_CHUNK_MATCH_ANY
174 | SCTP_CHUNK_MATCH_ONLY
)));
177 static struct ipt_match sctp_match
=
179 .list
= { NULL
, NULL
},
182 .checkentry
= &checkentry
,
187 static int __init
init(void)
189 return ipt_register_match(&sctp_match
);
192 static void __exit
fini(void)
194 ipt_unregister_match(&sctp_match
);
200 MODULE_LICENSE("GPL");
201 MODULE_AUTHOR("Kiran Kumar Immidi");
202 MODULE_DESCRIPTION("Match for SCTP protocol packets");