Commit | Line | Data |
---|---|---|
a7b4f989 JK |
1 | /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> |
2 | * Patrick Schaaf <bof@bof.de> | |
3 | * Martin Josefsson <gandalf@wlug.westbo.se> | |
4 | * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | */ | |
a8201414 DH |
10 | #ifndef _IP_SET_H |
11 | #define _IP_SET_H | |
a7b4f989 | 12 | |
ae8ded1c JE |
13 | #include <linux/ip.h> |
14 | #include <linux/ipv6.h> | |
15 | #include <linux/netlink.h> | |
16 | #include <linux/netfilter.h> | |
17 | #include <linux/netfilter/x_tables.h> | |
10111a6e | 18 | #include <linux/stringify.h> |
ae8ded1c JE |
19 | #include <linux/vmalloc.h> |
20 | #include <net/netlink.h> | |
a8201414 | 21 | #include <uapi/linux/netfilter/ipset/ip_set.h> |
ae8ded1c | 22 | |
10111a6e JK |
23 | #define _IP_SET_MODULE_DESC(a, b, c) \ |
24 | MODULE_DESCRIPTION(a " type of IP sets, revisions " b "-" c) | |
25 | #define IP_SET_MODULE_DESC(a, b, c) \ | |
26 | _IP_SET_MODULE_DESC(a, __stringify(b), __stringify(c)) | |
27 | ||
a7b4f989 JK |
28 | /* Set features */ |
29 | enum ip_set_feature { | |
30 | IPSET_TYPE_IP_FLAG = 0, | |
31 | IPSET_TYPE_IP = (1 << IPSET_TYPE_IP_FLAG), | |
32 | IPSET_TYPE_PORT_FLAG = 1, | |
33 | IPSET_TYPE_PORT = (1 << IPSET_TYPE_PORT_FLAG), | |
34 | IPSET_TYPE_MAC_FLAG = 2, | |
35 | IPSET_TYPE_MAC = (1 << IPSET_TYPE_MAC_FLAG), | |
36 | IPSET_TYPE_IP2_FLAG = 3, | |
37 | IPSET_TYPE_IP2 = (1 << IPSET_TYPE_IP2_FLAG), | |
38 | IPSET_TYPE_NAME_FLAG = 4, | |
39 | IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG), | |
e385357a JK |
40 | IPSET_TYPE_IFACE_FLAG = 5, |
41 | IPSET_TYPE_IFACE = (1 << IPSET_TYPE_IFACE_FLAG), | |
3e0304a5 JK |
42 | IPSET_TYPE_NOMATCH_FLAG = 6, |
43 | IPSET_TYPE_NOMATCH = (1 << IPSET_TYPE_NOMATCH_FLAG), | |
a7b4f989 JK |
44 | /* Strictly speaking not a feature, but a flag for dumping: |
45 | * this settype must be dumped last */ | |
46 | IPSET_DUMP_LAST_FLAG = 7, | |
47 | IPSET_DUMP_LAST = (1 << IPSET_DUMP_LAST_FLAG), | |
48 | }; | |
49 | ||
50 | struct ip_set; | |
51 | ||
5416219e JK |
52 | typedef int (*ipset_adtfn)(struct ip_set *set, void *value, |
53 | u32 timeout, u32 flags); | |
a7b4f989 | 54 | |
ac8cc925 JK |
55 | /* Kernel API function options */ |
56 | struct ip_set_adt_opt { | |
57 | u8 family; /* Actual protocol family */ | |
58 | u8 dim; /* Dimension of match/target */ | |
59 | u8 flags; /* Direction and negation flags */ | |
60 | u32 cmdflags; /* Command-like flags */ | |
61 | u32 timeout; /* Timeout value */ | |
62 | }; | |
63 | ||
a7b4f989 JK |
64 | /* Set type, variant-specific part */ |
65 | struct ip_set_type_variant { | |
66 | /* Kernelspace: test/add/del entries | |
67 | * returns negative error code, | |
68 | * zero for no match/success to add/delete | |
69 | * positive for matching element */ | |
3ace95c0 | 70 | int (*kadt)(struct ip_set *set, const struct sk_buff *skb, |
b66554cf | 71 | const struct xt_action_param *par, |
ac8cc925 | 72 | enum ipset_adt adt, const struct ip_set_adt_opt *opt); |
a7b4f989 JK |
73 | |
74 | /* Userspace: test/add/del entries | |
75 | * returns negative error code, | |
76 | * zero for no match/success to add/delete | |
77 | * positive for matching element */ | |
78 | int (*uadt)(struct ip_set *set, struct nlattr *tb[], | |
3d14b171 | 79 | enum ipset_adt adt, u32 *lineno, u32 flags, bool retried); |
a7b4f989 JK |
80 | |
81 | /* Low level add/del/test functions */ | |
82 | ipset_adtfn adt[IPSET_ADT_MAX]; | |
83 | ||
84 | /* When adding entries and set is full, try to resize the set */ | |
85 | int (*resize)(struct ip_set *set, bool retried); | |
86 | /* Destroy the set */ | |
87 | void (*destroy)(struct ip_set *set); | |
88 | /* Flush the elements */ | |
89 | void (*flush)(struct ip_set *set); | |
90 | /* Expire entries before listing */ | |
91 | void (*expire)(struct ip_set *set); | |
92 | /* List set header data */ | |
93 | int (*head)(struct ip_set *set, struct sk_buff *skb); | |
94 | /* List elements */ | |
95 | int (*list)(const struct ip_set *set, struct sk_buff *skb, | |
96 | struct netlink_callback *cb); | |
97 | ||
98 | /* Return true if "b" set is the same as "a" | |
99 | * according to the create set parameters */ | |
100 | bool (*same_set)(const struct ip_set *a, const struct ip_set *b); | |
101 | }; | |
102 | ||
103 | /* The core set type structure */ | |
104 | struct ip_set_type { | |
105 | struct list_head list; | |
106 | ||
107 | /* Typename */ | |
108 | char name[IPSET_MAXNAMELEN]; | |
109 | /* Protocol version */ | |
110 | u8 protocol; | |
111 | /* Set features to control swapping */ | |
112 | u8 features; | |
113 | /* Set type dimension */ | |
114 | u8 dimension; | |
c15f1c83 JE |
115 | /* |
116 | * Supported family: may be NFPROTO_UNSPEC for both | |
117 | * NFPROTO_IPV4/NFPROTO_IPV6. | |
118 | */ | |
a7b4f989 | 119 | u8 family; |
f1e00b39 JK |
120 | /* Type revisions */ |
121 | u8 revision_min, revision_max; | |
a7b4f989 JK |
122 | |
123 | /* Create set */ | |
124 | int (*create)(struct ip_set *set, struct nlattr *tb[], u32 flags); | |
125 | ||
126 | /* Attribute policies */ | |
127 | const struct nla_policy create_policy[IPSET_ATTR_CREATE_MAX + 1]; | |
128 | const struct nla_policy adt_policy[IPSET_ATTR_ADT_MAX + 1]; | |
129 | ||
130 | /* Set this to THIS_MODULE if you are a module, otherwise NULL */ | |
131 | struct module *me; | |
132 | }; | |
133 | ||
134 | /* register and unregister set type */ | |
135 | extern int ip_set_type_register(struct ip_set_type *set_type); | |
136 | extern void ip_set_type_unregister(struct ip_set_type *set_type); | |
137 | ||
138 | /* A generic IP set */ | |
139 | struct ip_set { | |
140 | /* The name of the set */ | |
141 | char name[IPSET_MAXNAMELEN]; | |
142 | /* Lock protecting the set data */ | |
143 | rwlock_t lock; | |
144 | /* References to the set */ | |
2f9f28b2 | 145 | u32 ref; |
a7b4f989 JK |
146 | /* The core set type */ |
147 | struct ip_set_type *type; | |
148 | /* The type variant doing the real job */ | |
149 | const struct ip_set_type_variant *variant; | |
150 | /* The actual INET family of the set */ | |
151 | u8 family; | |
f1e00b39 JK |
152 | /* The type revision */ |
153 | u8 revision; | |
a7b4f989 JK |
154 | /* The type specific data */ |
155 | void *data; | |
156 | }; | |
157 | ||
158 | /* register and unregister set references */ | |
159 | extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set); | |
160 | extern void ip_set_put_byindex(ip_set_id_t index); | |
15b4d93f | 161 | extern const char *ip_set_name_byindex(ip_set_id_t index); |
a7b4f989 JK |
162 | extern ip_set_id_t ip_set_nfnl_get(const char *name); |
163 | extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index); | |
164 | extern void ip_set_nfnl_put(ip_set_id_t index); | |
165 | ||
166 | /* API for iptables set match, and SET target */ | |
ac8cc925 | 167 | |
a7b4f989 | 168 | extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb, |
b66554cf | 169 | const struct xt_action_param *par, |
ac8cc925 | 170 | const struct ip_set_adt_opt *opt); |
a7b4f989 | 171 | extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb, |
b66554cf | 172 | const struct xt_action_param *par, |
ac8cc925 | 173 | const struct ip_set_adt_opt *opt); |
a7b4f989 | 174 | extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb, |
b66554cf | 175 | const struct xt_action_param *par, |
ac8cc925 | 176 | const struct ip_set_adt_opt *opt); |
a7b4f989 JK |
177 | |
178 | /* Utility functions */ | |
15b4d93f | 179 | extern void *ip_set_alloc(size_t size); |
a7b4f989 JK |
180 | extern void ip_set_free(void *members); |
181 | extern int ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr); | |
182 | extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr); | |
183 | ||
184 | static inline int | |
185 | ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr) | |
186 | { | |
187 | __be32 ip; | |
188 | int ret = ip_set_get_ipaddr4(nla, &ip); | |
15b4d93f | 189 | |
a7b4f989 JK |
190 | if (ret) |
191 | return ret; | |
192 | *ipaddr = ntohl(ip); | |
193 | return 0; | |
194 | } | |
195 | ||
196 | /* Ignore IPSET_ERR_EXIST errors if asked to do so? */ | |
197 | static inline bool | |
198 | ip_set_eexist(int ret, u32 flags) | |
199 | { | |
200 | return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST); | |
201 | } | |
202 | ||
203 | /* Check the NLA_F_NET_BYTEORDER flag */ | |
204 | static inline bool | |
205 | ip_set_attr_netorder(struct nlattr *tb[], int type) | |
206 | { | |
207 | return tb[type] && (tb[type]->nla_type & NLA_F_NET_BYTEORDER); | |
208 | } | |
209 | ||
210 | static inline bool | |
211 | ip_set_optattr_netorder(struct nlattr *tb[], int type) | |
212 | { | |
213 | return !tb[type] || (tb[type]->nla_type & NLA_F_NET_BYTEORDER); | |
214 | } | |
215 | ||
216 | /* Useful converters */ | |
217 | static inline u32 | |
218 | ip_set_get_h32(const struct nlattr *attr) | |
219 | { | |
220 | return ntohl(nla_get_be32(attr)); | |
221 | } | |
222 | ||
223 | static inline u16 | |
224 | ip_set_get_h16(const struct nlattr *attr) | |
225 | { | |
226 | return ntohs(nla_get_be16(attr)); | |
227 | } | |
228 | ||
229 | #define ipset_nest_start(skb, attr) nla_nest_start(skb, attr | NLA_F_NESTED) | |
230 | #define ipset_nest_end(skb, start) nla_nest_end(skb, start) | |
231 | ||
7cf7899d DM |
232 | static inline int nla_put_ipaddr4(struct sk_buff *skb, int type, __be32 ipaddr) |
233 | { | |
234 | struct nlattr *__nested = ipset_nest_start(skb, type); | |
235 | int ret; | |
236 | ||
237 | if (!__nested) | |
238 | return -EMSGSIZE; | |
239 | ret = nla_put_net32(skb, IPSET_ATTR_IPADDR_IPV4, ipaddr); | |
240 | if (!ret) | |
241 | ipset_nest_end(skb, __nested); | |
242 | return ret; | |
243 | } | |
244 | ||
3ace95c0 JK |
245 | static inline int nla_put_ipaddr6(struct sk_buff *skb, int type, |
246 | const struct in6_addr *ipaddrptr) | |
7cf7899d DM |
247 | { |
248 | struct nlattr *__nested = ipset_nest_start(skb, type); | |
249 | int ret; | |
250 | ||
251 | if (!__nested) | |
252 | return -EMSGSIZE; | |
253 | ret = nla_put(skb, IPSET_ATTR_IPADDR_IPV6, | |
254 | sizeof(struct in6_addr), ipaddrptr); | |
255 | if (!ret) | |
256 | ipset_nest_end(skb, __nested); | |
257 | return ret; | |
258 | } | |
a7b4f989 JK |
259 | |
260 | /* Get address from skbuff */ | |
261 | static inline __be32 | |
262 | ip4addr(const struct sk_buff *skb, bool src) | |
263 | { | |
264 | return src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr; | |
265 | } | |
266 | ||
267 | static inline void | |
268 | ip4addrptr(const struct sk_buff *skb, bool src, __be32 *addr) | |
269 | { | |
270 | *addr = src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr; | |
271 | } | |
272 | ||
273 | static inline void | |
274 | ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr) | |
275 | { | |
276 | memcpy(addr, src ? &ipv6_hdr(skb)->saddr : &ipv6_hdr(skb)->daddr, | |
277 | sizeof(*addr)); | |
278 | } | |
279 | ||
280 | /* Calculate the bytes required to store the inclusive range of a-b */ | |
281 | static inline int | |
282 | bitmap_bytes(u32 a, u32 b) | |
283 | { | |
284 | return 4 * ((((b - a + 8) / 8) + 3) / 4); | |
285 | } | |
286 | ||
a7b4f989 | 287 | #endif /*_IP_SET_H */ |