~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to net/netfilter/ipset/ip_set_hash_ipport.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
 
2
 *
 
3
 * This program is free software; you can redistribute it and/or modify
 
4
 * it under the terms of the GNU General Public License version 2 as
 
5
 * published by the Free Software Foundation.
 
6
 */
 
7
 
 
8
/* Kernel module implementing an IP set type: the hash:ip,port type */
 
9
 
 
10
#include <linux/jhash.h>
 
11
#include <linux/module.h>
 
12
#include <linux/ip.h>
 
13
#include <linux/skbuff.h>
 
14
#include <linux/errno.h>
 
15
#include <linux/random.h>
 
16
#include <net/ip.h>
 
17
#include <net/ipv6.h>
 
18
#include <net/netlink.h>
 
19
#include <net/tcp.h>
 
20
 
 
21
#include <linux/netfilter.h>
 
22
#include <linux/netfilter/ipset/pfxlen.h>
 
23
#include <linux/netfilter/ipset/ip_set.h>
 
24
#include <linux/netfilter/ipset/ip_set_timeout.h>
 
25
#include <linux/netfilter/ipset/ip_set_getport.h>
 
26
#include <linux/netfilter/ipset/ip_set_hash.h>
 
27
 
 
28
MODULE_LICENSE("GPL");
 
29
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
 
30
MODULE_DESCRIPTION("hash:ip,port type of IP sets");
 
31
MODULE_ALIAS("ip_set_hash:ip,port");
 
32
 
 
33
/* Type specific function prefix */
 
34
#define TYPE            hash_ipport
 
35
 
 
36
static bool
 
37
hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b);
 
38
 
 
39
#define hash_ipport4_same_set   hash_ipport_same_set
 
40
#define hash_ipport6_same_set   hash_ipport_same_set
 
41
 
 
42
/* The type variant functions: IPv4 */
 
43
 
 
44
/* Member elements without timeout */
 
45
struct hash_ipport4_elem {
 
46
        __be32 ip;
 
47
        __be16 port;
 
48
        u8 proto;
 
49
        u8 padding;
 
50
};
 
51
 
 
52
/* Member elements with timeout support */
 
53
struct hash_ipport4_telem {
 
54
        __be32 ip;
 
55
        __be16 port;
 
56
        u8 proto;
 
57
        u8 padding;
 
58
        unsigned long timeout;
 
59
};
 
60
 
 
61
static inline bool
 
62
hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
 
63
                        const struct hash_ipport4_elem *ip2)
 
64
{
 
65
        return ip1->ip == ip2->ip &&
 
66
               ip1->port == ip2->port &&
 
67
               ip1->proto == ip2->proto;
 
68
}
 
69
 
 
70
static inline bool
 
71
hash_ipport4_data_isnull(const struct hash_ipport4_elem *elem)
 
72
{
 
73
        return elem->proto == 0;
 
74
}
 
75
 
 
76
static inline void
 
77
hash_ipport4_data_copy(struct hash_ipport4_elem *dst,
 
78
                       const struct hash_ipport4_elem *src)
 
79
{
 
80
        dst->ip = src->ip;
 
81
        dst->port = src->port;
 
82
        dst->proto = src->proto;
 
83
}
 
84
 
 
85
static inline void
 
86
hash_ipport4_data_zero_out(struct hash_ipport4_elem *elem)
 
87
{
 
88
        elem->proto = 0;
 
89
}
 
90
 
 
91
static bool
 
92
hash_ipport4_data_list(struct sk_buff *skb,
 
93
                       const struct hash_ipport4_elem *data)
 
94
{
 
95
        NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
 
96
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
 
97
        NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
 
98
        return 0;
 
99
 
 
100
nla_put_failure:
 
101
        return 1;
 
102
}
 
103
 
 
104
static bool
 
105
hash_ipport4_data_tlist(struct sk_buff *skb,
 
106
                        const struct hash_ipport4_elem *data)
 
107
{
 
108
        const struct hash_ipport4_telem *tdata =
 
109
                (const struct hash_ipport4_telem *)data;
 
110
 
 
111
        NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
 
112
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
 
113
        NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
 
114
        NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
 
115
                      htonl(ip_set_timeout_get(tdata->timeout)));
 
116
 
 
117
        return 0;
 
118
 
 
119
nla_put_failure:
 
120
        return 1;
 
121
}
 
122
 
 
123
#define PF              4
 
124
#define HOST_MASK       32
 
125
#include <linux/netfilter/ipset/ip_set_ahash.h>
 
126
 
 
127
static int
 
128
hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
 
129
                  enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
 
