~ubuntu-branches/ubuntu/precise/xtables-addons/precise

« back to all changes in this revision

Viewing changes to extensions/ipset/ip_set.c

  • Committer: Bazaar Package Importer
  • Author(s): Pierre Chifflier
  • Date: 2008-10-27 22:31:20 UTC
  • Revision ID: james.westby@ubuntu.com-20081027223120-njqjsraqjpp7s98t
Tags: upstream-1.5.7
ImportĀ upstreamĀ versionĀ 1.5.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
 
2
 *                         Patrick Schaaf <bof@bof.de>
 
3
 * Copyright (C) 2003-2004 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License version 2 as
 
7
 * published by the Free Software Foundation.
 
8
 */
 
9
 
 
10
/* Kernel module for IP set management */
 
11
 
 
12
#include <linux/version.h>
 
13
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
 
14
#include <linux/config.h>
 
15
#endif
 
16
#include <linux/module.h>
 
17
#include <linux/moduleparam.h>
 
18
#include <linux/kmod.h>
 
19
#include <linux/ip.h>
 
20
#include <linux/skbuff.h>
 
21
#include <linux/random.h>
 
22
#include <linux/jhash.h>
 
23
#include <linux/netfilter_ipv4/ip_tables.h>
 
24
#include <linux/errno.h>
 
25
#include <asm/uaccess.h>
 
26
#include <asm/bitops.h>
 
27
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
 
28
#       include <linux/semaphore.h>
 
29
#else
 
30
#       include <asm/semaphore.h>
 
31
#endif
 
32
#include <linux/spinlock.h>
 
33
#include <linux/vmalloc.h>
 
34
 
 
35
#define ASSERT_READ_LOCK(x)
 
36
#define ASSERT_WRITE_LOCK(x)
 
37
#include "ip_set.h"
 
38
 
 
39
static struct list_head set_type_list;          /* all registered sets */
 
40
static struct ip_set **ip_set_list;             /* all individual sets */
 
41
static DEFINE_RWLOCK(ip_set_lock);              /* protects the lists and the hash */
 
42
static DECLARE_MUTEX(ip_set_app_mutex);         /* serializes user access */
 
43
static ip_set_id_t ip_set_max = CONFIG_IP_NF_SET_MAX;
 
44
static ip_set_id_t ip_set_bindings_hash_size =  CONFIG_IP_NF_SET_HASHSIZE;
 
45
static struct list_head *ip_set_hash;           /* hash of bindings */
 
46
static unsigned int ip_set_hash_random;         /* random seed */
 
47
 
 
48
#define SETNAME_EQ(a,b)         (strncmp(a,b,IP_SET_MAXNAMELEN) == 0)
 
49
 
 
50
/*
 
51
 * Sets are identified either by the index in ip_set_list or by id.
 
52
 * The id never changes and is used to find a key in the hash.
 
53
 * The index may change by swapping and used at all other places
 
54
 * (set/SET netfilter modules, binding value, etc.)
 
55
 *
 
56
 * Userspace requests are serialized by ip_set_mutex and sets can
 
57
 * be deleted only from userspace. Therefore ip_set_list locking
 
58
 * must obey the following rules:
 
59
 *
 
60
 * - kernel requests: read and write locking mandatory
 
61
 * - user requests: read locking optional, write locking mandatory
 
62
 */
 
63
 
 
64
static inline void
 
65
__ip_set_get(ip_set_id_t index)
 
66
{
 
67
        atomic_inc(&ip_set_list[index]->ref);
 
68
}
 
69
 
 
70
static inline void
 
71
__ip_set_put(ip_set_id_t index)
 
72
{
 
73
        atomic_dec(&ip_set_list[index]->ref);
 
74
}
 
75
 
 
76
/*
 
77
 * Binding routines
 
78
 */
 
79
 
 
80
static inline struct ip_set_hash *
 
81
__ip_set_find(u_int32_t key, ip_set_id_t id, ip_set_ip_t ip)
 
82
{
 
83
        struct ip_set_hash *set_hash;
 
84
 
 
85
        list_for_each_entry(set_hash, &ip_set_hash[key], list)
 
86
                if (set_hash->id == id && set_hash->ip == ip)
 
87
                        return set_hash;
 
88
                        
 
89
        return NULL;
 
90
}
 
91
 
 
92
static ip_set_id_t
 
93
ip_set_find_in_hash(ip_set_id_t id, ip_set_ip_t ip)
 
94
{
 
95
        u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)
 
96
                                % ip_set_bindings_hash_size;
 
97
        struct ip_set_hash *set_hash;
 
98
 
 
99
        ASSERT_READ_LOCK(&ip_set_lock);
 
100
        IP_SET_ASSERT(ip_set_list[id]);
 
101
        DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));     
 
102
        
 
103
        set_hash = __ip_set_find(key, id, ip);
 
104
        
 
105
        DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
 
106
           HIPQUAD(ip),
 
107
           set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
 
108
 
 
109
        return (set_hash != NULL ? set_hash->binding : IP_SET_INVALID_ID);
 
110
}
 
111
 
 
112
static inline void
 
113
__set_hash_del(struct ip_set_hash *set_hash)
 
114
{
 
115
        ASSERT_WRITE_LOCK(&ip_set_lock);
 
116
        IP_SET_ASSERT(ip_set_list[set_hash->binding]);  
 
117
 
 
118
        __ip_set_put(set_hash->binding);
 
119
        list_del(&set_hash->list);
 
120
        kfree(set_hash);
 
121
}
 
122
 
 
123
static int
 
124
ip_set_hash_del(ip_set_id_t id, ip_set_ip_t ip)
 
125
{
 
126
        u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)
 
127
                                % ip_set_bindings_hash_size;
 
128
        struct ip_set_hash *set_hash;
 
129
        
 
130
        IP_SET_ASSERT(ip_set_list[id]);
 
131
        DP("set: %s, ip: %u.%u.%u.%u", ip_set_list[id]->name, HIPQUAD(ip));     
 
132
        write_lock_bh(&ip_set_lock);
 
133
        set_hash = __ip_set_find(key, id, ip);
 
134
        DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
 
135
           HIPQUAD(ip),
 
136
           set_hash != NULL ? ip_set_list[set_hash->binding]->name : "");
 
137
 
 
138
        if (set_hash != NULL)
 
139
                __set_hash_del(set_hash);
 
140
        write_unlock_bh(&ip_set_lock);
 
141
        return 0;
 
142
}
 
143
 
 
144
static int
 
145
ip_set_hash_add(ip_set_id_t id, ip_set_ip_t ip, ip_set_id_t binding)
 
146
{
 
147
        u_int32_t key = jhash_2words(id, ip, ip_set_hash_random)
 
148
                                % ip_set_bindings_hash_size;
 
149
        struct ip_set_hash *set_hash;
 
150
        int ret = 0;
 
151
        
 
152
        IP_SET_ASSERT(ip_set_list[id]);
 
153
        IP_SET_ASSERT(ip_set_list[binding]);
 
154
        DP("set: %s, ip: %u.%u.%u.%u, binding: %s", ip_set_list[id]->name,
 
155
           HIPQUAD(ip), ip_set_list[binding]->name);
 
156
        write_lock_bh(&ip_set_lock);
 
157
        set_hash = __ip_set_find(key, id, ip);
 
158
        if (!set_hash) {
 
159
                set_hash = kmalloc(sizeof(struct ip_set_hash), GFP_ATOMIC);
 
160
                if (!set_hash) {
 
161
                        ret = -ENOMEM;
 
162
                        goto unlock;
 
163
                }
 
164
                INIT_LIST_HEAD(&set_hash->list);
 
165
                set_hash->id = id;
 
166
                set_hash->ip = ip;
 
167
                list_add(&set_hash->list, &ip_set_hash[key]);
 
168
        } else {
 
169
                IP_SET_ASSERT(ip_set_list[set_hash->binding]);  
 
170
                DP("overwrite binding: %s",
 
171
                   ip_set_list[set_hash->binding]->name);
 
172
                __ip_set_put(set_hash->binding);
 
173
        }
 
174
        set_hash->binding = binding;
 
175
        __ip_set_get(set_hash->binding);
 
176
        DP("stored: key %u, id %u (%s), ip %u.%u.%u.%u, binding %u (%s)",
 
177
           key, id, ip_set_list[id]->name,
 
178
           HIPQUAD(ip), binding, ip_set_list[binding]->name);
 
179
    unlock:
 
180
        write_unlock_bh(&ip_set_lock);
 
181
        return ret;
 
182
}
 
183
 
 
184
#define FOREACH_HASH_DO(fn, args...)                                            \
 
