1 /* Kernel module to match one of a list of TCP/UDP ports: ports are in
2 the same place so we can treat them as equal. */
3 #include <linux/module.h>
4 #include <linux/types.h>
6 #include <linux/skbuff.h>
7 #include <linux/version.h>
9 #include <linux/netfilter_ipv4/ipt_mport.h>
10 #include <linux/netfilter_ipv4/ip_tables.h>
12 MODULE_LICENSE("GPL");
15 #define duprintf(format, args...) printk(format , ## args)
17 #define duprintf(format, args...)
20 /* Returns 1 if the port is matched by the test, 0 otherwise. */
22 ports_match(const struct ipt_mport
*minfo
, u_int16_t src
, u_int16_t dst
)
26 u_int16_t pflags
= minfo
->pflags
;
27 for (i
=0, m
=1; i
<IPT_MULTI_PORTS
; i
++, m
<<=1) {
31 && minfo
->ports
[i
] == 65535)
37 e
= minfo
->ports
[++i
];
42 if (minfo
->flags
& IPT_MPORT_SOURCE
43 && src
>= s
&& src
<= e
)
46 if (minfo
->flags
& IPT_MPORT_DESTINATION
47 && dst
>= s
&& dst
<= e
)
54 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
59 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
60 match(const struct sk_buff
*skb
, const struct net_device
*in
, const struct net_device
*out
,
61 const struct xt_match
*match
, const void *matchinfo
, int offset
,
62 unsigned int protoff
, int *hotdrop
)
63 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) */
64 match(const struct sk_buff
*skb
, const struct xt_match_param
*par
)
67 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
68 const struct ipt_mport
*minfo
= matchinfo
;
70 const struct ipt_mport
*minfo
= par
->matchinfo
;
71 const int offset
= par
->fragoff
;
73 const struct iphdr
*ip
= ip_hdr(skb
);
74 const struct udphdr
*udp
= (void *)ip
+ ip
->ihl
* 4;
75 unsigned int datalen
= ntohs(ip
->tot_len
);
77 /* Must be big enough to read ports. */
78 if (offset
== 0 && datalen
< sizeof(struct udphdr
)) {
79 /* We've been asked to examine this packet, and we
80 can't. Hence, no choice but to drop. */
82 " Dropping evil offset=0 tinygram.\n");
87 /* Must not be a fragment. */
89 && ports_match(minfo
, ntohs(udp
->source
), ntohs(udp
->dest
));
92 /* Called when user tries to insert an entry of this type. */
93 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
98 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
99 checkentry(const char *tablename
, const void *inf
, const struct xt_match
*match
,
100 void *matchinfo
, unsigned int hook_mask
)
102 checkentry(const struct xt_mtchk_param
*par
)
105 const struct ipt_ip
*ip
= inf
;
107 /* Must specify proto == TCP/UDP, no unknown flags or bad count */
108 return (ip
->proto
== IPPROTO_TCP
|| ip
->proto
== IPPROTO_UDP
)
109 && !(ip
->invflags
& IPT_INV_PROTO
);
112 static struct xt_match mport_match
= {
116 .matchsize
= sizeof(struct ipt_mport
),
117 .checkentry
= &checkentry
,
122 static int __init
init(void)
124 return xt_register_match(&mport_match
);
127 static void __exit
fini(void)
129 xt_unregister_match(&mport_match
);