130
{
 
131
        const struct ip_set_hash *h = set->data;
 
132
        ipset_adtfn adtfn = set->variant->adt[adt];
 
133
        struct hash_ipport4_elem data = { };
 
134
 
 
135
        if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
 
136
                                 &data.port, &data.proto))
 
137
                return -EINVAL;
 
138
 
 
139
        ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
 
140
 
 
141
        return adtfn(set, &data, h->timeout);
 
142
}
 
143
 
 
144
static int
 
145
hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
 
146
                  enum ipset_adt adt, u32 *lineno, u32 flags)
 
147
{
 
148
        const struct ip_set_hash *h = set->data;
 
149
        ipset_adtfn adtfn = set->variant->adt[adt];
 
150
        struct hash_ipport4_elem data = { };
 
151
        u32 ip, ip_to, p, port, port_to;
 
152
        u32 timeout = h->timeout;
 
153
        bool with_ports = false;
 
154
        int ret;
 
155
 
 
156
        if (unlikely(!tb[IPSET_ATTR_IP] ||
 
157
                     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
 
158
                     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
 
159
                     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
 
160
                return -IPSET_ERR_PROTOCOL;
 
161
 
 
162
        if (tb[IPSET_ATTR_LINENO])
 
163
                *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 
164
 
 
165
        ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
 
166
        if (ret)
 
167
                return ret;
 
168
 
 
169
        if (tb[IPSET_ATTR_PORT])
 
170
                data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
 
171
        else
 
172
                return -IPSET_ERR_PROTOCOL;
 
173
 
 
174
        if (tb[IPSET_ATTR_PROTO]) {
 
175
                data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
 
176
                with_ports = ip_set_proto_with_ports(data.proto);
 
177
 
 
178
                if (data.proto == 0)
 
179
                        return -IPSET_ERR_INVALID_PROTO;
 
180
        } else
 
181
                return -IPSET_ERR_MISSING_PROTO;
 
182
 
 
183
        if (!(with_ports || data.proto == IPPROTO_ICMP))
 
184
                data.port = 0;
 
185
 
 
186
        if (tb[IPSET_ATTR_TIMEOUT]) {
 
187
                if (!with_timeout(h->timeout))
 
188
                        return -IPSET_ERR_TIMEOUT;
 
189
                timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 
190
        }
 
191
 
 
192
        if (adt == IPSET_TEST ||
 
193
            !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
 
194
              tb[IPSET_ATTR_PORT_TO])) {
 
195
                ret = adtfn(set, &data, timeout);
 
196
                return ip_set_eexist(ret, flags) ? 0 : ret;
 
197
        }
 
198
 
 
199
        ip = ntohl(data.ip);
 
200
        if (tb[IPSET_ATTR_IP_TO]) {
 
201
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
 
202
                if (ret)
 
203
                        return ret;
 
204
                if (ip > ip_to)
 
205
                        swap(ip, ip_to);
 
206
        } else if (tb[IPSET_ATTR_CIDR]) {
 
207
                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 
208
 
 
209
                if (cidr > 32)
 
210
                        return -IPSET_ERR_INVALID_CIDR;
 
211
                ip &= ip_set_hostmask(cidr);
 
212
                ip_to = ip | ~ip_set_hostmask(cidr);
 
213
        } else
 
214
                ip_to = ip;
 
215
 
 
216
        port_to = port = ntohs(data.port);
 
217
        if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
 
218
                port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
 
219
                if (port > port_to)
 
220
                        swap(port, port_to);
 
221
        }
 
222
 
 
223
        for (; !before(ip_to, ip); ip++)
 
224
                for (p = port; p <= port_to; p++) {
 
225
                        data.ip = htonl(ip);
 
226
                        data.port = htons(p);
 
227
                        ret = adtfn(set, &data, timeout);
 
228
 
 
229
                        if (ret && !ip_set_eexist(ret, flags))
 
230
                                return ret;
 
231
                        else
 
232
                                ret = 0;
 
233
                }
 
234
        return ret;
 
235
}
 
236
 
 
237
static bool
 
238
hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b)
 
239
{
 
240
        const struct ip_set_hash *x = a->data;
 
241
        const struct ip_set_hash *y = b->data;
 
242
 
 
243
        /* Resizing changes htable_bits, so we ignore it */
 
244
        return x->maxelem == y->maxelem &&
 
245
               x->timeout == y->timeout;
 
246
}
 
247
 
 
248
/* The type variant functions: IPv6 */
 
249
 
 
250
struct hash_ipport6_elem {
 
251
        union nf_inet_addr ip;
 
252
        __be16 port;
 
253
        u8 proto;
 
254
        u8 padding;
 
255
};
 
256
 
 
257
struct hash_ipport6_telem {
 
258
        union nf_inet_addr ip;
 
259
        __be16 port;
 
260
        u8 proto;
 
261
        u8 padding;
 
262
        unsigned long timeout;
 
263
};
 