185
({                                                                              \
 
186
        ip_set_id_t __key;                                                      \
 
187
        struct ip_set_hash *__set_hash;                                         \
 
188
                                                                                \
 
189
        for (__key = 0; __key < ip_set_bindings_hash_size; __key++) {           \
 
190
                list_for_each_entry(__set_hash, &ip_set_hash[__key], list)      \
 
191
                        fn(__set_hash , ## args);                               \
 
192
        }                                                                       \
 
193
})
 
194
 
 
195
#define FOREACH_HASH_RW_DO(fn, args...)                                                 \
 
196
({                                                                              \
 
197
        ip_set_id_t __key;                                                      \
 
198
        struct ip_set_hash *__set_hash, *__n;                                   \
 
199
                                                                                \
 
200
        ASSERT_WRITE_LOCK(&ip_set_lock);                                        \
 
201
        for (__key = 0; __key < ip_set_bindings_hash_size; __key++) {           \
 
202
                list_for_each_entry_safe(__set_hash, __n, &ip_set_hash[__key], list)\
 
203
                        fn(__set_hash , ## args);                               \
 
204
        }                                                                       \
 
205
})
 
206
 
 
207
/* Add, del and test set entries from kernel */
 
208
 
 
209
#define follow_bindings(index, set, ip)                                 \
 
210
((index = ip_set_find_in_hash((set)->id, ip)) != IP_SET_INVALID_ID      \
 
211
 || (index = (set)->binding) != IP_SET_INVALID_ID)
 
212
 
 
213
int
 
214
ip_set_testip_kernel(ip_set_id_t index,
 
215
                     const struct sk_buff *skb,
 
216
                     const u_int32_t *flags)
 
217
{
 
218
        struct ip_set *set;
 
219
        ip_set_ip_t ip;
 
220
        int res;
 
221
        unsigned char i = 0;
 
222
        
 
223
        IP_SET_ASSERT(flags[i]);
 
224
        read_lock_bh(&ip_set_lock);
 
225
        do {
 
226
                set = ip_set_list[index];
 
227
                IP_SET_ASSERT(set);
 
228
                DP("set %s, index %u", set->name, index);
 
229
                read_lock_bh(&set->lock);
 
230
                res = set->type->testip_kernel(set, skb, &ip, flags, i++);
 
231
                read_unlock_bh(&set->lock);
 
232
                i += !!(set->type->features & IPSET_DATA_DOUBLE);
 
233
        } while (res > 0
 
234
                 && flags[i]
 
235
                 && follow_bindings(index, set, ip));
 
236
        read_unlock_bh(&ip_set_lock);
 
237
 
 
238
        return res;
 
239
}
 
240
 
 
241
void
 
242
ip_set_addip_kernel(ip_set_id_t index,
 
243
                    const struct sk_buff *skb,
 
244
                    const u_int32_t *flags)
 
245
{
 
246
        struct ip_set *set;
 
247
        ip_set_ip_t ip;
 
248
        int res;
 
249
        unsigned char i = 0;
 
250
 
 
251
        IP_SET_ASSERT(flags[i]);
 
252
   retry:
 
253
        read_lock_bh(&ip_set_lock);
 
254
        do {
 
255
                set = ip_set_list[index];
 
256
                IP_SET_ASSERT(set);
 
257
                DP("set %s, index %u", set->name, index);
 
258
                write_lock_bh(&set->lock);
 
259
                res = set->type->addip_kernel(set, skb, &ip, flags, i++);
 
260
                write_unlock_bh(&set->lock);
 
261
                i += !!(set->type->features & IPSET_DATA_DOUBLE);
 
262
        } while ((res == 0 || res == -EEXIST)
 
263
                 && flags[i]
 
264
                 && follow_bindings(index, set, ip));
 
265
        read_unlock_bh(&ip_set_lock);
 
266
 
 
267
        if (res == -EAGAIN
 
268
            && set->type->retry
 
269
            && (res = set->type->retry(set)) == 0)
 
270
                goto retry;
 
271
}
 
272
 
 
273
void
 
274
ip_set_delip_kernel(ip_set_id_t index,
 
275
                    const struct sk_buff *skb,
 
276
                    const u_int32_t *flags)
 
277
{
 
278
        struct ip_set *set;
 
279
        ip_set_ip_t ip;
 
280
        int res;
 
281
        unsigned char i = 0;
 
282
 
 
283
        IP_SET_ASSERT(flags[i]);
 
284
        read_lock_bh(&ip_set_lock);
 
285
        do {
 
286
                set = ip_set_list[index];
 
287
                IP_SET_ASSERT(set);
 
288
                DP("set %s, index %u", set->name, index);
 
289
                write_lock_bh(&set->lock);
 
290
                res = set->type->delip_kernel(set, skb, &ip, flags, i++);
 
291
                write_unlock_bh(&set->lock);
 
292
                i += !!(set->type->features & IPSET_DATA_DOUBLE);
 
293
        } while ((res == 0 || res == -EEXIST)
 
294
                 && flags[i]
 
295
                 && follow_bindings(index, set, ip));
 
296
        read_unlock_bh(&ip_set_lock);
 
297
}
 
298
 
 
299
/* Register and deregister settype */
 
300
 
 
301
static inline struct ip_set_type *
 
302
find_set_type(const char *name)
 
303
{
 
304
        struct ip_set_type *set_type;
 
305
 
 
306
        list_for_each_entry(set_type, &set_type_list, list)
 
307
                if (!strncmp(set_type->typename, name, IP_SET_MAXNAMELEN - 1))
 
308
                        return set_type;
 
309
        return NULL;
 
310
}
 
311
 
 
312
int
 
313
ip_set_register_set_type(struct ip_set_type *set_type)
 
314
{
 
315
        int ret = 0;
 
316
        
 
317
        if (set_type->protocol_version != IP_SET_PROTOCOL_VERSION) {
 
318
                ip_set_printk("'%s' uses wrong protocol version %u (want %u)",
 
319
                              set_type->typename,
 
320
                              set_type->protocol_version,
 
321
                              IP_SET_PROTOCOL_VERSION);
 
322
                return -EINVAL;
 
323
        }
 
324
 
 
325
        write_lock_bh(&ip_set_lock);
 
326
        if (find_set_type(set_type->typename)) {
 
327
                /* Duplicate! */
 
328
                ip_set_printk("'%s' already registered!",
 
329
                              set_type->typename);
 
330
                ret = -EINVAL;
 
331
                goto unlock;
 
332
        }
 
333
        if (!try_module_get(THIS_MODULE)) {
 
334
                ret = -EFAULT;
 
335
                goto unlock;
 
336
        }
 
337
        list_add(&set_type->list, &set_type_list);
 
338
        DP("'%s' registered.", set_type->typename);
 
339
   unlock:
 
340
        write_unlock_bh(&ip_set_lock);
 
341
        return ret;
 
342
}
 
343
 
 
344
void
 
345
ip_set_unregister_set_type(struct ip_set_type *set_type)
 
346
{
 
347
        write_lock_bh(&ip_set_lock);
 
348
        if (!find_set_type(set_type->typename)) {
 
349
                ip_set_printk("'%s' not registered?",
 
350
                              set_type->typename);
 
351
                goto unlock;
 
352
        }
 
353
        list_del(&set_type->list);
 
354
        module_put(THIS_MODULE);
 
355
        DP("'%s' unregistered.", set_type->typename);
 
356
   unlock:
 
357
        write_unlock_bh(&ip_set_lock);
 
358
 
 
359
}
 
360
 
 
361
/*
 
362
 * Userspace routines
 
363
 */
 
364
 
 
365
/*
 
366
 * Find set by name, reference it once. The reference makes sure the
 
367
 * thing pointed to, does not go away under our feet. Drop the reference
 
368
 * later, using ip_set_put().
 
369
 */
 
370
ip_set_id_t
 
371
ip_set_get_byname(const char *name)
 
372
{
 
373
        ip_set_id_t i, index = IP_SET_INVALID_ID;
 
374
        
 
375
        down(&ip_set_app_mutex);
 
376
        for (i = 0; i < ip_set_max; i++) {
 
377
                if (ip_set_list[i] != NULL
 
378
                    && SETNAME_EQ(ip_set_list[i]->name, name)) {
 
379
                        __ip_set_get(i);
 
380
                        index = i;
 
381
                        break;
 
382
                }
 
383
        }
 
384
        up(&ip_set_app_mutex);
 
385
        return index;
 
386
}
 
387
 
 
388
/*
 
389
 * Find set by index, reference it once. The reference makes sure the
 
390
 * thing pointed to, does not go away under our feet. Drop the reference
 
391
 * later, using ip_set_put().
 
392
 */
 
393
ip_set_id_t
 
394
ip_set_get_byindex(ip_set_id_t index)
 
395
{
 
396
        down(&ip_set_app_mutex);
 
397
 
 
398
        if (index >= ip_set_max)
 
399
                return IP_SET_INVALID_ID;
 
400
        
 
401
        if (ip_set_list[index])
 
402
                __ip_set_get(index);
 
403
        else
 
404
                index = IP_SET_INVALID_ID;
 
405
                
 
406
        up(&ip_set_app_mutex);
 
407
        return index;
 
408
}
 
409
 
 
410
/*
 
411
 * If the given set pointer points to a valid set, decrement
 
412
 * reference count by 1. The caller shall not assume the index
 
413
 * to be valid, after calling this function.
 
414
 */
 
415
void ip_set_put(ip_set_id_t index)
 
416
{
 
417
        down(&ip_set_app_mutex);
 
418
        if (ip_set_list[index])
 
419
                __ip_set_put(index);
 
420
        up(&ip_set_app_mutex);
 
421
}
 
422
 
 
423
/* Find a set by name or index */
 
424
static ip_set_id_t
 
425
ip_set_find_byname(const char *name)
 
426
{
 
427
        ip_set_id_t i, index = IP_SET_INVALID_ID;
 
428
        
 
429
        for (i = 0; i < ip_set_max; i++) {
 
430
                if (ip_set_list[i] != NULL
 
431
                    && SETNAME_EQ(ip_set_list[i]->name, name)) {
 
432
                        index = i;
 
433
                        break;
 
434
                }
 
435
        }
 
436
        return index;
 
437
}
 
438
 
 
439
static ip_set_id_t
 
440
ip_set_find_byindex(ip_set_id_t index)
 
441
{
 
442
        if (index >= ip_set_max || ip_set_list[index] == NULL)
 
443
                index = IP_SET_INVALID_ID;
 
444
        
 
445
        return index;
 
446
}
 
447
 
 
448
/*
 
449
 * Add, del, test, bind and unbind
 
450
 */
 
451
 
 
452
static inline int
 
453
__ip_set_testip(struct ip_set *set,
 
454
                const void *data,
 
455
                size_t size,
 
456
                ip_set_ip_t *ip)
 
457
{
 
458
        int res;
 
459
 
 
460
        read_lock_bh(&set->lock);
 
461
        res = set->type->testip(set, data, size, ip);
 
462
        read_unlock_bh(&set->lock);
 
463
 
 
464
        return res;
 
465
}
 
466
 
 
467
static int
 
468
__ip_set_addip(ip_set_id_t index,
 
469
               const void *data,
 
470
               size_t size)
 
471
{
 
472
        struct ip_set *set = ip_set_list[index];
 
473
        ip_set_ip_t ip;
 
474
        int res;
 
475
        
 
476
        IP_SET_ASSERT(set);
 
477
        do {
 
478
                write_lock_bh(&set->lock);
 
479
                res = set->type->addip(set, data, size, &ip);
 
480
                write_unlock_bh(&set->lock);
 
481
        } while (res == -EAGAIN
 
482
                 && set->type->retry
 
483
                 && (res = set->type->retry(set)) == 0);
 
484
 
 
485
        return res;
 
486
}
 
487
 
 
488
static int
 
489
ip_set_addip(ip_set_id_t index,
 
490
             const void *data,
 
491
             size_t size)
 
492
{
 
493
 
 
494
        return __ip_set_addip(index,
 
495
                              data + sizeof(struct ip_set_req_adt),
 
496
                              size - sizeof(struct ip_set_req_adt));
 
497
}
 
498
 
 
499
static int
 
500
ip_set_delip(ip_set_id_t index,
 
501
             const void *data,
 
502
             size_t size)
 
503
{
 
504
        struct ip_set *set = ip_set_list[index];
 
505
        ip_set_ip_t ip;
 
506
        int res;
 
507
        
 
508
        IP_SET_ASSERT(set);
 
509
        write_lock_bh(&set->lock);
 
510
        res = set->type->delip(set,
 
511
                               data + sizeof(struct ip_set_req_adt),
 
512
                               size - sizeof(struct ip_set_req_adt),
 
513
                               &ip);
 
514
        write_unlock_bh(&set->lock);
 
515
 
 
516
        return res;
 
517
}
 
518
 
 
519
static int
 
520
ip_set_testip(ip_set_id_t index,
 
521
              const void *data,
 
522
              size_t size)
 
523
{
 
524
        struct ip_set *set = ip_set_list[index];
 
525
        ip_set_ip_t ip;
 
526
        int res;
 
527
 
 
528
        IP_SET_ASSERT(set);
 
529
        res = __ip_set_testip(set,
 
530
                              data + sizeof(struct ip_set_req_adt),
 
531
                              size - sizeof(struct ip_set_req_adt),
 
532
                              &ip);
 
533
 
 
534
        return (res > 0 ? -EEXIST : res);
 
535
}
 
536
 
 
537
static int
 
538
ip_set_bindip(ip_set_id_t index,
 
539
              const void *data,
 
540
              size_t size)
 
541
{
 
542
        struct ip_set *set = ip_set_list[index];
 
543
        const struct ip_set_req_bind *req_bind;
 
544
        ip_set_id_t binding;
 
545
        ip_set_ip_t ip;
 
546
        int res;
 
547
 
 
548
        IP_SET_ASSERT(set);
 
549
        if (size < sizeof(struct ip_set_req_bind))
 
550
                return -EINVAL;
 
551
                
 
552
        req_bind = data;
 
553
 
 
554
        if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_DEFAULT)) {
 
555
                /* Default binding of a set */
 
556
                const char *binding_name;
 
557
                
 
558
                if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN)
 
559
                        return -EINVAL;
 
560
 
 
561
                binding_name = data + sizeof(struct ip_set_req_bind);
 
562
 
 
563
                binding = ip_set_find_byname(binding_name);
 
564
                if (binding == IP_SET_INVALID_ID)
 
565
                        return -ENOENT;
 
566
 
 
567
                write_lock_bh(&ip_set_lock);
 
568
                /* Sets as binding values are referenced */
 
569
                if (set->binding != IP_SET_INVALID_ID)
 
570
                        __ip_set_put(set->binding);
 
571
                set->binding = binding;
 
572
                __ip_set_get(set->binding);
 
573
                write_unlock_bh(&ip_set_lock);
 
574
 
 
575
                return 0;
 
576
        }
 
