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-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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.
11 /* Kernel module implementing an IP set type: the macipmap type */
13 #include <linux/module.h>
15 #include <linux/skbuff.h>
16 #include <linux/netfilter_ipv4/ip_tables.h>
17 #include <linux/netfilter_ipv4/ip_set.h>
18 #include <linux/errno.h>
19 #include <asm/uaccess.h>
20 #include <asm/bitops.h>
21 #include <linux/spinlock.h>
22 #include <linux/if_ether.h>
23 #include <linux/vmalloc.h>
25 #include <linux/netfilter_ipv4/ip_set_malloc.h>
26 #include <linux/netfilter_ipv4/ip_set_macipmap.h>
29 testip(struct ip_set *set, const void *data, size_t size, ip_set_ip_t *hash_ip)
31 struct ip_set_macipmap *map = (struct ip_set_macipmap *) set->data;
32 struct ip_set_macip *table = (struct ip_set_macip *) map->members;
33 struct ip_set_req_macipmap *req = (struct ip_set_req_macipmap *) data;
35 if (size != sizeof(struct ip_set_req_macipmap)) {
36 ip_set_printk("data length wrong (want %zu, have %zu)",
37 sizeof(struct ip_set_req_macipmap),
42 if (req->ip < map->first_ip || req->ip > map->last_ip)
46 DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
47 set->name, HIPQUAD(req->ip), HIPQUAD(*hash_ip));
48 if (test_bit(IPSET_MACIP_ISSET,
49 (void *) &table[req->ip - map->first_ip].flags)) {
50 return (memcmp(req->ethernet,
51 &table[req->ip - map->first_ip].ethernet,
54 return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
59 testip_kernel(struct ip_set *set,
60 const struct sk_buff *skb,
62 const u_int32_t *flags,
65 struct ip_set_macipmap *map =
66 (struct ip_set_macipmap *) set->data;
67 struct ip_set_macip *table =
68 (struct ip_set_macip *) map->members;
71 ip = ntohl(flags[index] & IPSET_SRC
73 : skb->nh.iph->daddr);
74 DP("flag: %s src: %u.%u.%u.%u dst: %u.%u.%u.%u",
75 flags[index] & IPSET_SRC ? "SRC" : "DST",
76 NIPQUAD(skb->nh.iph->saddr),
77 NIPQUAD(skb->nh.iph->daddr));
79 if (ip < map->first_ip || ip > map->last_ip)
83 DP("set: %s, ip:%u.%u.%u.%u, %u.%u.%u.%u",
84 set->name, HIPQUAD(ip), HIPQUAD(*hash_ip));
85 if (test_bit(IPSET_MACIP_ISSET,
86 (void *) &table[ip - map->first_ip].flags)) {
87 /* Is mac pointer valid?
88 * If so, compare... */
89 return (skb->mac.raw >= skb->head
90 && (skb->mac.raw + ETH_HLEN) <= skb->data
91 && (memcmp(eth_hdr(skb)->h_source,
92 &table[ip - map->first_ip].ethernet,
95 return (map->flags & IPSET_MACIP_MATCHUNSET ? 1 : 0);
99 /* returns 0 on success */
101 __addip(struct ip_set *set,
102 ip_set_ip_t ip, unsigned char *ethernet, ip_set_ip_t *hash_ip)
104 struct ip_set_macipmap *map =
105 (struct ip_set_macipmap *) set->data;
106 struct ip_set_macip *table =
107 (struct ip_set_macip *) map->members;
109 if (ip < map->first_ip || ip > map->last_ip)
111 if (test_and_set_bit(IPSET_MACIP_ISSET,
112 (void *) &table[ip - map->first_ip].flags))
116 DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
117 memcpy(&table[ip - map->first_ip].ethernet, ethernet, ETH_ALEN);
122 addip(struct ip_set *set, const void *data, size_t size,
123 ip_set_ip_t *hash_ip)
125 struct ip_set_req_macipmap *req =
126 (struct ip_set_req_macipmap *) data;
128 if (size != sizeof(struct ip_set_req_macipmap)) {
129 ip_set_printk("data length wrong (want %zu, have %zu)",
130 sizeof(struct ip_set_req_macipmap),
134 return __addip(set, req->ip, req->ethernet, hash_ip);
138 addip_kernel(struct ip_set *set,
139 const struct sk_buff *skb,
140 ip_set_ip_t *hash_ip,
141 const u_int32_t *flags,
146 ip = ntohl(flags[index] & IPSET_SRC
148 : skb->nh.iph->daddr);
150 if (!(skb->mac.raw >= skb->head
151 && (skb->mac.raw + ETH_HLEN) <= skb->data))
154 return __addip(set, ip, eth_hdr(skb)->h_source, hash_ip);
158 __delip(struct ip_set *set, ip_set_ip_t ip, ip_set_ip_t *hash_ip)
160 struct ip_set_macipmap *map =
161 (struct ip_set_macipmap *) set->data;
162 struct ip_set_macip *table =
163 (struct ip_set_macip *) map->members;
165 if (ip < map->first_ip || ip > map->last_ip)
167 if (!test_and_clear_bit(IPSET_MACIP_ISSET,
168 (void *)&table[ip - map->first_ip].flags))
172 DP("%u.%u.%u.%u, %u.%u.%u.%u", HIPQUAD(ip), HIPQUAD(*hash_ip));
177 delip(struct ip_set *set, const void *data, size_t size,
178 ip_set_ip_t *hash_ip)
180 struct ip_set_req_macipmap *req =
181 (struct ip_set_req_macipmap *) data;
183 if (size != sizeof(struct ip_set_req_macipmap)) {
184 ip_set_printk("data length wrong (want %zu, have %zu)",
185 sizeof(struct ip_set_req_macipmap),
189 return __delip(set, req->ip, hash_ip);
193 delip_kernel(struct ip_set *set,
194 const struct sk_buff *skb,
195 ip_set_ip_t *hash_ip,
196 const u_int32_t *flags,
200 ntohl(flags[index] & IPSET_SRC
202 : skb->nh.iph->daddr),
206 static inline size_t members_size(ip_set_id_t from, ip_set_id_t to)
208 return (size_t)((to - from + 1) * sizeof(struct ip_set_macip));
211 static int create(struct ip_set *set, const void *data, size_t size)
214 struct ip_set_req_macipmap_create *req =
215 (struct ip_set_req_macipmap_create *) data;
216 struct ip_set_macipmap *map;
218 if (size != sizeof(struct ip_set_req_macipmap_create)) {
219 ip_set_printk("data length wrong (want %zu, have %zu)",
220 sizeof(struct ip_set_req_macipmap_create),
225 DP("from %u.%u.%u.%u to %u.%u.%u.%u",
226 HIPQUAD(req->from), HIPQUAD(req->to));
228 if (req->from > req->to) {
233 if (req->to - req->from > MAX_RANGE) {
234 ip_set_printk("range too big (max %d addresses)",
239 map = kmalloc(sizeof(struct ip_set_macipmap), GFP_KERNEL);
241 DP("out of memory for %d bytes",
242 sizeof(struct ip_set_macipmap));
245 map->flags = req->flags;
246 map->first_ip = req->from;
247 map->last_ip = req->to;
248 newbytes = members_size(map->first_ip, map->last_ip);
249 map->members = ip_set_malloc(newbytes);
250 DP("members: %u %p", newbytes, map->members);
252 DP("out of memory for %d bytes", newbytes);
256 memset(map->members, 0, newbytes);
262 static void destroy(struct ip_set *set)
264 struct ip_set_macipmap *map =
265 (struct ip_set_macipmap *) set->data;
267 ip_set_free(map->members, members_size(map->first_ip, map->last_ip));
273 static void flush(struct ip_set *set)
275 struct ip_set_macipmap *map =
276 (struct ip_set_macipmap *) set->data;
277 memset(map->members, 0, members_size(map->first_ip, map->last_ip));
280 static void list_header(const struct ip_set *set, void *data)
282 struct ip_set_macipmap *map =
283 (struct ip_set_macipmap *) set->data;
284 struct ip_set_req_macipmap_create *header =
285 (struct ip_set_req_macipmap_create *) data;
287 DP("list_header %x %x %u", map->first_ip, map->last_ip,
290 header->from = map->first_ip;
291 header->to = map->last_ip;
292 header->flags = map->flags;
295 static int list_members_size(const struct ip_set *set)
297 struct ip_set_macipmap *map =
298 (struct ip_set_macipmap *) set->data;
300 DP("%u", members_size(map->first_ip, map->last_ip));
301 return members_size(map->first_ip, map->last_ip);
304 static void list_members(const struct ip_set *set, void *data)
306 struct ip_set_macipmap *map =
307 (struct ip_set_macipmap *) set->data;
309 int bytes = members_size(map->first_ip, map->last_ip);
311 DP("members: %u %p", bytes, map->members);
312 memcpy(data, map->members, bytes);
315 static struct ip_set_type ip_set_macipmap = {
316 .typename = SETTYPE_NAME,
317 .features = IPSET_TYPE_IP | IPSET_DATA_SINGLE,
318 .protocol_version = IP_SET_PROTOCOL_VERSION,
322 .reqsize = sizeof(struct ip_set_req_macipmap),
324 .addip_kernel = &addip_kernel,
326 .delip_kernel = &delip_kernel,
328 .testip_kernel = &testip_kernel,
329 .header_size = sizeof(struct ip_set_req_macipmap_create),
330 .list_header = &list_header,
331 .list_members_size = &list_members_size,
332 .list_members = &list_members,
336 MODULE_LICENSE("GPL");
337 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
338 MODULE_DESCRIPTION("macipmap type of IP sets");
340 static int __init init(void)
342 init_max_malloc_size();
343 return ip_set_register_set_type(&ip_set_macipmap);
346 static void __exit fini(void)
348 /* FIXME: possible race with ip_set_create() */
349 ip_set_unregister_set_type(&ip_set_macipmap);