264
 
 
265
static inline bool
 
266
hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
 
267
                        const struct hash_ipport6_elem *ip2)
 
268
{
 
269
        return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
 
270
               ip1->port == ip2->port &&
 
271
               ip1->proto == ip2->proto;
 
272
}
 
273
 
 
274
static inline bool
 
275
hash_ipport6_data_isnull(const struct hash_ipport6_elem *elem)
 
276
{
 
277
        return elem->proto == 0;
 
278
}
 
279
 
 
280
static inline void
 
281
hash_ipport6_data_copy(struct hash_ipport6_elem *dst,
 
282
                       const struct hash_ipport6_elem *src)
 
283
{
 
284
        memcpy(dst, src, sizeof(*dst));
 
285
}
 
286
 
 
287
static inline void
 
288
hash_ipport6_data_zero_out(struct hash_ipport6_elem *elem)
 
289
{
 
290
        elem->proto = 0;
 
291
}
 
292
 
 
293
static bool
 
294
hash_ipport6_data_list(struct sk_buff *skb,
 
295
                       const struct hash_ipport6_elem *data)
 
296
{
 
297
        NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
 
298
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
 
299
        NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
 
300
        return 0;
 
301
 
 
302
nla_put_failure:
 
303
        return 1;
 
304
}
 
305
 
 
306
static bool
 
307
hash_ipport6_data_tlist(struct sk_buff *skb,
 
308
                        const struct hash_ipport6_elem *data)
 
309
{
 
310
        const struct hash_ipport6_telem *e =
 
311
                (const struct hash_ipport6_telem *)data;
 
312
 
 
313
        NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
 
314
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
 
315
        NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
 
316
        NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
 
317
                      htonl(ip_set_timeout_get(e->timeout)));
 
318
        return 0;
 
319
 
 
320
nla_put_failure:
 
321
        return 1;
 
322
}
 
323
 
 
324
#undef PF
 
325
#undef HOST_MASK
 
326
 
 
327
#define PF              6
 
328
#define HOST_MASK       128
 
329
#include <linux/netfilter/ipset/ip_set_ahash.h>
 
330
 
 
331
static int
 
332
hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
 
333
                  enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
 
334
{
 
335
        const struct ip_set_hash *h = set->data;
 
336
        ipset_adtfn adtfn = set->variant->adt[adt];
 
337
        struct hash_ipport6_elem data = { };
 
338
 
 
339
        if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
 
340
                                 &data.port, &data.proto))
 
341
                return -EINVAL;
 
342
 
 
343
        ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
 
344
 
 
345
        return adtfn(set, &data, h->timeout);
 
346
}
 
347
 
 
348
static int
 
349
hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
 
350
                  enum ipset_adt adt, u32 *lineno, u32 flags)
 
351
{
 
352
        const struct ip_set_hash *h = set->data;
 
353
        ipset_adtfn adtfn = set->variant->adt[adt];
 
354
        struct hash_ipport6_elem data = { };
 
355
        u32 port, port_to;
 
356
        u32 timeout = h->timeout;
 
357
        bool with_ports = false;
 
358
        int ret;
 
359
 
 
360
        if (unlikely(!tb[IPSET_ATTR_IP] ||
 
361
                     !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
 
362
                     !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
 
363
                     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
 
364
                     tb[IPSET_ATTR_IP_TO] ||
 
365
                     tb[IPSET_ATTR_CIDR]))
 
366
                return -IPSET_ERR_PROTOCOL;
 
367
 
 
368
        if (tb[IPSET_ATTR_LINENO])
 
369
                *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
 
370
 
 
371
        ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
 
372
        if (ret)
 
373
                return ret;
 
374
 
 
375
        if (tb[IPSET_ATTR_PORT])
 
376
                data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
 
377
        else
 
378
                return -IPSET_ERR_PROTOCOL;
 
379
 
 
380
        if (tb[IPSET_ATTR_PROTO]) {
 
381
                data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
 
382
                with_ports = ip_set_proto_with_ports(data.proto);
 
383
 
 
384
                if (data.proto == 0)
 
385
                        return -IPSET_ERR_INVALID_PROTO;
 
386
        } else
 
387
                return -IPSET_ERR_MISSING_PROTO;
 
388
 
 
389
        if (!(with_ports || data.proto == IPPROTO_ICMPV6))
 
390
                data.port = 0;
 
391
 
 
392
        if (tb[IPSET_ATTR_TIMEOUT]) {
 
393
                if (!with_timeout(h->timeout))
 
394
                        return -IPSET_ERR_TIMEOUT;
 
395
                timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 
396
        }
 
397
 
 
398
        if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
 
399
                ret = adtfn(set, &data, timeout);
 
400
                return ip_set_eexist(ret, flags) ? 0 : ret;
 
401
        }
 