577
        binding = ip_set_find_byname(req_bind->binding);
 
578
        if (binding == IP_SET_INVALID_ID)
 
579
                return -ENOENT;
 
580
 
 
581
        res = __ip_set_testip(set,
 
582
                              data + sizeof(struct ip_set_req_bind),
 
583
                              size - sizeof(struct ip_set_req_bind),
 
584
                              &ip);
 
585
        DP("set %s, ip: %u.%u.%u.%u, binding %s",
 
586
           set->name, HIPQUAD(ip), ip_set_list[binding]->name);
 
587
        
 
588
        if (res >= 0)
 
589
                res = ip_set_hash_add(set->id, ip, binding);
 
590
 
 
591
        return res;
 
592
}
 
593
 
 
594
#define FOREACH_SET_DO(fn, args...)                             \
 
595
({                                                              \
 
596
        ip_set_id_t __i;                                        \
 
597
        struct ip_set *__set;                                   \
 
598
                                                                \
 
599
        for (__i = 0; __i < ip_set_max; __i++) {                \
 
600
                __set = ip_set_list[__i];                       \
 
601
                if (__set != NULL)                              \
 
602
                        fn(__set , ##args);                     \
 
603
        }                                                       \
 
604
})
 
605
 
 
606
static inline void
 
607
__set_hash_del_byid(struct ip_set_hash *set_hash, ip_set_id_t id)
 
608
{
 
609
        if (set_hash->id == id)
 
610
                __set_hash_del(set_hash);
 
611
}
 
612
 
 
613
static inline void
 
614
__unbind_default(struct ip_set *set)
 
615
{
 
616
        if (set->binding != IP_SET_INVALID_ID) {
 
617
                /* Sets as binding values are referenced */
 
618
                __ip_set_put(set->binding);
 
619
                set->binding = IP_SET_INVALID_ID;
 
620
        }
 
621
}
 
622
 
 
623
static int
 
624
ip_set_unbindip(ip_set_id_t index,
 
625
                const void *data,
 
626
                size_t size)
 
627
{
 
628
        struct ip_set *set;
 
629
        const struct ip_set_req_bind *req_bind;
 
630
        ip_set_ip_t ip;
 
631
        int res;
 
632
 
 
633
        DP("");
 
634
        if (size < sizeof(struct ip_set_req_bind))
 
635
                return -EINVAL;
 
636
                
 
637
        req_bind = data;
 
638
        
 
639
        DP("%u %s", index, req_bind->binding);
 
640
        if (index == IP_SET_INVALID_ID) {
 
641
                /* unbind :all: */
 
642
                if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_DEFAULT)) {
 
643
                        /* Default binding of sets */
 
644
                        write_lock_bh(&ip_set_lock);
 
645
                        FOREACH_SET_DO(__unbind_default);
 
646
                        write_unlock_bh(&ip_set_lock);
 
647
                        return 0;
 
648
                } else if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_ALL)) {
 
649
                        /* Flush all bindings of all sets*/
 
650
                        write_lock_bh(&ip_set_lock);
 
651
                        FOREACH_HASH_RW_DO(__set_hash_del);
 
652
                        write_unlock_bh(&ip_set_lock);
 
653
                        return 0;
 
654
                }
 
655
                DP("unreachable reached!");
 
656
                return -EINVAL;
 
657
        }
 
658
        
 
659
        set = ip_set_list[index];
 
660
        IP_SET_ASSERT(set);
 
661
        if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_DEFAULT)) {
 
662
                /* Default binding of set */
 
663
                ip_set_id_t binding = ip_set_find_byindex(set->binding);
 
664
 
 
665
                if (binding == IP_SET_INVALID_ID)
 
666
                        return -ENOENT;
 
667
                        
 
668
                write_lock_bh(&ip_set_lock);
 
669
                /* Sets in hash values are referenced */
 
670
                __ip_set_put(set->binding);
 
671
                set->binding = IP_SET_INVALID_ID;
 
672
                write_unlock_bh(&ip_set_lock);
 
673
 
 
674
                return 0;
 
675
        } else if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_ALL)) {
 
676
                /* Flush all bindings */
 
677
 
 
678
                write_lock_bh(&ip_set_lock);
 
679
                FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
 
680
                write_unlock_bh(&ip_set_lock);
 
681
                return 0;
 
682
        }
 
683
        
 
684
        res = __ip_set_testip(set,
 
685
                              data + sizeof(struct ip_set_req_bind),
 
686
                              size - sizeof(struct ip_set_req_bind),
 
687
                              &ip);
 
688
 
 
689
        DP("set %s, ip: %u.%u.%u.%u", set->name, HIPQUAD(ip));
 
690
        if (res >= 0)
 
691
                res = ip_set_hash_del(set->id, ip);
 
692
 
 
693
        return res;
 
694
}
 
695
 
 
696
static int
 
697
ip_set_testbind(ip_set_id_t index,
 
698
                const void *data,
 
699
                size_t size)
 
700
{
 
701
        struct ip_set *set = ip_set_list[index];
 
702
        const struct ip_set_req_bind *req_bind;
 
703
        ip_set_id_t binding;
 
704
        ip_set_ip_t ip;
 
705
        int res;
 
706
 
 
707
        IP_SET_ASSERT(set);
 
708
        if (size < sizeof(struct ip_set_req_bind))
 
709
                return -EINVAL;
 
710
                
 
711
        req_bind = data;
 
712
 
 
713
        if (SETNAME_EQ(req_bind->binding, IPSET_TOKEN_DEFAULT)) {
 
714
                /* Default binding of set */
 
715
                const char *binding_name;
 
716
                
 
717
                if (size != sizeof(struct ip_set_req_bind) + IP_SET_MAXNAMELEN)
 
718
                        return -EINVAL;
 
719
 
 
720
                binding_name = data + sizeof(struct ip_set_req_bind);
 
721
 
 
722
                binding = ip_set_find_byname(binding_name);
 
723
                if (binding == IP_SET_INVALID_ID)
 
724
                        return -ENOENT;
 
725
                
 
726
                res = (set->binding == binding) ? -EEXIST : 0;
 
727
 
 
728
                return res;
 
729
        }
 
730
        binding = ip_set_find_byname(req_bind->binding);
 
731
        if (binding == IP_SET_INVALID_ID)
 
732
                return -ENOENT;
 
733
                
 
734
        
 
735
        res = __ip_set_testip(set,
 
736
                              data + sizeof(struct ip_set_req_bind),
 
737
                              size - sizeof(struct ip_set_req_bind),
 
738
                              &ip);
 
739
        DP("set %s, ip: %u.%u.%u.%u, binding %s",
 
740
           set->name, HIPQUAD(ip), ip_set_list[binding]->name);
 
741
        
 
742
        if (res >= 0)
 
743
                res = (ip_set_find_in_hash(set->id, ip) == binding)
 
744
                        ? -EEXIST : 0;
 
745
 
 
746
        return res;
 
747
}
 
748
 
 
749
static struct ip_set_type *
 
750
find_set_type_rlock(const char *typename)
 
751
{
 
752
        struct ip_set_type *type;
 
753
        
 
754
        read_lock_bh(&ip_set_lock);
 
755
        type = find_set_type(typename);
 
756
        if (type == NULL)
 
757
                read_unlock_bh(&ip_set_lock);
 
758
 
 
759
        return type;
 
760
}
 
761
 
 
762
static int
 
763
find_free_id(const char *name,
 
764
             ip_set_id_t *index,
 
765
             ip_set_id_t *id)
 
