2 * iptables module to match inet_addr_type() of an ip.
4 * Copyright (c) 2004 Patrick McHardy <kaber@trash.net>
5 * (C) 2007 Laszlo Attila Toth <panther@balabit.hu>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/skbuff.h>
15 #include <linux/netdevice.h>
17 #include <net/route.h>
19 #include <linux/netfilter_ipv4/ipt_addrtype.h>
20 #include <linux/netfilter/x_tables.h>
22 MODULE_LICENSE("GPL");
23 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
24 MODULE_DESCRIPTION("Xtables: address type match for IPv4");
26 static inline bool match_type(struct net
*net
, const struct net_device
*dev
,
27 __be32 addr
, u_int16_t mask
)
29 return !!(mask
& (1 << inet_dev_addr_type(net
, dev
, addr
)));
33 addrtype_mt_v0(const struct sk_buff
*skb
, struct xt_action_param
*par
)
35 struct net
*net
= dev_net(par
->in
? par
->in
: par
->out
);
36 const struct ipt_addrtype_info
*info
= par
->matchinfo
;
37 const struct iphdr
*iph
= ip_hdr(skb
);
41 ret
&= match_type(net
, NULL
, iph
->saddr
, info
->source
) ^
44 ret
&= match_type(net
, NULL
, iph
->daddr
, info
->dest
) ^
51 addrtype_mt_v1(const struct sk_buff
*skb
, struct xt_action_param
*par
)
53 struct net
*net
= dev_net(par
->in
? par
->in
: par
->out
);
54 const struct ipt_addrtype_info_v1
*info
= par
->matchinfo
;
55 const struct iphdr
*iph
= ip_hdr(skb
);
56 const struct net_device
*dev
= NULL
;
59 if (info
->flags
& IPT_ADDRTYPE_LIMIT_IFACE_IN
)
61 else if (info
->flags
& IPT_ADDRTYPE_LIMIT_IFACE_OUT
)
65 ret
&= match_type(net
, dev
, iph
->saddr
, info
->source
) ^
66 (info
->flags
& IPT_ADDRTYPE_INVERT_SOURCE
);
67 if (ret
&& info
->dest
)
68 ret
&= match_type(net
, dev
, iph
->daddr
, info
->dest
) ^
69 !!(info
->flags
& IPT_ADDRTYPE_INVERT_DEST
);
73 static int addrtype_mt_checkentry_v1(const struct xt_mtchk_param
*par
)
75 struct ipt_addrtype_info_v1
*info
= par
->matchinfo
;
77 if (info
->flags
& IPT_ADDRTYPE_LIMIT_IFACE_IN
&&
78 info
->flags
& IPT_ADDRTYPE_LIMIT_IFACE_OUT
) {
79 pr_info("both incoming and outgoing "
80 "interface limitation cannot be selected\n");
84 if (par
->hook_mask
& ((1 << NF_INET_PRE_ROUTING
) |
85 (1 << NF_INET_LOCAL_IN
)) &&
86 info
->flags
& IPT_ADDRTYPE_LIMIT_IFACE_OUT
) {
87 pr_info("output interface limitation "
88 "not valid in PREROUTING and INPUT\n");
92 if (par
->hook_mask
& ((1 << NF_INET_POST_ROUTING
) |
93 (1 << NF_INET_LOCAL_OUT
)) &&
94 info
->flags
& IPT_ADDRTYPE_LIMIT_IFACE_IN
) {
95 pr_info("input interface limitation "
96 "not valid in POSTROUTING and OUTPUT\n");
103 static struct xt_match addrtype_mt_reg
[] __read_mostly
= {
106 .family
= NFPROTO_IPV4
,
107 .match
= addrtype_mt_v0
,
108 .matchsize
= sizeof(struct ipt_addrtype_info
),
113 .family
= NFPROTO_IPV4
,
115 .match
= addrtype_mt_v1
,
116 .checkentry
= addrtype_mt_checkentry_v1
,
117 .matchsize
= sizeof(struct ipt_addrtype_info_v1
),
122 static int __init
addrtype_mt_init(void)
124 return xt_register_matches(addrtype_mt_reg
,
125 ARRAY_SIZE(addrtype_mt_reg
));
128 static void __exit
addrtype_mt_exit(void)
130 xt_unregister_matches(addrtype_mt_reg
, ARRAY_SIZE(addrtype_mt_reg
));
133 module_init(addrtype_mt_init
);
134 module_exit(addrtype_mt_exit
);