402
 
 
403
        port = ntohs(data.port);
 
404
        port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
 
405
        if (port > port_to)
 
406
                swap(port, port_to);
 
407
 
 
408
        for (; port <= port_to; port++) {
 
409
                data.port = htons(port);
 
410
                ret = adtfn(set, &data, timeout);
 
411
 
 
412
                if (ret && !ip_set_eexist(ret, flags))
 
413
                        return ret;
 
414
                else
 
415
                        ret = 0;
 
416
        }
 
417
        return ret;
 
418
}
 
419
 
 
420
/* Create hash:ip type of sets */
 
421
 
 
422
static int
 
423
hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
 
424
{
 
425
        struct ip_set_hash *h;
 
426
        u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
 
427
        u8 hbits;
 
428
 
 
429
        if (!(set->family == AF_INET || set->family == AF_INET6))
 
430
                return -IPSET_ERR_INVALID_FAMILY;
 
431
 
 
432
        if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
 
433
                     !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
 
434
                     !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
 
435
                return -IPSET_ERR_PROTOCOL;
 
436
 
 
437
        if (tb[IPSET_ATTR_HASHSIZE]) {
 
438
                hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
 
439
                if (hashsize < IPSET_MIMINAL_HASHSIZE)
 
440
                        hashsize = IPSET_MIMINAL_HASHSIZE;
 
441
        }
 
442
 
 
443
        if (tb[IPSET_ATTR_MAXELEM])
 
444
                maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
 
445
 
 
446
        h = kzalloc(sizeof(*h), GFP_KERNEL);
 
447
        if (!h)
 
448
                return -ENOMEM;
 
449
 
 
450
        h->maxelem = maxelem;
 
451
        get_random_bytes(&h->initval, sizeof(h->initval));
 
452
        h->timeout = IPSET_NO_TIMEOUT;
 
453
 
 
454
        hbits = htable_bits(hashsize);
 
455
        h->table = ip_set_alloc(
 
456
                        sizeof(struct htable)
 
457
                        + jhash_size(hbits) * sizeof(struct hbucket));
 
458
        if (!h->table) {
 
459
                kfree(h);
 
460
                return -ENOMEM;
 
461
        }
 
462
        h->table->htable_bits = hbits;
 
463
 
 
464
        set->data = h;
 
465
 
 
466
        if (tb[IPSET_ATTR_TIMEOUT]) {
 
467
                h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
 
468
 
 
469
                set->variant = set->family == AF_INET
 
470
                        ? &hash_ipport4_tvariant : &hash_ipport6_tvariant;
 
471
 
 
472
                if (set->family == AF_INET)
 
473
                        hash_ipport4_gc_init(set);
 
474
                else
 
475
                        hash_ipport6_gc_init(set);
 
476
        } else {
 
477
                set->variant = set->family == AF_INET
 
478
                        ? &hash_ipport4_variant : &hash_ipport6_variant;
 
479
        }
 
480
 
 
481
        pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
 
482
                 set->name, jhash_size(h->table->htable_bits),
 
483
                 h->table->htable_bits, h->maxelem, set->data, h->table);
 
484
 
 
485
        return 0;
 
486
}
 
487
 
 
488
static struct ip_set_type hash_ipport_type __read_mostly = {
 
489
        .name           = "hash:ip,port",
 
490
        .protocol       = IPSET_PROTOCOL,
 
491
        .features       = IPSET_TYPE_IP | IPSET_TYPE_PORT,
 
492
        .dimension      = IPSET_DIM_TWO,
 
493
        .family         = AF_UNSPEC,
 
494
        .revision       = 1,
 
495
        .create         = hash_ipport_create,
 
496
        .create_policy  = {
 
497
                [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
 
498
                [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
 
499
                [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
 
500
                [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
 
501
                [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
 
502
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 
503
        },
 
504
        .adt_policy     = {
 
505
                [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
 
506
                [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
 
507
                [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
 
508
                [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
 
509
                [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
 
510
                [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
 
511
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
 
512
                [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
 
513
        },
 
514
        .me             = THIS_MODULE,
 
515
};
 
516
 
 
517
static int __init
 
518
hash_ipport_init(void)
 
519
{
 
520
        return ip_set_type_register(&hash_ipport_type);
 
521
}
 
522
 
 
523
static void __exit
 
524
hash_ipport_fini(void)
 
525
{
 
526
        ip_set_type_unregister(&hash_ipport_type);
 
527
}
 
528
 
 
529
module_init(hash_ipport_init);
 
530
module_exit(hash_ipport_fini);