766
{
 
767
        ip_set_id_t i;
 
768
 
 
769
        *id = IP_SET_INVALID_ID;
 
770
        for (i = 0;  i < ip_set_max; i++) {
 
771
                if (ip_set_list[i] == NULL) {
 
772
                        if (*id == IP_SET_INVALID_ID)
 
773
                                *id = *index = i;
 
774
                } else if (SETNAME_EQ(name, ip_set_list[i]->name))
 
775
                        /* Name clash */
 
776
                        return -EEXIST;
 
777
        }
 
778
        if (*id == IP_SET_INVALID_ID)
 
779
                /* No free slot remained */
 
780
                return -ERANGE;
 
781
        /* Check that index is usable as id (swapping) */
 
782
    check:      
 
783
        for (i = 0;  i < ip_set_max; i++) {
 
784
                if (ip_set_list[i] != NULL
 
785
                    && ip_set_list[i]->id == *id) {
 
786
                    *id = i;
 
787
                    goto check;
 
788
                }
 
789
        }
 
790
        return 0;
 
791
}
 
792
 
 
793
/*
 
794
 * Create a set
 
795
 */
 
796
static int
 
797
ip_set_create(const char *name,
 
798
              const char *typename,
 
799
              ip_set_id_t restore,
 
800
              const void *data,
 
801
              size_t size)
 
802
{
 
803
        struct ip_set *set;
 
804
        ip_set_id_t index = 0, id;
 
805
        int res = 0;
 
806
 
 
807
        DP("setname: %s, typename: %s, id: %u", name, typename, restore);
 
808
        /*
 
809
         * First, and without any locks, allocate and initialize
 
810
         * a normal base set structure.
 
811
         */
 
812
        set = kmalloc(sizeof(struct ip_set), GFP_KERNEL);
 
813
        if (!set)
 
814
                return -ENOMEM;
 
815
        set->lock = RW_LOCK_UNLOCKED;
 
816
        strncpy(set->name, name, IP_SET_MAXNAMELEN);
 
817
        set->binding = IP_SET_INVALID_ID;
 
818
        atomic_set(&set->ref, 0);
 
819
 
 
820
        /*
 
821
         * Next, take the &ip_set_lock, check that we know the type,
 
822
         * and take a reference on the type, to make sure it
 
823
         * stays available while constructing our new set.
 
824
         *
 
825
         * After referencing the type, we drop the &ip_set_lock,
 
826
         * and let the new set construction run without locks.
 
827
         */
 
828
        set->type = find_set_type_rlock(typename);
 
829
        if (set->type == NULL) {
 
830
                /* Try loading the module */
 
831
                char modulename[IP_SET_MAXNAMELEN + strlen("ip_set_") + 1];
 
832
                strcpy(modulename, "ip_set_");
 
833
                strcat(modulename, typename);
 
834
                DP("try to load %s", modulename);
 
835
                request_module(modulename);
 
836
                set->type = find_set_type_rlock(typename);
 
837
        }
 
838
        if (set->type == NULL) {
 
839
                ip_set_printk("no set type '%s', set '%s' not created",
 
840
                              typename, name);
 
841
                res = -ENOENT;
 
842
                goto out;
 
843
        }
 
844
        if (!try_module_get(set->type->me)) {
 
845
                read_unlock_bh(&ip_set_lock);
 
846
                res = -EFAULT;
 
847
                goto out;
 
848
        }
 
849
        read_unlock_bh(&ip_set_lock);
 
850
 
 
851
        /*
 
852
         * Without holding any locks, create private part.
 
853
         */
 
854
        res = set->type->create(set, data, size);
 
855
        if (res != 0)
 
856
                goto put_out;
 
857
 
 
858
        /* BTW, res==0 here. */
 
859
 
 
860
        /*
 
861
         * Here, we have a valid, constructed set. &ip_set_lock again,
 
862
         * find free id/index and check that it is not already in
 
863
         * ip_set_list.
 
864
         */
 
865
        write_lock_bh(&ip_set_lock);
 
866
        if ((res = find_free_id(set->name, &index, &id)) != 0) {
 
867
                DP("no free id!");
 
868
                goto cleanup;
 
869
        }
 
870
 
 
871
        /* Make sure restore gets the same index */
 
872
        if (restore != IP_SET_INVALID_ID && index != restore) {
 
873
                DP("Can't restore, sets are screwed up");
 
874
                res = -ERANGE;
 
875
                goto cleanup;
 
876
        }
 
877
        
 
878
        /*
 
879
         * Finally! Add our shiny new set to the list, and be done.
 
880
         */
 
881
        DP("create: '%s' created with index %u, id %u!", set->name, index, id);
 
882
        set->id = id;
 
883
        ip_set_list[index] = set;
 
884
        write_unlock_bh(&ip_set_lock);
 
885
        return res;
 
886
        
 
887
    cleanup:
 
888
        write_unlock_bh(&ip_set_lock);
 
889
        set->type->destroy(set);
 
890
    put_out:
 
891
        module_put(set->type->me);
 
892
    out:
 
893
        kfree(set);
 
894
        return res;
 
895
}
 
896
 
 
897
/*
 
898
 * Destroy a given existing set
 
899
 */
 
900
static void
 
901
ip_set_destroy_set(ip_set_id_t index)
 
902
{
 
903
        struct ip_set *set = ip_set_list[index];
 
904
 
 
905
        IP_SET_ASSERT(set);
 
906
        DP("set: %s",  set->name);
 
907
        write_lock_bh(&ip_set_lock);
 
908
        FOREACH_HASH_RW_DO(__set_hash_del_byid, set->id);
 
909
        if (set->binding != IP_SET_INVALID_ID)
 
910
                __ip_set_put(set->binding);
 
911
        ip_set_list[index] = NULL;
 
912
        write_unlock_bh(&ip_set_lock);
 
913
 
 
914
        /* Must call it without holding any lock */
 
915
        set->type->destroy(set);
 
916
        module_put(set->type->me);
 
917
        kfree(set);
 
918
}
 
919
 
 
920
/*
 
921
 * Destroy a set - or all sets
 
922
 * Sets must not be referenced/used.
 
923
 */
 
924
static int
 
925
ip_set_destroy(ip_set_id_t index)
 
926
{
 
927
        ip_set_id_t i;
 
928
 
 
929
        /* ref modification always protected by the mutex */
 
930
        if (index != IP_SET_INVALID_ID) {
 
931
                if (atomic_read(&ip_set_list[index]->ref))
 
932
                        return -EBUSY;
 
933
                ip_set_destroy_set(index);
 
934
        } else {
 
935
                for (i = 0; i < ip_set_max; i++) {
 
936
                        if (ip_set_list[i] != NULL
 
937
                            && (atomic_read(&ip_set_list[i]->ref)))
 
938
                                return -EBUSY;
 
939
                }
 
940
 
 
941
                for (i = 0; i < ip_set_max; i++) {
 
942
                        if (ip_set_list[i] != NULL)
 
943
                                ip_set_destroy_set(i);
 
944
                }
 
945
        }
 
946
        return 0;
 
947
}
 
948
 
 
949
static void
 
950
ip_set_flush_set(struct ip_set *set)
 
951
{
 
952
        DP("set: %s %u",  set->name, set->id);
 
953
 
 
954
        write_lock_bh(&set->lock);
 
955
        set->type->flush(set);
 
956
        write_unlock_bh(&set->lock);
 
957
}
 
958
 
 
959
/*
 
960
 * Flush data in a set - or in all sets
 
961
 */
 
962
static int
 
963
ip_set_flush(ip_set_id_t index)
 
964
{
 
965
        if (index != IP_SET_INVALID_ID) {
 
966
                IP_SET_ASSERT(ip_set_list[index]);
 
967
                ip_set_flush_set(ip_set_list[index]);
 
968
        } else
 
969
                FOREACH_SET_DO(ip_set_flush_set);
 
970
 
 
971
        return 0;
 
972
}
 
973
 
 
974
/* Rename a set */
 
975
static int
 
976
ip_set_rename(ip_set_id_t index, const char *name)
 
977
{
 
978
        struct ip_set *set = ip_set_list[index];
 
979
        ip_set_id_t i;
 
980
        int res = 0;
 
981
 
 
982
        DP("set: %s to %s",  set->name, name);
 
983
        write_lock_bh(&ip_set_lock);
 
984
        for (i = 0; i < ip_set_max; i++) {
 
985
                if (ip_set_list[i] != NULL
 
986
                    && SETNAME_EQ(ip_set_list[i]->name, name)) {
 
987
                        res = -EEXIST;
 
988
                        goto unlock;
 
989
                }
 
990
        }
 
991
        strncpy(set->name, name, IP_SET_MAXNAMELEN);
 
992
    unlock:
 
993
        write_unlock_bh(&ip_set_lock);
 
994
        return res;
 
995
}
 
996
 
 
997
/*
 
998
 * Swap two sets so that name/index points to the other.
 
999
 * References are also swapped.
 
1000
 */
 
1001
static int
 
1002
ip_set_swap(ip_set_id_t from_index, ip_set_id_t to_index)
 
1003
{
 
1004
        struct ip_set *from = ip_set_list[from_index];
 
1005
        struct ip_set *to = ip_set_list[to_index];
 
1006
        char from_name[IP_SET_MAXNAMELEN];
 
1007
        u_int32_t from_ref;
 
1008
 
 
1009
        DP("set: %s to %s",  from->name, to->name);
 
1010
        /* Features must not change. Artifical restriction. */
 
1011
        if (from->type->features != to->type->features)
 
1012
                return -ENOEXEC;
 
1013
 
 
1014
        /* No magic here: ref munging protected by the mutex */ 
 
1015
        write_lock_bh(&ip_set_lock);
 
1016
        strncpy(from_name, from->name, IP_SET_MAXNAMELEN);
 
1017
        from_ref = atomic_read(&from->ref);
 
1018
 
 
1019
        strncpy(from->name, to->name, IP_SET_MAXNAMELEN);
 
1020
        atomic_set(&from->ref, atomic_read(&to->ref));
 
1021
        strncpy(to->name, from_name, IP_SET_MAXNAMELEN);
 
1022
        atomic_set(&to->ref, from_ref);
 
1023
        
 
1024
        ip_set_list[from_index] = to;
 
1025
        ip_set_list[to_index] = from;
 
1026
        
 
1027
        write_unlock_bh(&ip_set_lock);
 
1028
        return 0;
 
1029
}
 
1030
 
 
1031
/*
 
1032
 * List set data
 
1033
 */
 
1034
 
 
1035
static inline void
 
1036
__set_hash_bindings_size_list(struct ip_set_hash *set_hash,
 
1037
                              ip_set_id_t id, size_t *size)
 
1038
{
 
1039
        if (set_hash->id == id)
 
1040
                *size += sizeof(struct ip_set_hash_list);
 
1041
}
 
1042
 
 
1043
static inline void
 
