-
Notifications
You must be signed in to change notification settings - Fork 3
/
xt_ipaddr.c
138 lines (113 loc) · 3.14 KB
/
xt_ipaddr.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netfilter/x_tables.h>
#include <net/ipv6.h>
#include <linux/ipv6.h>
#include <linux/ip.h>
#include "xt_ipaddr.h"
MODULE_AUTHOR("Me and <[email protected]>");
MODULE_DESCRIPTION("Xtables: Match source/destination address");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ip6t_ipaddr");
static bool ipaddr_mt(const struct sk_buff *skb,
struct xt_action_param *par)
{
const struct xt_ipaddr_mtinfo *info = par->matchinfo;
const struct ipv6hdr *iph = ipv6_hdr(skb);
pr_info("xt_ipaddr: IN=%s OUT=%s "
"SRC=%pI6 DST=%pI6 "
"IPSRC=%pI6 IPDST=%pI6\n",
(par->in != NULL) ? par->in->name : "",
(par->out != NULL) ? par->out->name : "",
&iph->saddr, &iph->daddr,
&info->src, &info->dst);
if (info->flags & XT_IPADDR_SRC)
if ((ipv6_addr_cmp(&iph->saddr, &info->src.in6) != 0) ^
!!(info->flags & XT_IPADDR_INV_SRC)) {
pr_notice("src IP - no match\n");
return false;
}
if (info->flags & XT_IPADDR_DST)
if ((ipv6_addr_cmp(&iph->daddr, &info->dst.in6) != 0) ^
!!(info->flags & XT_IPADDR_INV_DST)) {
pr_info("dst IP - no match\n");
return false;
}
return true;
}
static int ipaddr_mt_check(const struct xt_mtchk_param *par)
{
const struct xt_ipaddr_mtinfo *info = par->matchinfo;
if(!(info->flags & (XT_IPADDR_SRC | XT_IPADDR_DST))) {
pr_info("not testing anything\n");
return -EINVAL;
}
if (ntohl(info->src.ip6[0]) == 0x20010DB8) {
/* Disallow test network 2001:db8::/32 */
pr_info("I'm sorry, Dave. "
"I'm afraid I can't let you do that.\n");
return -EPERM;
}
return 0;
}
static void ipaddr_mt_destroy(const struct xt_mtdtor_param *par)
{
const struct xt_ipaddr_mtinfo *info = par->matchinfo;
pr_info("Test for address %pI6 removed\n",
&info->src.ip6);
}
static bool ipaddr_mt4(const struct sk_buff *skb,
struct xt_action_param *par)
{
const struct xt_ipaddr_mtinfo *info = par->matchinfo;
const struct iphdr *iph = ip_hdr(skb);
if (info->flags & XT_IPADDR_SRC)
if ((iph->saddr != info->src.ip) ^
!!(info->flags & XT_IPADDR_INV_SRC))
return false;
if (info->flags & XT_IPADDR_DST)
if ((iph->daddr != info->dst.ip) ^
!! (info->flags & XT_IPADDR_INV_SRC))
return false;
return true;
}
static struct xt_match ipaddr_mt4_reg __read_mostly = {
.name = "ipaddr",
.revision = 0,
.family = NFPROTO_IPV6,
.match = ipaddr_mt4,
.matchsize = sizeof(struct xt_ipaddr_mtinfo),
.me = THIS_MODULE,
};
static struct xt_match ipaddr_mt_reg __read_mostly = {
.name = "ipaddr",
.revision = 0,
.family = NFPROTO_IPV6,
.match = ipaddr_mt,
.checkentry = ipaddr_mt_check,
.destroy = ipaddr_mt_destroy,
.matchsize = sizeof(struct xt_ipaddr_mtinfo),
.me = THIS_MODULE,
};
static int __init ipaddr_mt_init(void)
{
int ret;
ret = xt_register_match(&ipaddr_mt_reg);
if (ret < 0)
return ret;
ret = xt_register_match(&ipaddr_mt4_reg);
if (ret < 0) {
xt_unregister_match(&ipaddr_mt_reg);
return ret;
}
return 0;
}
static void __exit ipaddr_mt_exit(void)
{
xt_unregister_match(&ipaddr_mt_reg);
xt_unregister_match(&ipaddr_mt4_reg);
}
module_init(ipaddr_mt_init);
module_exit(ipaddr_mt_exit);