1044
__set_hash_bindings_size_save(struct ip_set_hash *set_hash,
 
1045
                              ip_set_id_t id, size_t *size)
 
1046
{
 
1047
        if (set_hash->id == id)
 
1048
                *size += sizeof(struct ip_set_hash_save);
 
1049
}
 
1050
 
 
1051
static inline void
 
1052
__set_hash_bindings(struct ip_set_hash *set_hash,
 
1053
                    ip_set_id_t id, void *data, int *used)
 
1054
{
 
1055
        if (set_hash->id == id) {
 
1056
                struct ip_set_hash_list *hash_list = data + *used;
 
1057
 
 
1058
                hash_list->ip = set_hash->ip;
 
1059
                hash_list->binding = set_hash->binding;
 
1060
                *used += sizeof(struct ip_set_hash_list);
 
1061
        }
 
1062
}
 
1063
 
 
1064
static int ip_set_list_set(ip_set_id_t index,
 
1065
                           void *data,
 
1066
                           int *used,
 
1067
                           int len)
 
1068
{
 
1069
        struct ip_set *set = ip_set_list[index];
 
1070
        struct ip_set_list *set_list;
 
1071
 
 
1072
        /* Pointer to our header */
 
1073
        set_list = data + *used;
 
1074
 
 
1075
        DP("set: %s, used: %d %p %p", set->name, *used, data, data + *used);
 
1076
 
 
1077
        /* Get and ensure header size */
 
1078
        if (*used + sizeof(struct ip_set_list) > len)
 
1079
                goto not_enough_mem;
 
1080
        *used += sizeof(struct ip_set_list);
 
1081
 
 
1082
        read_lock_bh(&set->lock);
 
1083
        /* Get and ensure set specific header size */
 
1084
        set_list->header_size = set->type->header_size;
 
1085
        if (*used + set_list->header_size > len)
 
1086
                goto unlock_set;
 
1087
 
 
1088
        /* Fill in the header */
 
1089
        set_list->index = index;
 
1090
        set_list->binding = set->binding;
 
1091
        set_list->ref = atomic_read(&set->ref);
 
1092
 
 
1093
        /* Fill in set spefific header data */
 
1094
        set->type->list_header(set, data + *used);
 
1095
        *used += set_list->header_size;
 
1096
 
 
1097
        /* Get and ensure set specific members size */
 
1098
        set_list->members_size = set->type->list_members_size(set);
 
1099
        if (*used + set_list->members_size > len)
 
1100
                goto unlock_set;
 
1101
 
 
1102
        /* Fill in set spefific members data */
 
1103
        set->type->list_members(set, data + *used);
 
1104
        *used += set_list->members_size;
 
1105
        read_unlock_bh(&set->lock);
 
1106
 
 
1107
        /* Bindings */
 
1108
 
 
1109
        /* Get and ensure set specific bindings size */
 
1110
        set_list->bindings_size = 0;
 
1111
        FOREACH_HASH_DO(__set_hash_bindings_size_list,
 
1112
                        set->id, &set_list->bindings_size);
 
1113
        if (*used + set_list->bindings_size > len)
 
1114
                goto not_enough_mem;
 
1115
 
 
1116
        /* Fill in set spefific bindings data */
 
1117
        FOREACH_HASH_DO(__set_hash_bindings, set->id, data, used);
 
1118
        
 
1119
        return 0;
 
1120
 
 
1121
    unlock_set:
 
1122
        read_unlock_bh(&set->lock);
 
1123
    not_enough_mem:
 
1124
        DP("not enough mem, try again");
 
1125
        return -EAGAIN;
 
1126
}
 
1127
 
 
1128
/*
 
1129
 * Save sets
 
1130
 */
 
1131
static int ip_set_save_set(ip_set_id_t index,
 
1132
                           void *data,
 
1133
                           int *used,
 
1134
                           int len)
 
1135
{
 
1136
        struct ip_set *set;
 
1137
        struct ip_set_save *set_save;
 
1138
 
 
1139
        /* Pointer to our header */
 
1140
        set_save = data + *used;
 
1141
 
 
1142
        /* Get and ensure header size */
 
1143
        if (*used + sizeof(struct ip_set_save) > len)
 
1144
                goto not_enough_mem;
 
1145
        *used += sizeof(struct ip_set_save);
 
1146
 
 
1147
        set = ip_set_list[index];
 
1148
        DP("set: %s, used: %u(%u) %p %p", set->name, *used, len,
 
1149
           data, data + *used);
 
1150
 
 
1151
        read_lock_bh(&set->lock);
 
1152
        /* Get and ensure set specific header size */
 
1153
        set_save->header_size = set->type->header_size;
 
1154
        if (*used + set_save->header_size > len)
 
1155
                goto unlock_set;
 
1156
 
 
1157
        /* Fill in the header */
 
1158
        set_save->index = index;
 
1159
        set_save->binding = set->binding;
 
1160
 
 
1161
        /* Fill in set spefific header data */
 
1162
        set->type->list_header(set, data + *used);
 
1163
        *used += set_save->header_size;
 
1164
 
 
1165
        DP("set header filled: %s, used: %u(%u) %p %p", set->name, *used,
 
1166
           set_save->header_size, data, data + *used);
 
1167
        /* Get and ensure set specific members size */
 
1168
        set_save->members_size = set->type->list_members_size(set);
 
1169
        if (*used + set_save->members_size > len)
 
1170
                goto unlock_set;
 
1171
 
 
1172
        /* Fill in set spefific members data */
 
1173
        set->type->list_members(set, data + *used);
 
1174
        *used += set_save->members_size;
 
1175
        read_unlock_bh(&set->lock);
 
1176
        DP("set members filled: %s, used: %u(%u) %p %p", set->name, *used,
 
1177
           set_save->members_size, data, data + *used);
 
1178
        return 0;
 
1179
 
 
1180
    unlock_set:
 
1181
        read_unlock_bh(&set->lock);
 
1182
    not_enough_mem:
 
1183
        DP("not enough mem, try again");
 
1184
        return -EAGAIN;
 
1185
}
 
1186
 
 
1187
static inline void
 
1188
__set_hash_save_bindings(struct ip_set_hash *set_hash,
 
1189
                         ip_set_id_t id,
 
1190
                         void *data,
 
1191
                         int *used,
 
1192
                         int len,
 
1193
                         int *res)
 
1194
{
 
1195
        if (*res == 0
 
1196
            && (id == IP_SET_INVALID_ID || set_hash->id == id)) {
 
1197
                struct ip_set_hash_save *hash_save = data + *used;
 
1198
                /* Ensure bindings size */
 
1199
                if (*used + sizeof(struct ip_set_hash_save) > len) {
 
1200
                        *res = -ENOMEM;
 
1201
                        return;
 
1202
                }
 
1203
                hash_save->id = set_hash->id;
 
1204
                hash_save->ip = set_hash->ip;
 
1205
                hash_save->binding = set_hash->binding;
 
1206
                *used += sizeof(struct ip_set_hash_save);
 
1207
        }
 
1208
}
 
1209
 
 
1210
static int ip_set_save_bindings(ip_set_id_t index,
 
1211
                                void *data,
 
1212
                                int *used,
 
1213
                                int len)
 
1214
{
 
1215
        int res = 0;
 
1216
        struct ip_set_save *set_save;
 
1217
 
 
1218
        DP("used %u, len %u", *used, len);
 
1219
        /* Get and ensure header size */
 
1220
        if (*used + sizeof(struct ip_set_save) > len)
 
1221
                return -ENOMEM;
 
1222
 
 
1223
        /* Marker */
 
1224
        set_save = data + *used;
 
1225
        set_save->index = IP_SET_INVALID_ID;
 
1226
        set_save->header_size = 0;
 
1227
        set_save->members_size = 0;
 
1228
        *used += sizeof(struct ip_set_save);
 
1229
 
 
1230
        DP("marker added used %u, len %u", *used, len);
 
1231
        /* Fill in bindings data */
 
1232
        if (index != IP_SET_INVALID_ID)
 
1233
                /* Sets are identified by id in hash */
 
1234
                index = ip_set_list[index]->id;
 
1235
        FOREACH_HASH_DO(__set_hash_save_bindings, index, data, used, len, &res);
 
1236
 
 
1237
        return res;     
 
1238
}
 
1239
 
 
1240
/*
 
1241
 * Restore sets
 
1242
 */
 
1243
static int ip_set_restore(void *data,
 
1244
                          int len)
 
1245
{
 
1246
        int res = 0;
 
1247
        int line = 0, used = 0, members_size;
 
1248
        struct ip_set *set;
 
1249
        struct ip_set_hash_save *hash_save;
 
1250
        struct ip_set_restore *set_restore;
 
1251
        ip_set_id_t index;
 
1252
 
 
1253
        /* Loop to restore sets */
 
1254
        while (1) {
 
1255
                line++;
 
1256
                
 
1257
                DP("%u %u %u", used, sizeof(struct ip_set_restore), len);
 
1258
                /* Get and ensure header size */
 
1259
                if (used + sizeof(struct ip_set_restore) > len)
 
1260
                        return line;
 
1261
                set_restore = data + used;
 
1262
                used += sizeof(struct ip_set_restore);
 
1263
 
 
1264
                /* Ensure data size */
 
1265
                if (used
 
1266
                    + set_restore->header_size
 
1267
                    + set_restore->members_size > len)
 
1268
                        return line;
 
1269
 
 
1270
                /* Check marker */
 
1271
                if (set_restore->index == IP_SET_INVALID_ID) {
 
1272
                        line--;
 
1273
                        goto bindings;
 
1274
                }
 
1275
                
 
1276
                /* Try to create the set */
 
1277
                DP("restore %s %s", set_restore->name, set_restore->typename);
 
1278
                res = ip_set_create(set_restore->name,
 
1279
                                    set_restore->typename,
 
1280
                                    set_restore->index,
 
1281
                                    data + used,
 
1282
                                    set_restore->header_size);
 
1283
                
 
1284
                if (res != 0)
 
1285
                        return line;
 
1286
                used += set_restore->header_size;
 
1287
 
 
1288
                index = ip_set_find_byindex(set_restore->index);
 
1289
                DP("index %u, restore_index %u", index, set_restore->index);
 
1290
                if (index != set_restore->index)
 
1291
                        return line;
 
1292
                /* Try to restore members data */
 
1293
                set = ip_set_list[index];
 
1294
                members_size = 0;
 
1295
                DP("members_size %u reqsize %u",
 
1296
                   set_restore->members_size, set->type->reqsize);
 
1297
                while (members_size + set->type->reqsize <=
 
1298
                       set_restore->members_size) {
 
1299
                        line++;
 
1300
                        DP("members: %u, line %u", members_size, line);
 
1301
                        res = __ip_set_addip(index,
 
1302
                                           data + used + members_size,
 
1303
                                           set->type->reqsize);
 
1304
                        if (!(res == 0 || res == -EEXIST))
 
1305
                                return line;
 
1306
                        members_size += set->type->reqsize;
 
1307
                }
 
1308
 
 
1309
                DP("members_size %u  %u",
 
1310
                   set_restore->members_size, members_size);
 
1311
                if (members_size != set_restore->members_size)
 
1312
                        return line++;
 
1313
                used += set_restore->members_size;              
 
1314
        }
 
1315
        
 
1316
   bindings:
 
1317
        /* Loop to restore bindings */
 
1318
        while (used < len) {
 
1319
                line++;
 
1320
 
 
1321
                DP("restore binding, line %u", line);           
 
1322
                /* Get and ensure size */
 
1323
                if (used + sizeof(struct ip_set_hash_save) > len)
 
1324
                        return line;
 
1325
                hash_save = data + used;
 
1326
                used += sizeof(struct ip_set_hash_save);
 
1327
                
 
1328
                /* hash_save->id is used to store the index */
 
1329
                index = ip_set_find_byindex(hash_save->id);
 
1330
                DP("restore binding index %u, id %u, %u -> %u",
 
1331
                   index, hash_save->id, hash_save->ip, hash_save->binding);            
 
1332
                if (index != hash_save->id)
 
1333
                        return line;
 
1334
                if (ip_set_find_byindex(hash_save->binding) == IP_SET_INVALID_ID) {
 
1335
                        DP("corrupt binding set index %u", hash_save->binding);
 
1336
                        return line;
 
1337
                }
 
1338
                set = ip_set_list[hash_save->id];
 
1339
                /* Null valued IP means default binding */
 
1340
                if (hash_save->ip)
 
1341
                        res = ip_set_hash_add(set->id,
 
1342
                                              hash_save->ip,
 
1343
                                              hash_save->binding);
 
1344
                else {
 
1345
                        IP_SET_ASSERT(set->binding == IP_SET_INVALID_ID);
 
1346
                        write_lock_bh(&ip_set_lock);
 
1347
                        set->binding = hash_save->binding;
 
1348
                        __ip_set_get(set->binding);
 
1349
                        write_unlock_bh(&ip_set_lock);
 
1350
                        DP("default binding: %u", set->binding);
 
1351
                }
 
1352
                if (res != 0)
 
1353
                        return line;
 
1354
        }
 
1355
        if (used != len)
 
1356
                return line;
 
1357
        
 
1358
        return 0;       
 
1359
}
 
1360
 
 
1361
static int
 
1362
ip_set_sockfn_set(struct sock *sk, int optval, void *user, unsigned int len)
 
1363
{
 
1364
        void *data;
 
1365
        int res = 0;            /* Assume OK */
 
1366
        unsigned *op;
 
1367
        struct ip_set_req_adt *req_adt;
 
1368
        ip_set_id_t index = IP_SET_INVALID_ID;
 
1369
        int (*adtfn)(ip_set_id_t index,
 
1370
                     const void *data, size_t size);
 
1371
        struct fn_table {
 
1372
                int (*fn)(ip_set_id_t index,
 
1373
                          const void *data, size_t size);
 
1374
        } adtfn_table[] =
 
1375
        { { ip_set_addip }, { ip_set_delip }, { ip_set_testip},
 
1376
          { ip_set_bindip}, { ip_set_unbindip }, { ip_set_testbind },
 
1377
        };
 
1378
 
 
1379
        DP("optval=%d, user=%p, len=%d", optval, user, len);
 
1380
        if (!capable(CAP_NET_ADMIN))
 
1381
                return -EPERM;
 
1382
        if (optval != SO_IP_SET)
 
1383
                return -EBADF;
 
1384
        if (len <= sizeof(unsigned)) {
 
1385
                ip_set_printk("short userdata (want >%zu, got %u)",
 
1386
                              sizeof(unsigned), len);
 
1387
                return -EINVAL;
 
1388
        }
 
1389
        data = vmalloc(len);
 
1390
        if (!data) {
 
1391
                DP("out of mem for %u bytes", len);
 
1392
                return -ENOMEM;
 
1393
        }
 
1394
        if (copy_from_user(data, user, len) != 0) {
 
1395
                res = -EFAULT;
 
1396
                goto done;
 
1397
        }
 
1398
        if (down_interruptible(&ip_set_app_mutex)) {
 
1399
                res = -EINTR;
 
1400
                goto done;
 
1401
        }
 
1402
 
 
1403
        op = (unsigned *)data;
 
1404
        DP("op=%x", *op);
 
1405
        
 
1406
        if (*op < IP_SET_OP_VERSION) {
 
1407
                /* Check the version at the beginning of operations */
 
1408
                struct ip_set_req_version *req_version = data;
 
1409
                if (req_version->version != IP_SET_PROTOCOL_VERSION) {
 
1410
                        res = -EPROTO;
 
1411
                        goto done;
 
1412
                }
 
1413
        }
 
1414
 
 
1415
        switch (*op) {
 
1416
        case IP_SET_OP_CREATE:{
 
1417
                struct ip_set_req_create *req_create = data;
 
1418
                
 
1419
                if (len < sizeof(struct ip_set_req_create)) {
 
1420
                        ip_set_printk("short CREATE data (want >=%zu, got %u)",
 
1421
                                      sizeof(struct ip_set_req_create), len);
 
1422
                        res = -EINVAL;
 
1423
                        goto done;
 
1424
                }
 
1425
                req_create->name[IP_SET_MAXNAMELEN - 1] = '\0';
 
1426
                req_create->typename[IP_SET_MAXNAMELEN - 1] = '\0';
 
1427
                res = ip_set_create(req_create->name,
 
1428
                                    req_create->typename,
 
1429
                                    IP_SET_INVALID_ID,
 
1430
                                    data + sizeof(struct ip_set_req_create),
 
1431
                                    len - sizeof(struct ip_set_req_create));
 
1432
                goto done;
 
1433
        }
 
1434
        case IP_SET_OP_DESTROY:{
 
1435
                struct ip_set_req_std *req_destroy = data;
 
1436
                
 
1437
                if (len != sizeof(struct ip_set_req_std)) {
 
1438
                        ip_set_printk("invalid DESTROY data (want %zu, got %u)",
 
1439
                                      sizeof(struct ip_set_req_std), len);
 
1440
                        res = -EINVAL;
 
1441
                        goto done;
 
1442
                }
 
1443
                if (SETNAME_EQ(req_destroy->name, IPSET_TOKEN_ALL)) {
 
1444
                        /* Destroy all sets */
 
1445
                        index = IP_SET_INVALID_ID;
 
1446
                } else {
 
1447
                        req_destroy->name[IP_SET_MAXNAMELEN - 1] = '\0';
 
1448
                        index = ip_set_find_byname(req_destroy->name);
 
1449
 
 
1450
                        if (index == IP_SET_INVALID_ID) {
 
1451
                                res = -ENOENT;
 
1452
                                goto done;
 
1453
                        }
 
1454
                }
 
1455
                        
 
1456
                res = ip_set_destroy(index);
 
1457
                goto done;
 
1458
        }
 
1459
        case IP_SET_OP_FLUSH:{
 
1460
                struct ip_set_req_std *req_flush = data;
 
1461
 
 
1462
                if (len != sizeof(struct ip_set_req_std)) {
 
1463
                        ip_set_printk("invalid FLUSH data (want %zu, got %u)",
 
1464
                                      sizeof(struct ip_set_req_std), len);
 
1465
                        res = -EINVAL;
 
1466
                        goto done;
 
1467
                }
 
1468
                if (SETNAME_EQ(req_flush->name, IPSET_TOKEN_ALL)) {
 
1469
                        /* Flush all sets */
 
1470
                        index = IP_SET_INVALID_ID;
 
1471
                } else {
 
1472
                        req_flush->name[IP_SET_MAXNAMELEN - 1] = '\0';
 
1473
                        index = ip_set_find_byname(req_flush->name);
 
1474
 
 
1475
                        if (index == IP_SET_INVALID_ID) {
 
1476
                                res = -ENOENT;
 
1477
                                goto done;
 
1478
                        }
 
1479
                }
 
1480
                res = ip_set_flush(index);
 
1481
                goto done;
 
1482
        }
 
1483
        case IP_SET_OP_RENAME:{
 
1484
                struct ip_set_req_create *req_rename = data;
 
1485
 
 
1486
                if (len != sizeof(struct ip_set_req_create)) {
 
1487
                        ip_set_printk("invalid RENAME data (want %zu, got %u)",
 
1488
                                      sizeof(struct ip_set_req_create), len);
 
1489
                        res = -EINVAL;
 
1490
                        goto done;
 
1491
                }
 
1492
 
 
1493
                req_rename->name[IP_SET_MAXNAMELEN - 1] = '\0';
 
1494
                req_rename->typename[IP_SET_MAXNAMELEN - 1] = '\0';
 
1495
                        
 
1496
                index = ip_set_find_byname(req_rename->name);
 
1497
                if (index == IP_SET_INVALID_ID) {
 
1498
                        res = -ENOENT;
 
1499
                        goto done;
 
1500
                }
 
1501
                res = ip_set_rename(index, req_rename->typename);
 
1502
                goto done;
 
1503
        }
 
1504
        case IP_SET_OP_SWAP:{
 
1505
                struct ip_set_req_create *req_swap = data;
 
1506
                ip_set_id_t to_index;
 
1507
 
 
1508
                if (len != sizeof(struct ip_set_req_create)) {
 
1509
                        ip_set_printk("invalid SWAP data (want %zu, got %u)",
 
1510
                                      sizeof(struct ip_set_req_create), len);
 
1511
                        res = -EINVAL;
 
1512
                        goto done;
 
1513
                }
 
1514
 
 
1515
                req_swap->name[IP_SET_MAXNAMELEN - 1] = '\0';
 
1516
                req_swap->typename[IP_SET_MAXNAMELEN - 1] = '\0';
 
1517
 
 
1518
                index = ip_set_find_byname(req_swap->name);
 
1519
                if (index == IP_SET_INVALID_ID) {
 
1520
                        res = -ENOENT;
 
1521
                        goto done;
 
1522
                }
 
1523
                to_index = ip_set_find_byname(req_swap->typename);
 
1524
                if (to_index == IP_SET_INVALID_ID) {
 
1525
                        res = -ENOENT;
 
1526
                        goto done;
 
1527
                }
 
1528
                res = ip_set_swap(index, to_index);
 
1529
                goto done;
 
1530
        }
 
1531
        default:
 
1532
                break;  /* Set identified by id */
 
1533
        }
 
1534
        
 
1535
        /* There we may have add/del/test/bind/unbind/test_bind operations */
 
1536
        if (*op < IP_SET_OP_ADD_IP || *op > IP_SET_OP_TEST_BIND_SET) {
 
1537
                res = -EBADMSG;
 
1538
                goto done;
 
1539
        }
 
1540
        adtfn = adtfn_table[*op - IP_SET_OP_ADD_IP].fn;
 
1541
 
 
1542
        if (len < sizeof(struct ip_set_req_adt)) {
 
1543
                ip_set_printk("short data in adt request (want >=%zu, got %u)",
 
1544
                              sizeof(struct ip_set_req_adt), len);
 
1545
                res = -EINVAL;
 
1546
                goto done;
 
1547
        }
 
1548
        req_adt = data;
 
1549
 
 
1550
        /* -U :all: :all:|:default: uses IP_SET_INVALID_ID */
 
1551
        if (!(*op == IP_SET_OP_UNBIND_SET
 
1552
              && req_adt->index == IP_SET_INVALID_ID)) {
 
1553
                index = ip_set_find_byindex(req_adt->index);
 
1554
                if (index == IP_SET_INVALID_ID) {
 
1555
                        res = -ENOENT;
 
1556
                        goto done;
 
1557
                }
 
1558
        }
 
1559
        res = adtfn(index, data, len);
 
1560
 
 
1561
    done:
 
1562
        up(&ip_set_app_mutex);
 
1563
        vfree(data);
 
1564
        if (res > 0)
 
1565
                res = 0;
 
1566
        DP("final result %d", res);
 
1567
        return res;
 
1568
}
 
1569
 
 
1570
static int
 
1571
ip_set_sockfn_get(struct sock *sk, int optval, void *user, int *len)
 
1572
{
 
1573
        int res = 0;
 
1574
        unsigned *op;
 
1575
        ip_set_id_t index = IP_SET_INVALID_ID;
 
1576
        void *data;
 
1577
        int copylen = *len;
 
1578
 
 
1579
        DP("optval=%d, user=%p, len=%d", optval, user, *len);
 
1580
        if (!capable(CAP_NET_ADMIN))
 
1581
                return -EPERM;
 
1582
        if (optval != SO_IP_SET)
 
1583
                return -EBADF;
 
1584
        if (*len < sizeof(unsigned)) {
 
1585
                ip_set_printk("short userdata (want >=%zu, got %d)",
 
1586
                              sizeof(unsigned), *len);
 
1587
                return -EINVAL;
 
1588
        }
 
1589
        data = vmalloc(*len);
 
1590
        if (!data) {
 
1591
                DP("out of mem for %d bytes", *len);
 
1592
                return -ENOMEM;
 
1593
        }
 
1594
        if (copy_from_user(data, user, *len) != 0) {
 
1595
                res = -EFAULT;
 
1596
                goto done;
 
1597
        }
 
1598
        if (down_interruptible(&ip_set_app_mutex)) {
 
1599
                res = -EINTR;
 
1600
                goto done;
 
1601
        }
 
1602
 
 
1603
        op = (unsigned *) data;
 
1604
        DP("op=%x", *op);
 
1605
 
 
1606
        if (*op < IP_SET_OP_VERSION) {
 
1607
                /* Check the version at the beginning of operations */
 
1608
                struct ip_set_req_version *req_version = data;
 
1609
                if (req_version->version != IP_SET_PROTOCOL_VERSION) {
 
1610
                        res = -EPROTO;
 
1611
                        goto done;
 
1612
                }
 
1613
        }
 
1614
 
 
1615
        switch (*op) {
 
1616
        case IP_SET_OP_VERSION: {
 
1617
                struct ip_set_req_version *req_version = data;
 
1618
 
 
1619
                if (*len != sizeof(struct ip_set_req_version)) {
 
1620
                        ip_set_printk("invalid VERSION (want %zu, got %d)",
 
1621
                                      sizeof(struct ip_set_req_version),
 
1622
                                      *len);
 
1623
                        res = -EINVAL;
 
1624
                        goto done;
 
1625
                }
 
1626
 
 
1627
                req_version->version = IP_SET_PROTOCOL_VERSION;
 
1628
                res = copy_to_user(user, req_version,
 
1629
                                   sizeof(struct ip_set_req_version));
 
1630
                goto done;
 
1631
        }
 
1632
        case IP_SET_OP_GET_BYNAME: {
 
1633
                struct ip_set_req_get_set *req_get = data;
 
1634
 
 
1635
                if (*len != sizeof(struct ip_set_req_get_set)) {
 
1636
                        ip_set_printk("invalid GET_BYNAME (want %zu, got %d)",
 
1637
                                      sizeof(struct ip_set_req_get_set), *len);
 
1638
                        res = -EINVAL;
 
1639
                        goto done;
 
1640
                }
 
1641
                req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
 
1642
                index = ip_set_find_byname(req_get->set.name);
 
1643
                req_get->set.index = index;
 
1644
                goto copy;
 
1645
        }
 
1646
        case IP_SET_OP_GET_BYINDEX: {
 
1647
                struct ip_set_req_get_set *req_get = data;
 
1648
 
 
1649
                if (*len != sizeof(struct ip_set_req_get_set)) {
 
1650
                        ip_set_printk("invalid GET_BYINDEX (want %zu, got %d)",
 
1651
                                      sizeof(struct ip_set_req_get_set), *len);
 
1652
                        res = -EINVAL;
 
1653
                        goto done;
 
1654
                }
 
1655
                req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
 
1656
                index = ip_set_find_byindex(req_get->set.index);
 
1657
                strncpy(req_get->set.name,
 
1658
                        index == IP_SET_INVALID_ID ? ""
 
1659
                        : ip_set_list[index]->name, IP_SET_MAXNAMELEN);
 
1660
                goto copy;
 
1661
        }
 
1662
        case IP_SET_OP_ADT_GET: {
 
1663
                struct ip_set_req_adt_get *req_get = data;
 
1664
 
 
1665
                if (*len != sizeof(struct ip_set_req_adt_get)) {
 
1666
                        ip_set_printk("invalid ADT_GET (want %zu, got %d)",
 
1667
                                      sizeof(struct ip_set_req_adt_get), *len);
 
1668
                        res = -EINVAL;
 
1669
                        goto done;
 
1670
                }
 
1671
                req_get->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
 
1672
                index = ip_set_find_byname(req_get->set.name);
 
1673
                if (index != IP_SET_INVALID_ID) {
 
1674
                        req_get->set.index = index;
 
1675
                        strncpy(req_get->typename,
 
1676
                                ip_set_list[index]->type->typename,
 
1677
                                IP_SET_MAXNAMELEN - 1);
 
1678
                } else {
 
1679
                        res = -ENOENT;
 
1680
                        goto done;
 
1681
                }
 
1682
                goto copy;
 
1683
        }
 
1684
        case IP_SET_OP_MAX_SETS: {
 
1685
                struct ip_set_req_max_sets *req_max_sets = data;
 
1686
                ip_set_id_t i;
 
1687
 
 
1688
                if (*len != sizeof(struct ip_set_req_max_sets)) {
 
1689
                        ip_set_printk("invalid MAX_SETS (want %zu, got %d)",
 
1690
                                      sizeof(struct ip_set_req_max_sets), *len);
 
1691
                        res = -EINVAL;
 
1692
                        goto done;
 
1693
                }
 
1694
 
 
1695
                if (SETNAME_EQ(req_max_sets->set.name, IPSET_TOKEN_ALL)) {
 
1696
                        req_max_sets->set.index = IP_SET_INVALID_ID;
 
1697
                } else {
 
1698
                        req_max_sets->set.name[IP_SET_MAXNAMELEN - 1] = '\0';
 
1699
                        req_max_sets->set.index =
 
1700
                                ip_set_find_byname(req_max_sets->set.name);
 
1701
                        if (req_max_sets->set.index == IP_SET_INVALID_ID) {
 
1702
                                res = -ENOENT;
 
1703
                                goto done;
 
1704
                        }
 
1705
                }
 
1706
                req_max_sets->max_sets = ip_set_max;
 
1707
                req_max_sets->sets = 0;
 
1708
                for (i = 0; i < ip_set_max; i++) {
 
1709
                        if (ip_set_list[i] != NULL)
 
1710
                                req_max_sets->sets++;
 
1711
                }
 
1712
                goto copy;
 
1713
        }
 
1714
        case IP_SET_OP_LIST_SIZE:
 
1715
        case IP_SET_OP_SAVE_SIZE: {
 
1716
                struct ip_set_req_setnames *req_setnames = data;
 
1717
                struct ip_set_name_list *name_list;
 
1718
                struct ip_set *set;
 
1719
                ip_set_id_t i;
 
1720
                int used;
 
1721
 
 
1722
                if (*len < sizeof(struct ip_set_req_setnames)) {
 
1723
                        ip_set_printk("short LIST_SIZE (want >=%zu, got %d)",
 
1724
                                      sizeof(struct ip_set_req_setnames), *len);
 
1725
                        res = -EINVAL;
 
1726
                        goto done;
 
1727
                }
 
1728
 
 
1729
                req_setnames->size = 0;
 
1730
                used = sizeof(struct ip_set_req_setnames);
 
1731
                for (i = 0; i < ip_set_max; i++) {
 
1732
                        if (ip_set_list[i] == NULL)
 
1733
                                continue;
 
1734
                        name_list = data + used;
 
1735
                        used += sizeof(struct ip_set_name_list);
 
1736
                        if (used > copylen) {
 
1737
                                res = -EAGAIN;
 
1738
                                goto done;
 
1739
                        }
 
1740
                        set = ip_set_list[i];
 
1741
                        /* Fill in index, name, etc. */
 
1742
                        name_list->index = i;
 
1743
                        name_list->id = set->id;
 
1744
                        strncpy(name_list->name,
 
1745
                                set->name,
 
1746
                                IP_SET_MAXNAMELEN - 1);
 
1747
                        strncpy(name_list->typename,
 
1748
                                set->type->typename,
 
1749
                                IP_SET_MAXNAMELEN - 1);
 
1750
                        DP("filled %s of type %s, index %u\n",
 
1751
                           name_list->name, name_list->typename,
 
1752
                           name_list->index);
 
1753
                        if (!(req_setnames->index == IP_SET_INVALID_ID
 
1754
                              || req_setnames->index == i))
 
1755
                              continue;
 
1756
                        /* Update size */
 
1757
                        switch (*op) {
 
1758
                        case IP_SET_OP_LIST_SIZE: {
 
1759
                                req_setnames->size += sizeof(struct ip_set_list)
 
1760
                                        + set->type->header_size
 
1761
                                        + set->type->list_members_size(set);
 
1762
                                /* Sets are identified by id in the hash */
 
1763
                                FOREACH_HASH_DO(__set_hash_bindings_size_list,
 
1764
                                                set->id, &req_setnames->size);
 
1765
                                break;
 
1766
                        }
 
1767
                        case IP_SET_OP_SAVE_SIZE: {
 
1768
                                req_setnames->size += sizeof(struct ip_set_save)
 
1769
                                        + set->type->header_size
 
1770
                                        + set->type->list_members_size(set);
 
1771
                                FOREACH_HASH_DO(__set_hash_bindings_size_save,
 
1772
                                                set->id, &req_setnames->size);
 
1773
                                break;
 
1774
                        }
 
1775
                        default:
 
1776
                                break;
 
1777
                        }
 
1778
                }
 
1779
                if (copylen != used) {
 
1780
                        res = -EAGAIN;
 
1781
                        goto done;
 
1782
                }
 
1783
                goto copy;
 
1784
        }
 
1785
        case IP_SET_OP_LIST: {
 
1786
                struct ip_set_req_list *req_list = data;
 
1787
                ip_set_id_t i;
 
1788
                int used;
 
1789
 
 
1790
                if (*len < sizeof(struct ip_set_req_list)) {
 
1791
                        ip_set_printk("short LIST (want >=%zu, got %d)",
 
1792
                                      sizeof(struct ip_set_req_list), *len);
 
1793
                        res = -EINVAL;
 
1794
                        goto done;
 
1795
                }
 
1796
                index = req_list->index;
 
1797
                if (index != IP_SET_INVALID_ID
 
1798
                    && ip_set_find_byindex(index) != index) {
 
1799
                        res = -ENOENT;
 
1800
                        goto done;
 
1801
                }
 
1802
                used = 0;
 
1803
                if (index == IP_SET_INVALID_ID) {
 
1804
                        /* List all sets */
 
1805
                        for (i = 0; i < ip_set_max && res == 0; i++) {
 
1806
                                if (ip_set_list[i] != NULL)
 
1807
                                        res = ip_set_list_set(i, data, &used, *len);
 
1808
                        }
 
1809
                } else {
 
1810
                        /* List an individual set */
 
1811
                        res = ip_set_list_set(index, data, &used, *len);
 
1812
                }
 
1813
                if (res != 0)
 
1814
                        goto done;
 
1815
                else if (copylen != used) {
 
1816
                        res = -EAGAIN;
 
1817
                        goto done;
 
1818
                }
 
1819
                goto copy;
 
1820
        }
 
1821
        case IP_SET_OP_SAVE: {
 
1822
                struct ip_set_req_list *req_save = data;
 
1823
                ip_set_id_t i;
 
1824
                int used;
 
1825
 
 
1826
                if (*len < sizeof(struct ip_set_req_list)) {
 
1827
                        ip_set_printk("short SAVE (want >=%zu, got %d)",
 
1828
                                      sizeof(struct ip_set_req_list), *len);
 
1829
                        res = -EINVAL;
 
1830
                        goto done;
 
1831
                }
 
1832
                index = req_save->index;
 
1833
                if (index != IP_SET_INVALID_ID
 
1834
                    && ip_set_find_byindex(index) != index) {
 
1835
                        res = -ENOENT;
 
1836
                        goto done;
 
1837
                }
 
1838
                used = 0;
 
1839
                if (index == IP_SET_INVALID_ID) {
 
1840
                        /* Save all sets */
 
1841
                        for (i = 0; i < ip_set_max && res == 0; i++) {
 
1842
                                if (ip_set_list[i] != NULL)
 
1843
                                        res = ip_set_save_set(i, data, &used, *len);
 
1844
                        }
 
1845
                } else {
 
1846
                        /* Save an individual set */
 
1847
                        res = ip_set_save_set(index, data, &used, *len);
 
1848
                }
 
1849
                if (res == 0)
 
1850
                        res = ip_set_save_bindings(index, data, &used, *len);
 
1851
                        
 
1852
                if (res != 0)
 
1853
                        goto done;
 
1854
                else if (copylen != used) {
 
1855
                        res = -EAGAIN;
 
1856
                        goto done;
 
1857
                }
 
1858
                goto copy;
 
1859
        }
 
1860
        case IP_SET_OP_RESTORE: {
 
1861
                struct ip_set_req_setnames *req_restore = data;
 
1862
                int line;
 
1863
 
 
1864
                if (*len < sizeof(struct ip_set_req_setnames)
 
1865
                    || *len != req_restore->size) {
 
1866
                        ip_set_printk("invalid RESTORE (want =%zu, got %d)",
 
1867
                                      req_restore->size, *len);
 
1868
                        res = -EINVAL;
 
1869
                        goto done;
 
1870
                }
 
1871
                line = ip_set_restore(data + sizeof(struct ip_set_req_setnames),
 
1872
                                      req_restore->size - sizeof(struct ip_set_req_setnames));
 
1873
                DP("ip_set_restore: %u", line);
 
1874
                if (line != 0) {
 
1875
                        res = -EAGAIN;
 
1876
                        req_restore->size = line;
 
1877
                        copylen = sizeof(struct ip_set_req_setnames);
 
1878
                        goto copy;
 
1879
                }
 
1880
                goto done;
 
1881
        }
 
1882
        default:
 
1883
                res = -EBADMSG;
 
1884
                goto done;
 
1885
        }       /* end of switch(op) */
 
1886
 
 
1887
    copy:
 
1888
        DP("set %s, copylen %u", index != IP_SET_INVALID_ID
 
1889
                                 && ip_set_list[index]
 
1890
                     ? ip_set_list[index]->name
 
1891
                     : ":all:", copylen);
 
1892
        res = copy_to_user(user, data, copylen);
 
1893
        
 
1894
    done:
 
1895
        up(&ip_set_app_mutex);
 
1896
        vfree(data);
 
1897
        if (res > 0)
 
1898
                res = 0;
 
1899
        DP("final result %d", res);
 
1900
        return res;
 
1901
}
 
1902
 
 
1903
static struct nf_sockopt_ops so_set = {
 
1904
        .pf             = PF_INET,
 
1905
        .set_optmin     = SO_IP_SET,
 
1906
        .set_optmax     = SO_IP_SET + 1,
 
1907
        .set            = &ip_set_sockfn_set,
 
1908
        .get_optmin     = SO_IP_SET,
 
1909
        .get_optmax     = SO_IP_SET + 1,
 
1910
        .get            = &ip_set_sockfn_get,
 
1911
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
 
1912
        .use            = 0,
 
1913
#else
 
1914
        .owner          = THIS_MODULE,
 
1915
#endif
 
1916
};
 
1917
 
 
1918
static int max_sets, hash_size;
 
1919
module_param(max_sets, int, 0600);
 
1920
MODULE_PARM_DESC(max_sets, "maximal number of sets");
 
1921
module_param(hash_size, int, 0600);
 
1922
MODULE_PARM_DESC(hash_size, "hash size for bindings");
 
1923
MODULE_LICENSE("GPL");
 
1924
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
 
1925
MODULE_DESCRIPTION("module implementing core IP set support");
 
1926
 
 
1927
static int __init ip_set_init(void)
 
1928
{
 
1929
        int res;
 
1930
        ip_set_id_t i;
 
1931
 
 
1932
        get_random_bytes(&ip_set_hash_random, 4);
 
1933
        if (max_sets)
 
1934
                ip_set_max = max_sets;
 
1935
        ip_set_list = vmalloc(sizeof(struct ip_set *) * ip_set_max);
 
1936
        if (!ip_set_list) {
 
1937
                printk(KERN_ERR "Unable to create ip_set_list\n");
 
1938
                return -ENOMEM;
 
1939
        }
 
1940
        memset(ip_set_list, 0, sizeof(struct ip_set *) * ip_set_max);
 
1941
        if (hash_size)
 
1942
                ip_set_bindings_hash_size = hash_size;
 
1943
        ip_set_hash = vmalloc(sizeof(struct list_head) * ip_set_bindings_hash_size);
 
1944
        if (!ip_set_hash) {
 
1945
                printk(KERN_ERR "Unable to create ip_set_hash\n");
 
1946
                vfree(ip_set_list);
 
1947
                return -ENOMEM;
 
1948
        }
 
1949
        for (i = 0; i < ip_set_bindings_hash_size; i++)
 
1950
                INIT_LIST_HEAD(&ip_set_hash[i]);
 
1951
 
 
1952
        INIT_LIST_HEAD(&set_type_list);
 
1953
 
 
1954
        res = nf_register_sockopt(&so_set);
 
1955
        if (res != 0) {
 
1956
                ip_set_printk("SO_SET registry failed: %d", res);
 
1957
                vfree(ip_set_list);
 
1958
                vfree(ip_set_hash);
 
1959
                return res;
 
1960
        }
 
1961
        return 0;
 
1962
}
 
1963
 
 
1964
static void __exit ip_set_fini(void)
 
1965
{
 
1966
        /* There can't be any existing set or binding */
 
1967
        nf_unregister_sockopt(&so_set);
 
1968
        vfree(ip_set_list);
 
1969
        vfree(ip_set_hash);
 
1970
        DP("these are the famous last words");
 
1971
}
 
1972
 
 
1973
EXPORT_SYMBOL(ip_set_register_set_type);
 
1974
EXPORT_SYMBOL(ip_set_unregister_set_type);
 
1975
 
 
1976
EXPORT_SYMBOL(ip_set_get_byname);
 
1977
EXPORT_SYMBOL(ip_set_get_byindex);
 
1978
EXPORT_SYMBOL(ip_set_put);
 
1979
 
 
1980
EXPORT_SYMBOL(ip_set_addip_kernel);
 
1981
EXPORT_SYMBOL(ip_set_delip_kernel);
 
1982
EXPORT_SYMBOL(ip_set_testip_kernel);
 
1983
 
 
1984
module_init(ip_set_init);
 
1985
module_exit(ip_set_fini);