mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-12-07 16:43:54 +01:00
ipset: import ipset 5.2+GENL
This requires Linux 2.6.35 or newer to build, so it is deactivated by default in the "mconfig" file.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,6 +3,7 @@
|
||||
*.loT
|
||||
*.o
|
||||
.deps
|
||||
.dirstamp
|
||||
.libs
|
||||
Makefile
|
||||
Makefile.in
|
||||
|
||||
@@ -25,6 +25,7 @@ AC_CHECK_HEADERS([linux/netfilter/x_tables.h], [],
|
||||
[AC_MSG_ERROR([You need to have linux/netfilter/x_tables.h, see INSTALL file for details])])
|
||||
PKG_CHECK_MODULES([libxtables], [xtables >= 1.4.3])
|
||||
xtlibdir="$(pkg-config --variable=xtlibdir xtables)"
|
||||
PKG_CHECK_MODULES([libmnl], [libmnl >= 1])
|
||||
|
||||
AC_ARG_WITH([xtlibdir],
|
||||
AS_HELP_STRING([--with-xtlibdir=PATH],
|
||||
@@ -86,5 +87,6 @@ AC_SUBST([kbuilddir])
|
||||
AC_SUBST([xtlibdir])
|
||||
AC_CONFIG_FILES([Makefile Makefile.iptrules Makefile.mans geoip/Makefile
|
||||
extensions/Makefile extensions/ACCOUNT/Makefile
|
||||
extensions/ipset-4/Makefile extensions/pknock/Makefile])
|
||||
extensions/ipset-4/Makefile extensions/ipset-5/Makefile
|
||||
extensions/pknock/Makefile])
|
||||
AC_OUTPUT
|
||||
|
||||
@@ -4,6 +4,9 @@ HEAD
|
||||
Fixes:
|
||||
- Update to ipset 4.5
|
||||
* the iptreemap type used wrong gfp flags when deleting entries
|
||||
- Include ipset 5.2 with genetlink patch (beta)
|
||||
* no kernel patch needed, but requires Linux >= 2.6.35
|
||||
and thus needs to be manually enabled in mconfig
|
||||
|
||||
|
||||
v1.31 (2010-11-05)
|
||||
|
||||
@@ -27,6 +27,7 @@ obj-${build_geoip} += xt_geoip.o
|
||||
obj-${build_iface} += xt_iface.o
|
||||
obj-${build_ipp2p} += xt_ipp2p.o
|
||||
obj-${build_ipset4} += ipset-4/
|
||||
obj-${build_ipset5} += ipset-5/
|
||||
obj-${build_ipv4options} += xt_ipv4options.o
|
||||
obj-${build_length2} += xt_length2.o
|
||||
obj-${build_lscan} += xt_lscan.o
|
||||
|
||||
@@ -19,6 +19,7 @@ obj-${build_geoip} += libxt_geoip.so
|
||||
obj-${build_iface} += libxt_iface.so
|
||||
obj-${build_ipp2p} += libxt_ipp2p.so
|
||||
obj-${build_ipset4} += ipset-4/
|
||||
obj-${build_ipset5} += ipset-5/
|
||||
obj-${build_ipv4options} += libxt_ipv4options.so
|
||||
obj-${build_length2} += libxt_length2.so
|
||||
obj-${build_lscan} += libxt_lscan.so
|
||||
|
||||
1
extensions/ipset-5/.gitignore
vendored
Normal file
1
extensions/ipset-5/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/ipset
|
||||
7
extensions/ipset-5/Kbuild
Normal file
7
extensions/ipset-5/Kbuild
Normal file
@@ -0,0 +1,7 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
obj-m += xt_set.o
|
||||
obj-m += ip_set.o ip_set_bitmap_ip.o ip_set_bitmap_ipmac.o
|
||||
obj-m += ip_set_bitmap_port.o ip_set_hash_ip.o ip_set_hash_ipport.o
|
||||
obj-m += ip_set_hash_ipportip.o ip_set_hash_ipportnet.o ip_set_hash_net.o
|
||||
obj-m += ip_set_hash_netport.o ip_set_list_set.o
|
||||
23
extensions/ipset-5/Makefile.am
Normal file
23
extensions/ipset-5/Makefile.am
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
AM_CFLAGS = ${regular_CFLAGS} ${libmnl_CFLAGS} -Iinclude
|
||||
|
||||
include ../../Makefile.extra
|
||||
|
||||
lib_LTLIBRARIES = libipset.la
|
||||
libipset_la_SOURCES = libipset/data.c libipset/icmp.c libipset/icmpv6.c \
|
||||
libipset/mnl.c libipset/parse.c libipset/print.c \
|
||||
libipset/session.c libipset/types.c
|
||||
libipset_la_LIBADD = ${libmnl_LIBS}
|
||||
libipset_la_LDFLAGS = -version-info 1:0:0
|
||||
|
||||
sbin_PROGRAMS = ipset
|
||||
ipset_SOURCES = src/ipset.c src/errcode.c src/ui.c src/ipset_bitmap_ip.c \
|
||||
src/ipset_bitmap_ipmac.c src/ipset_bitmap_port.c \
|
||||
src/ipset_hash_ip.c src/ipset_hash_ipport.c \
|
||||
src/ipset_hash_ipportip.c src/ipset_hash_ipportnet.c \
|
||||
src/ipset_hash_net.c src/ipset_hash_netport.c \
|
||||
src/ipset_list_set.c
|
||||
ipset_LDADD = libipset.la
|
||||
|
||||
man_MANS = ipset.8
|
||||
2
extensions/ipset-5/Mbuild
Normal file
2
extensions/ipset-5/Mbuild
Normal file
@@ -0,0 +1,2 @@
|
||||
# -*- Makefile -*-
|
||||
|
||||
133
extensions/ipset-5/include/libipset/data.h
Normal file
133
extensions/ipset-5/include/libipset/data.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_DATA_H
|
||||
#define LIBIPSET_DATA_H
|
||||
|
||||
#include <stdbool.h> /* bool */
|
||||
#include <libipset/nf_inet_addr.h> /* union nf_inet_addr */
|
||||
|
||||
/* Data options */
|
||||
enum ipset_opt {
|
||||
IPSET_OPT_NONE = 0,
|
||||
/* Common ones */
|
||||
IPSET_SETNAME,
|
||||
IPSET_OPT_TYPENAME,
|
||||
IPSET_OPT_FAMILY,
|
||||
/* CADT options */
|
||||
IPSET_OPT_IP,
|
||||
IPSET_OPT_IP_FROM = IPSET_OPT_IP,
|
||||
IPSET_OPT_IP_TO,
|
||||
IPSET_OPT_CIDR,
|
||||
IPSET_OPT_PORT,
|
||||
IPSET_OPT_PORT_FROM = IPSET_OPT_PORT,
|
||||
IPSET_OPT_PORT_TO,
|
||||
IPSET_OPT_TIMEOUT,
|
||||
/* Create-specific options */
|
||||
IPSET_OPT_GC,
|
||||
IPSET_OPT_HASHSIZE,
|
||||
IPSET_OPT_MAXELEM,
|
||||
IPSET_OPT_NETMASK,
|
||||
IPSET_OPT_PROBES,
|
||||
IPSET_OPT_RESIZE,
|
||||
IPSET_OPT_SIZE,
|
||||
/* Create-specific options, filled out by the kernel */
|
||||
IPSET_OPT_ELEMENTS,
|
||||
IPSET_OPT_REFERENCES,
|
||||
IPSET_OPT_MEMSIZE,
|
||||
/* ADT-specific options */
|
||||
IPSET_OPT_ETHER,
|
||||
IPSET_OPT_NAME,
|
||||
IPSET_OPT_NAMEREF,
|
||||
IPSET_OPT_IP2,
|
||||
IPSET_OPT_CIDR2,
|
||||
IPSET_OPT_PROTO,
|
||||
/* Swap/rename to */
|
||||
IPSET_OPT_SETNAME2,
|
||||
/* Flags */
|
||||
IPSET_OPT_EXIST,
|
||||
IPSET_OPT_BEFORE,
|
||||
/* Internal options */
|
||||
IPSET_OPT_FLAGS = 48, /* IPSET_FLAG_EXIST| */
|
||||
IPSET_OPT_CADT_FLAGS, /* IPSET_FLAG_BEFORE| */
|
||||
IPSET_OPT_ELEM,
|
||||
IPSET_OPT_TYPE,
|
||||
IPSET_OPT_LINENO,
|
||||
IPSET_OPT_REVISION,
|
||||
IPSET_OPT_REVISION_MIN,
|
||||
IPSET_OPT_MAX,
|
||||
};
|
||||
|
||||
#define IPSET_FLAG(opt) (1LL << (opt))
|
||||
#define IPSET_FLAGS_ALL (~0LL)
|
||||
|
||||
#define IPSET_CREATE_FLAGS \
|
||||
( IPSET_FLAG(IPSET_OPT_FAMILY) \
|
||||
| IPSET_FLAG(IPSET_OPT_TYPENAME)\
|
||||
| IPSET_FLAG(IPSET_OPT_TYPE) \
|
||||
| IPSET_FLAG(IPSET_OPT_IP) \
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO) \
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR) \
|
||||
| IPSET_FLAG(IPSET_OPT_PORT) \
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO) \
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT) \
|
||||
| IPSET_FLAG(IPSET_OPT_GC) \
|
||||
| IPSET_FLAG(IPSET_OPT_HASHSIZE)\
|
||||
| IPSET_FLAG(IPSET_OPT_MAXELEM) \
|
||||
| IPSET_FLAG(IPSET_OPT_NETMASK) \
|
||||
| IPSET_FLAG(IPSET_OPT_PROBES) \
|
||||
| IPSET_FLAG(IPSET_OPT_RESIZE) \
|
||||
| IPSET_FLAG(IPSET_OPT_SIZE))
|
||||
|
||||
#define IPSET_ADT_FLAGS \
|
||||
( IPSET_FLAG(IPSET_OPT_IP) \
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO) \
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR) \
|
||||
| IPSET_FLAG(IPSET_OPT_PORT) \
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO) \
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT) \
|
||||
| IPSET_FLAG(IPSET_OPT_ETHER) \
|
||||
| IPSET_FLAG(IPSET_OPT_NAME) \
|
||||
| IPSET_FLAG(IPSET_OPT_NAMEREF) \
|
||||
| IPSET_FLAG(IPSET_OPT_IP2) \
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR2) \
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO) \
|
||||
| IPSET_FLAG(IPSET_OPT_CADT_FLAGS)\
|
||||
| IPSET_FLAG(IPSET_OPT_BEFORE))
|
||||
|
||||
struct ipset_data;
|
||||
|
||||
extern void ipset_strlcpy(char *dst, const char *src, size_t len);
|
||||
extern bool ipset_data_flags_test(const struct ipset_data *data,
|
||||
uint64_t flags);
|
||||
extern void ipset_data_flags_set(struct ipset_data *data, uint64_t flags);
|
||||
extern void ipset_data_flags_unset(struct ipset_data *data, uint64_t flags);
|
||||
extern bool ipset_data_ignored(struct ipset_data *data, enum ipset_opt opt);
|
||||
|
||||
extern int ipset_data_set(struct ipset_data *data, enum ipset_opt opt,
|
||||
const void *value);
|
||||
extern const void * ipset_data_get(const struct ipset_data *data,
|
||||
enum ipset_opt opt);
|
||||
|
||||
static inline bool
|
||||
ipset_data_test(const struct ipset_data *data, enum ipset_opt opt)
|
||||
{
|
||||
return ipset_data_flags_test(data, IPSET_FLAG(opt));
|
||||
}
|
||||
|
||||
/* Shortcuts */
|
||||
extern const char * ipset_data_setname(const struct ipset_data *data);
|
||||
extern uint8_t ipset_data_family(const struct ipset_data *data);
|
||||
extern uint8_t ipset_data_cidr(const struct ipset_data *data);
|
||||
extern uint64_t ipset_data_flags(const struct ipset_data *data);
|
||||
|
||||
extern void ipset_data_reset(struct ipset_data *data);
|
||||
extern struct ipset_data * ipset_data_init(void);
|
||||
extern void ipset_data_fini(struct ipset_data *data);
|
||||
|
||||
extern size_t ipset_data_sizeof(enum ipset_opt opt, uint8_t family);
|
||||
|
||||
#endif /* LIBIPSET_DATA_H */
|
||||
33
extensions/ipset-5/include/libipset/debug.h
Normal file
33
extensions/ipset-5/include/libipset/debug.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_DEBUG_H
|
||||
#define LIBIPSET_DEBUG_H
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/netlink.h>
|
||||
#define D(fmt, args...) \
|
||||
fprintf(stderr, "%s: %s: " fmt "\n", __FILE__, __FUNCTION__ , ## args)
|
||||
#define IF_D(test, fmt, args...) \
|
||||
if (test) \
|
||||
D(fmt , ## args)
|
||||
|
||||
static inline void
|
||||
dump_nla(struct nlattr *nla[], int maxlen)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < maxlen; i++)
|
||||
D("nla[%u] does%s exist", i, nla[i] ? "" : " NOT");
|
||||
}
|
||||
#else
|
||||
#define D(fmt, args...)
|
||||
#define IF_D(test, fmt, args...)
|
||||
#define dump_nla(nla, maxlen)
|
||||
#endif
|
||||
|
||||
#endif /* LIBIPSET_DEBUG_H */
|
||||
24
extensions/ipset-5/include/libipset/errcode.h
Normal file
24
extensions/ipset-5/include/libipset/errcode.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/* Copyright 2007-2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_ERRCODE_H
|
||||
#define LIBIPSET_ERRCODE_H
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
|
||||
struct ipset_session;
|
||||
|
||||
/* Kernel error code to message table */
|
||||
struct ipset_errcode_table {
|
||||
int errcode; /* error code returned by the kernel */
|
||||
enum ipset_cmd cmd; /* issued command */
|
||||
const char *message; /* error message the code translated to */
|
||||
};
|
||||
|
||||
extern int ipset_errcode(struct ipset_session *session, enum ipset_cmd cmd,
|
||||
int errcode);
|
||||
|
||||
#endif /* LIBIPSET_ERRCODE_H */
|
||||
16
extensions/ipset-5/include/libipset/icmp.h
Normal file
16
extensions/ipset-5/include/libipset/icmp.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_ICMP_H
|
||||
#define LIBIPSET_ICMP_H
|
||||
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
|
||||
extern const char * id_to_icmp(uint8_t id);
|
||||
extern const char * icmp_to_name(uint8_t type, uint8_t code);
|
||||
extern int name_to_icmp(const char *str, uint16_t *typecode);
|
||||
|
||||
#endif /* LIBIPSET_ICMP_H */
|
||||
16
extensions/ipset-5/include/libipset/icmpv6.h
Normal file
16
extensions/ipset-5/include/libipset/icmpv6.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_ICMPV6_H
|
||||
#define LIBIPSET_ICMPV6_H
|
||||
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
|
||||
extern const char * id_to_icmpv6(uint8_t id);
|
||||
extern const char * icmpv6_to_name(uint8_t type, uint8_t code);
|
||||
extern int name_to_icmpv6(const char *str, uint16_t *typecode);
|
||||
|
||||
#endif /* LIBIPSET_ICMPV6_H */
|
||||
163
extensions/ipset-5/include/libipset/linux_ip_set.h
Normal file
163
extensions/ipset-5/include/libipset/linux_ip_set.h
Normal file
@@ -0,0 +1,163 @@
|
||||
#ifndef _IP_SET_H
|
||||
#define _IP_SET_H
|
||||
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* The protocol version */
|
||||
#define IPSET_PROTOCOL 5
|
||||
|
||||
/* The max length of strings including NUL: set and type identifiers */
|
||||
#define IPSET_MAXNAMELEN 32
|
||||
|
||||
/* Message types and commands */
|
||||
enum ipset_cmd {
|
||||
IPSET_CMD_NONE,
|
||||
IPSET_CMD_PROTOCOL, /* 1: Return protocol version */
|
||||
IPSET_CMD_CREATE, /* 2: Create a new (empty) set */
|
||||
IPSET_CMD_DESTROY, /* 3: Destroy a (empty) set */
|
||||
IPSET_CMD_FLUSH, /* 4: Remove all elements from a set */
|
||||
IPSET_CMD_RENAME, /* 5: Rename a set */
|
||||
IPSET_CMD_SWAP, /* 6: Swap two sets */
|
||||
IPSET_CMD_LIST, /* 7: List sets */
|
||||
IPSET_CMD_SAVE, /* 8: Save sets */
|
||||
IPSET_CMD_ADD, /* 9: Add an element to a set */
|
||||
IPSET_CMD_DEL, /* 10: Delete an element from a set */
|
||||
IPSET_CMD_TEST, /* 11: Test an element in a set */
|
||||
IPSET_CMD_HEADER, /* 12: Get set header data only */
|
||||
IPSET_CMD_TYPE, /* 13: Get set type */
|
||||
IPSET_MSG_MAX, /* Netlink message commands */
|
||||
|
||||
/* Commands in userspace: */
|
||||
IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */
|
||||
IPSET_CMD_HELP, /* 15: Get help */
|
||||
IPSET_CMD_VERSION, /* 16: Get program version */
|
||||
IPSET_CMD_QUIT, /* 17: Quit from interactive mode */
|
||||
|
||||
IPSET_CMD_MAX,
|
||||
|
||||
IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
|
||||
};
|
||||
|
||||
/* Attributes at command level */
|
||||
enum {
|
||||
IPSET_ATTR_UNSPEC,
|
||||
IPSET_ATTR_PROTOCOL, /* 1: Protocol version */
|
||||
IPSET_ATTR_SETNAME, /* 2: Name of the set */
|
||||
IPSET_ATTR_TYPENAME, /* 3: Typename */
|
||||
IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */
|
||||
IPSET_ATTR_REVISION, /* 4: Settype revision */
|
||||
IPSET_ATTR_FAMILY, /* 5: Settype family */
|
||||
IPSET_ATTR_FLAGS, /* 6: Flags at command level */
|
||||
IPSET_ATTR_DATA, /* 7: Nested attributes */
|
||||
IPSET_ATTR_ADT, /* 8: Multiple data containers */
|
||||
IPSET_ATTR_LINENO, /* 9: Restore lineno */
|
||||
IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
|
||||
IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
|
||||
__IPSET_ATTR_CMD_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1)
|
||||
|
||||
/* CADT specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
|
||||
IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
|
||||
IPSET_ATTR_IP_TO, /* 2 */
|
||||
IPSET_ATTR_CIDR, /* 3 */
|
||||
IPSET_ATTR_PORT, /* 4 */
|
||||
IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
|
||||
IPSET_ATTR_PORT_TO, /* 5 */
|
||||
IPSET_ATTR_TIMEOUT, /* 6 */
|
||||
IPSET_ATTR_PROTO, /* 7 */
|
||||
IPSET_ATTR_CADT_FLAGS, /* 8 */
|
||||
IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */
|
||||
/* Reserve empty slots */
|
||||
IPSET_ATTR_CADT_MAX = 16,
|
||||
/* Create-only specific attributes */
|
||||
IPSET_ATTR_GC,
|
||||
IPSET_ATTR_HASHSIZE,
|
||||
IPSET_ATTR_MAXELEM,
|
||||
IPSET_ATTR_NETMASK,
|
||||
IPSET_ATTR_PROBES,
|
||||
IPSET_ATTR_RESIZE,
|
||||
IPSET_ATTR_SIZE,
|
||||
/* Kernel-only */
|
||||
IPSET_ATTR_ELEMENTS,
|
||||
IPSET_ATTR_REFERENCES,
|
||||
IPSET_ATTR_MEMSIZE,
|
||||
|
||||
__IPSET_ATTR_CREATE_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_CREATE_MAX (__IPSET_ATTR_CREATE_MAX - 1)
|
||||
|
||||
/* ADT specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1,
|
||||
IPSET_ATTR_NAME,
|
||||
IPSET_ATTR_NAMEREF,
|
||||
IPSET_ATTR_IP2,
|
||||
IPSET_ATTR_CIDR2,
|
||||
__IPSET_ATTR_ADT_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
|
||||
|
||||
/* IP specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1,
|
||||
IPSET_ATTR_IPADDR_IPV6,
|
||||
__IPSET_ATTR_IPADDR_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_IPADDR_MAX (__IPSET_ATTR_IPADDR_MAX - 1)
|
||||
|
||||
/* Error codes */
|
||||
enum ipset_errno {
|
||||
IPSET_ERR_PRIVATE = 128,
|
||||
IPSET_ERR_PROTOCOL,
|
||||
IPSET_ERR_FIND_TYPE,
|
||||
IPSET_ERR_MAX_SETS,
|
||||
IPSET_ERR_BUSY,
|
||||
IPSET_ERR_EXIST_SETNAME2,
|
||||
IPSET_ERR_TYPE_MISMATCH,
|
||||
IPSET_ERR_EXIST,
|
||||
IPSET_ERR_INVALID_CIDR,
|
||||
IPSET_ERR_INVALID_NETMASK,
|
||||
IPSET_ERR_INVALID_FAMILY,
|
||||
IPSET_ERR_TIMEOUT,
|
||||
IPSET_ERR_REFERENCED,
|
||||
IPSET_ERR_IPADDR_IPV4,
|
||||
IPSET_ERR_IPADDR_IPV6,
|
||||
|
||||
/* Type specific error codes */
|
||||
IPSET_ERR_TYPE_SPECIFIC = 160,
|
||||
};
|
||||
|
||||
/* Flags at command level */
|
||||
enum ipset_cmd_flags {
|
||||
IPSET_FLAG_BIT_EXIST = 0,
|
||||
IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST),
|
||||
};
|
||||
|
||||
/* Flags at CADT attribute level */
|
||||
enum ipset_cadt_flags {
|
||||
IPSET_FLAG_BIT_BEFORE = 0,
|
||||
IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE),
|
||||
};
|
||||
|
||||
/* Commands with settype-specific attributes */
|
||||
enum ipset_adt {
|
||||
IPSET_ADD,
|
||||
IPSET_DEL,
|
||||
IPSET_TEST,
|
||||
IPSET_ADT_MAX,
|
||||
IPSET_CREATE = IPSET_ADT_MAX,
|
||||
IPSET_CADT_MAX,
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_H */
|
||||
12
extensions/ipset-5/include/libipset/linux_ip_set_bitmap.h
Normal file
12
extensions/ipset-5/include/libipset/linux_ip_set_bitmap.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef __IP_SET_BITMAP_H
|
||||
#define __IP_SET_BITMAP_H
|
||||
|
||||
/* Bitmap type specific error codes */
|
||||
enum {
|
||||
/* The element is out of the range of the set */
|
||||
IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* The range exceeds the size limit of the set type */
|
||||
IPSET_ERR_BITMAP_RANGE_SIZE,
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_BITMAP_H */
|
||||
16
extensions/ipset-5/include/libipset/linux_ip_set_hash.h
Normal file
16
extensions/ipset-5/include/libipset/linux_ip_set_hash.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef __IP_SET_HASH_H
|
||||
#define __IP_SET_HASH_H
|
||||
|
||||
/* Hash type specific error codes */
|
||||
enum {
|
||||
/* Hash is full */
|
||||
IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* Null-valued element */
|
||||
IPSET_ERR_HASH_ELEM,
|
||||
/* Invalid protocol */
|
||||
IPSET_ERR_INVALID_PROTO,
|
||||
/* Protocol missing but must be specified */
|
||||
IPSET_ERR_MISSING_PROTO,
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_HASH_H */
|
||||
20
extensions/ipset-5/include/libipset/linux_ip_set_list.h
Normal file
20
extensions/ipset-5/include/libipset/linux_ip_set_list.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __IP_SET_LIST_H
|
||||
#define __IP_SET_LIST_H
|
||||
|
||||
/* List type specific error codes */
|
||||
enum {
|
||||
/* Set name to be added/deleted/tested does not exist. */
|
||||
IPSET_ERR_NAME = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* list:set type is not permitted to add */
|
||||
IPSET_ERR_LOOP,
|
||||
/* Missing reference set */
|
||||
IPSET_ERR_BEFORE,
|
||||
/* Reference set does not exist */
|
||||
IPSET_ERR_NAMEREF,
|
||||
/* Set is full */
|
||||
IPSET_ERR_LIST_FULL,
|
||||
/* Reference set is not added to the set */
|
||||
IPSET_ERR_REF_EXIST,
|
||||
};
|
||||
|
||||
#endif /* __IP_SET_LIST_H */
|
||||
29
extensions/ipset-5/include/libipset/mnl.h
Normal file
29
extensions/ipset-5/include/libipset/mnl.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_MNL_H
|
||||
#define LIBIPSET_MNL_H
|
||||
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
#include <libmnl/libmnl.h> /* libmnl backend */
|
||||
|
||||
#include <libipset/transport.h> /* struct ipset_transport */
|
||||
|
||||
#ifndef NFNETLINK_V0
|
||||
#define NFNETLINK_V0 0
|
||||
|
||||
struct nfgenmsg {
|
||||
uint8_t nfgen_family;
|
||||
uint8_t version;
|
||||
uint16_t res_id;
|
||||
};
|
||||
#endif
|
||||
|
||||
extern int ipset_get_nlmsg_type(const struct nlmsghdr *nlh);
|
||||
|
||||
extern const struct ipset_transport ipset_mnl_transport;
|
||||
|
||||
#endif /* LIBIPSET_MNL_H */
|
||||
22
extensions/ipset-5/include/libipset/nf_inet_addr.h
Normal file
22
extensions/ipset-5/include/libipset/nf_inet_addr.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_NF_INET_ADDR_H
|
||||
#define LIBIPSET_NF_INET_ADDR_H
|
||||
|
||||
#include <stdint.h> /* uint32_t */
|
||||
#include <netinet/in.h> /* struct in[6]_addr */
|
||||
|
||||
/* The structure to hold IP addresses, same as in linux/netfilter.h */
|
||||
union nf_inet_addr {
|
||||
uint32_t all[4];
|
||||
uint32_t ip;
|
||||
uint32_t ip6[4];
|
||||
struct in_addr in;
|
||||
struct in6_addr in6;
|
||||
};
|
||||
|
||||
#endif /* LIBIPSET_NF_INET_ADDR_H */
|
||||
96
extensions/ipset-5/include/libipset/parse.h
Normal file
96
extensions/ipset-5/include/libipset/parse.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_PARSE_H
|
||||
#define LIBIPSET_PARSE_H
|
||||
|
||||
#include <libipset/data.h> /* enum ipset_opt */
|
||||
|
||||
/* For parsing/printing data */
|
||||
#define IPSET_CIDR_SEPARATOR "/"
|
||||
#define IPSET_RANGE_SEPARATOR "-"
|
||||
#define IPSET_ELEM_SEPARATOR ","
|
||||
#define IPSET_NAME_SEPARATOR ","
|
||||
#define IPSET_PROTO_SEPARATOR ":"
|
||||
|
||||
struct ipset_session;
|
||||
|
||||
typedef int (*ipset_parsefn)(struct ipset_session *s,
|
||||
enum ipset_opt opt, const char *str);
|
||||
|
||||
extern int ipset_parse_ether(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str,
|
||||
const char *proto);
|
||||
extern int ipset_parse_tcpudp_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str,
|
||||
const char *proto);
|
||||
extern int ipset_parse_tcp_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_single_tcp_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_proto(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_icmp(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_icmpv6(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_proto_port(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_family(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_ip(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_single_ip(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_net(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_range(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_netrange(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_iprange(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_ipnet(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_ip4_single6(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_name(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_before(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_after(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_setname(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_uint32(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_uint8(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_netmask(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_flag(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_typename(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_output(struct ipset_session *session,
|
||||
int opt, const char *str);
|
||||
extern int ipset_parse_ignored(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_elem(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_call_parser(struct ipset_session *session,
|
||||
ipset_parsefn parse, const char *optstr,
|
||||
enum ipset_opt optional, const char *str);
|
||||
|
||||
/* Compatibility parser functions */
|
||||
extern int ipset_parse_iptimeout(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
extern int ipset_parse_name_compat(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str);
|
||||
|
||||
#endif /* LIBIPSET_PARSE_H */
|
||||
157
extensions/ipset-5/include/libipset/pfxlen.h
Normal file
157
extensions/ipset-5/include/libipset/pfxlen.h
Normal file
@@ -0,0 +1,157 @@
|
||||
#ifndef _NET_PFXLEN_H
|
||||
#define _NET_PFXLEN_H 1
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#ifdef HAVE_PFXLEN_H
|
||||
#include <linux/netfilter/pfxlen.h>
|
||||
#else
|
||||
|
||||
#include <libipset/nf_inet_addr.h> /* union nf_inet_addr */
|
||||
|
||||
#define E(a, b, c, d) \
|
||||
{.ip6 = { \
|
||||
__constant_htonl(a), __constant_htonl(b), \
|
||||
__constant_htonl(c), __constant_htonl(d), \
|
||||
}}
|
||||
|
||||
/*
|
||||
* This table works for both IPv4 and IPv6;
|
||||
* just use prefixlen_netmask_map[prefixlength].ip.
|
||||
*/
|
||||
const union nf_inet_addr prefixlen_netmask_map[] = {
|
||||
E(0x00000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0x80000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xC0000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xE0000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xF0000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xF8000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFC000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFE000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFF000000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFF800000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE),
|
||||
E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
|
||||
};
|
||||
#endif /* !HAVE_PFXLEN_H */
|
||||
|
||||
#define PFXLEN(n) prefixlen_netmask_map[n].ip
|
||||
#define PFXLEN6(n) prefixlen_netmask_map[n].ip6
|
||||
|
||||
#endif
|
||||
65
extensions/ipset-5/include/libipset/print.h
Normal file
65
extensions/ipset-5/include/libipset/print.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_PRINT_H
|
||||
#define LIBIPSET_PRINT_H
|
||||
|
||||
#include <libipset/data.h> /* enum ipset_opt */
|
||||
|
||||
typedef int (*ipset_printfn)(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
|
||||
extern int ipset_print_ether(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_family(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_type(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_ip(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_ipaddr(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_number(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_name(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_port(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_proto(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_icmp(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_icmpv6(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_proto_port(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_flag(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
extern int ipset_print_elem(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
|
||||
#define ipset_print_portnum ipset_print_number
|
||||
|
||||
extern int ipset_print_data(char *buf, unsigned int len,
|
||||
const struct ipset_data *data,
|
||||
enum ipset_opt opt, uint8_t env);
|
||||
|
||||
#endif /* LIBIPSET_PRINT_H */
|
||||
94
extensions/ipset-5/include/libipset/session.h
Normal file
94
extensions/ipset-5/include/libipset/session.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_SESSION_H
|
||||
#define LIBIPSET_SESSION_H
|
||||
|
||||
#include <stdbool.h> /* bool */
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
|
||||
/* Report and output buffer sizes */
|
||||
#define IPSET_ERRORBUFLEN 1024
|
||||
#define IPSET_OUTBUFLEN 8192
|
||||
|
||||
struct ipset_session;
|
||||
struct ipset_data;
|
||||
struct ipset_handle;
|
||||
|
||||
extern struct ipset_data * ipset_session_data(const struct ipset_session *session);
|
||||
extern struct ipset_handle * ipset_session_handle(const struct ipset_session *session);
|
||||
extern const struct ipset_type * ipset_saved_type(const struct ipset_session *session);
|
||||
|
||||
enum ipset_err_type {
|
||||
IPSET_ERROR,
|
||||
IPSET_WARNING,
|
||||
};
|
||||
|
||||
extern int ipset_session_report(struct ipset_session *session,
|
||||
enum ipset_err_type type,
|
||||
const char *fmt, ...);
|
||||
|
||||
#define ipset_err(session, fmt, args...) \
|
||||
ipset_session_report(session, IPSET_ERROR, fmt , ## args)
|
||||
|
||||
#define ipset_warn(session, fmt, args...) \
|
||||
ipset_session_report(session, IPSET_WARNING, fmt , ## args)
|
||||
|
||||
#define ipset_errptr(session, fmt, args...) ({ \
|
||||
ipset_session_report(session, IPSET_ERROR, fmt , ## args); \
|
||||
NULL; \
|
||||
})
|
||||
|
||||
extern void ipset_session_report_reset(struct ipset_session *session);
|
||||
extern const char * ipset_session_error(const struct ipset_session *session);
|
||||
extern const char * ipset_session_warning(const struct ipset_session *session);
|
||||
|
||||
#define ipset_session_data_set(session, opt, value) \
|
||||
ipset_data_set(ipset_session_data(session), opt, value)
|
||||
#define ipset_session_data_get(session, opt) \
|
||||
ipset_data_get(ipset_session_data(session), opt)
|
||||
|
||||
/* Environment option flags */
|
||||
enum ipset_envopt {
|
||||
IPSET_ENV_BIT_SORTED = 0,
|
||||
IPSET_ENV_SORTED = (1 << IPSET_ENV_BIT_SORTED),
|
||||
IPSET_ENV_BIT_QUIET = 1,
|
||||
IPSET_ENV_QUIET = (1 << IPSET_ENV_BIT_QUIET),
|
||||
IPSET_ENV_BIT_RESOLVE = 2,
|
||||
IPSET_ENV_RESOLVE = (1 << IPSET_ENV_BIT_RESOLVE),
|
||||
IPSET_ENV_BIT_EXIST = 3,
|
||||
IPSET_ENV_EXIST = (1 << IPSET_ENV_BIT_EXIST),
|
||||
};
|
||||
|
||||
extern int ipset_envopt_parse(struct ipset_session *session,
|
||||
int env, const char *str);
|
||||
extern bool ipset_envopt_test(struct ipset_session *session,
|
||||
enum ipset_envopt env);
|
||||
|
||||
enum ipset_output_mode {
|
||||
IPSET_LIST_NONE,
|
||||
IPSET_LIST_PLAIN,
|
||||
IPSET_LIST_SAVE,
|
||||
IPSET_LIST_XML,
|
||||
};
|
||||
|
||||
extern int ipset_session_output(struct ipset_session *session,
|
||||
enum ipset_output_mode mode);
|
||||
|
||||
extern int ipset_commit(struct ipset_session *session);
|
||||
extern int ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd,
|
||||
uint32_t lineno);
|
||||
|
||||
typedef int (*ipset_outfn)(const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
extern struct ipset_session * ipset_session_init(ipset_outfn outfn);
|
||||
extern int ipset_session_fini(struct ipset_session *session);
|
||||
|
||||
#endif /* LIBIPSET_SESSION_H */
|
||||
27
extensions/ipset-5/include/libipset/transport.h
Normal file
27
extensions/ipset-5/include/libipset/transport.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_TRANSPORT_H
|
||||
#define LIBIPSET_TRANSPORT_H
|
||||
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
#include <linux/netlink.h> /* struct nlmsghdr */
|
||||
|
||||
#include <libmnl/libmnl.h> /* mnl_cb_t */
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
|
||||
struct ipset_handle;
|
||||
|
||||
struct ipset_transport {
|
||||
struct ipset_handle * (*init)(mnl_cb_t *cb_ctl, void *data);
|
||||
int (*fini)(struct ipset_handle *handle);
|
||||
void (*fill_hdr)(struct ipset_handle *handle, enum ipset_cmd cmd,
|
||||
void *buffer, size_t len, uint8_t envflags);
|
||||
int (*query)(struct ipset_handle *handle, void *buffer, size_t len);
|
||||
};
|
||||
|
||||
#endif /* LIBIPSET_TRANSPORT_H */
|
||||
110
extensions/ipset-5/include/libipset/types.h
Normal file
110
extensions/ipset-5/include/libipset/types.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_TYPES_H
|
||||
#define LIBIPSET_TYPES_H
|
||||
|
||||
#include <stddef.h> /* NULL */
|
||||
#include <stdint.h> /* uintxx_t */
|
||||
|
||||
#include <libipset/data.h> /* enum ipset_opt */
|
||||
#include <libipset/parse.h> /* ipset_parsefn */
|
||||
#include <libipset/print.h> /* ipset_printfn */
|
||||
#include <libipset/linux_ip_set.h> /* IPSET_MAXNAMELEN */
|
||||
|
||||
#define AF_INET46 255
|
||||
|
||||
/* Family rules:
|
||||
* - AF_UNSPEC: type is family-neutral
|
||||
* - AF_INET: type supports IPv4 only
|
||||
* - AF_INET6: type supports IPv6 only
|
||||
* - AF_INET46: type supports both IPv4 and IPv6
|
||||
*/
|
||||
|
||||
/* Set dimensions */
|
||||
enum {
|
||||
IPSET_DIM_ONE, /* foo */
|
||||
IPSET_DIM_TWO, /* foo,bar */
|
||||
IPSET_DIM_THREE, /* foo,bar,fie */
|
||||
IPSET_DIM_MAX,
|
||||
};
|
||||
|
||||
/* Parser options */
|
||||
enum {
|
||||
IPSET_NO_ARG = -1,
|
||||
IPSET_OPTIONAL_ARG,
|
||||
IPSET_MANDATORY_ARG,
|
||||
IPSET_MANDATORY_ARG2,
|
||||
};
|
||||
|
||||
struct ipset_session;
|
||||
|
||||
/* Parse and print type-specific arguments */
|
||||
struct ipset_arg {
|
||||
const char *name[2]; /* option names */
|
||||
int has_arg; /* mandatory/optional/no arg */
|
||||
enum ipset_opt opt; /* argumentum type */
|
||||
ipset_parsefn parse; /* parser function */
|
||||
ipset_printfn print; /* printing function */
|
||||
};
|
||||
|
||||
/* Type check against the kernel */
|
||||
enum {
|
||||
IPSET_KERNEL_MISMATCH = -1,
|
||||
IPSET_KERNEL_CHECK_NEEDED,
|
||||
IPSET_KERNEL_OK,
|
||||
};
|
||||
|
||||
/* How element parts are parsed */
|
||||
struct ipset_elem {
|
||||
ipset_parsefn parse; /* elem parser function */
|
||||
ipset_printfn print; /* elem print function */
|
||||
enum ipset_opt opt; /* elem option */
|
||||
};
|
||||
|
||||
/* The set types in userspace
|
||||
* we could collapse 'args' and 'mandatory' to two-element lists
|
||||
* but for the readability the full list is supported.
|
||||
*/
|
||||
struct ipset_type {
|
||||
char name[IPSET_MAXNAMELEN]; /* type name */
|
||||
uint8_t revision; /* revision number */
|
||||
uint8_t family; /* supported family */
|
||||
uint8_t dimension; /* elem dimension */
|
||||
int8_t kernel_check; /* kernel check */
|
||||
bool last_elem_optional; /* last element optional */
|
||||
struct ipset_elem elem[IPSET_DIM_MAX]; /* parse elem */
|
||||
ipset_parsefn compat_parse_elem; /* compatibility parser */
|
||||
const struct ipset_arg *args[IPSET_CADT_MAX]; /* create/ADT args besides elem */
|
||||
uint64_t mandatory[IPSET_CADT_MAX]; /* create/ADT mandatory flags */
|
||||
uint64_t full[IPSET_CADT_MAX]; /* full args flags */
|
||||
const char *usage; /* terse usage */
|
||||
void (*usagefn)(void); /* additional usage */
|
||||
|
||||
struct ipset_type *next;
|
||||
const char *alias[]; /* name alias(es) */
|
||||
};
|
||||
|
||||
extern int ipset_cache_add(const char *name, const struct ipset_type *type,
|
||||
uint8_t family);
|
||||
extern int ipset_cache_del(const char *name);
|
||||
extern int ipset_cache_rename(const char *from, const char *to);
|
||||
extern int ipset_cache_swap(const char *from, const char *to);
|
||||
|
||||
extern int ipset_cache_init(void);
|
||||
extern void ipset_cache_fini(void);
|
||||
|
||||
extern const struct ipset_type * ipset_type_get(struct ipset_session *session,
|
||||
enum ipset_cmd cmd);
|
||||
extern const struct ipset_type * ipset_type_check(struct ipset_session *session);
|
||||
|
||||
extern int ipset_type_add(struct ipset_type *type);
|
||||
extern const struct ipset_type * ipset_types(void);
|
||||
extern const char * ipset_typename_resolve(const char *str);
|
||||
extern bool ipset_match_typename(const char *str,
|
||||
const struct ipset_type *t);
|
||||
|
||||
#endif /* LIBIPSET_TYPES_H */
|
||||
44
extensions/ipset-5/include/libipset/ui.h
Normal file
44
extensions/ipset-5/include/libipset/ui.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_UI_H
|
||||
#define LIBIPSET_UI_H
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
|
||||
/* Commands in userspace */
|
||||
struct ipset_commands {
|
||||
enum ipset_cmd cmd;
|
||||
int has_arg;
|
||||
const char *name[2];
|
||||
const char *help;
|
||||
};
|
||||
|
||||
extern const struct ipset_commands ipset_commands[];
|
||||
|
||||
struct ipset_session;
|
||||
struct ipset_data;
|
||||
|
||||
/* Environment options */
|
||||
struct ipset_envopts {
|
||||
int flag;
|
||||
int has_arg;
|
||||
const char *name[2];
|
||||
const char *help;
|
||||
int (*parse)(struct ipset_session *s, int flag, const char *str);
|
||||
int (*print)(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, int flag, uint8_t env);
|
||||
};
|
||||
|
||||
extern const struct ipset_envopts ipset_envopts[];
|
||||
|
||||
extern bool ipset_match_cmd(const char *arg, const char * const name[]);
|
||||
extern bool ipset_match_option(const char *arg, const char * const name[]);
|
||||
extern bool ipset_match_envopt(const char *arg, const char * const name[]);
|
||||
extern void ipset_shift_argv(int *argc, char *argv[], int from);
|
||||
extern void ipset_port_usage(void);
|
||||
|
||||
#endif /* LIBIPSET_UI_H */
|
||||
45
extensions/ipset-5/include/libipset/utils.h
Normal file
45
extensions/ipset-5/include/libipset/utils.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#ifndef LIBIPSET_UTILS_H
|
||||
#define LIBIPSET_UTILS_H
|
||||
|
||||
#include <string.h> /* strcmp */
|
||||
#include <netinet/in.h> /* struct in[6]_addr */
|
||||
|
||||
/* String equality tests */
|
||||
#define STREQ(a,b) (strcmp(a,b) == 0)
|
||||
#define STRNEQ(a,b,n) (strncmp(a,b,n) == 0)
|
||||
#define STRCASEQ(a,b) (strcasecmp(a,b) == 0)
|
||||
#define STRNCASEQ(a,b,n) (strncasecmp(a,b,n) == 0)
|
||||
|
||||
/* Stringify tokens */
|
||||
#define _STR(c) #c
|
||||
#define STR(c) _STR(c)
|
||||
|
||||
/* Min/max */
|
||||
#define MIN(a, b) (a < b ? a : b)
|
||||
#define MAX(a, b) (a > b ? a : b)
|
||||
|
||||
#define UNUSED __attribute__ ((unused))
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
in4cpy(struct in_addr *dest, const struct in_addr *src)
|
||||
{
|
||||
dest->s_addr = src->s_addr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
in6cpy(struct in6_addr *dest, const struct in6_addr *src)
|
||||
{
|
||||
memcpy(dest, src, sizeof(struct in6_addr));
|
||||
}
|
||||
|
||||
#endif /* LIBIPSET_UTILS_H */
|
||||
1863
extensions/ipset-5/ip_set.c
Normal file
1863
extensions/ipset-5/ip_set.c
Normal file
File diff suppressed because it is too large
Load Diff
530
extensions/ipset-5/ip_set.h
Normal file
530
extensions/ipset-5/ip_set.h
Normal file
@@ -0,0 +1,530 @@
|
||||
#ifndef _IP_SET_H
|
||||
#define _IP_SET_H
|
||||
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* The protocol version */
|
||||
#define IPSET_PROTOCOL 5
|
||||
|
||||
/* The max length of strings including NUL: set and type identifiers */
|
||||
#define IPSET_MAXNAMELEN 32
|
||||
|
||||
/* Message types and commands */
|
||||
enum ipset_cmd {
|
||||
IPSET_CMD_NONE,
|
||||
IPSET_CMD_PROTOCOL, /* 1: Return protocol version */
|
||||
IPSET_CMD_CREATE, /* 2: Create a new (empty) set */
|
||||
IPSET_CMD_DESTROY, /* 3: Destroy a (empty) set */
|
||||
IPSET_CMD_FLUSH, /* 4: Remove all elements from a set */
|
||||
IPSET_CMD_RENAME, /* 5: Rename a set */
|
||||
IPSET_CMD_SWAP, /* 6: Swap two sets */
|
||||
IPSET_CMD_LIST, /* 7: List sets */
|
||||
IPSET_CMD_SAVE, /* 8: Save sets */
|
||||
IPSET_CMD_ADD, /* 9: Add an element to a set */
|
||||
IPSET_CMD_DEL, /* 10: Delete an element from a set */
|
||||
IPSET_CMD_TEST, /* 11: Test an element in a set */
|
||||
IPSET_CMD_HEADER, /* 12: Get set header data only */
|
||||
IPSET_CMD_TYPE, /* 13: Get set type */
|
||||
IPSET_MSG_MAX, /* Netlink message commands */
|
||||
|
||||
/* Commands in userspace: */
|
||||
IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */
|
||||
IPSET_CMD_HELP, /* 15: Get help */
|
||||
IPSET_CMD_VERSION, /* 16: Get program version */
|
||||
IPSET_CMD_QUIT, /* 17: Quit from interactive mode */
|
||||
|
||||
IPSET_CMD_MAX,
|
||||
|
||||
IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
|
||||
};
|
||||
|
||||
/* Attributes at command level */
|
||||
enum {
|
||||
IPSET_ATTR_UNSPEC,
|
||||
IPSET_ATTR_PROTOCOL, /* 1: Protocol version */
|
||||
IPSET_ATTR_SETNAME, /* 2: Name of the set */
|
||||
IPSET_ATTR_TYPENAME, /* 3: Typename */
|
||||
IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */
|
||||
IPSET_ATTR_REVISION, /* 4: Settype revision */
|
||||
IPSET_ATTR_FAMILY, /* 5: Settype family */
|
||||
IPSET_ATTR_FLAGS, /* 6: Flags at command level */
|
||||
IPSET_ATTR_DATA, /* 7: Nested attributes */
|
||||
IPSET_ATTR_ADT, /* 8: Multiple data containers */
|
||||
IPSET_ATTR_LINENO, /* 9: Restore lineno */
|
||||
IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
|
||||
IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
|
||||
__IPSET_ATTR_CMD_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1)
|
||||
|
||||
/* CADT specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
|
||||
IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
|
||||
IPSET_ATTR_IP_TO, /* 2 */
|
||||
IPSET_ATTR_CIDR, /* 3 */
|
||||
IPSET_ATTR_PORT, /* 4 */
|
||||
IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
|
||||
IPSET_ATTR_PORT_TO, /* 5 */
|
||||
IPSET_ATTR_TIMEOUT, /* 6 */
|
||||
IPSET_ATTR_PROTO, /* 7 */
|
||||
IPSET_ATTR_CADT_FLAGS, /* 8 */
|
||||
IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */
|
||||
/* Reserve empty slots */
|
||||
IPSET_ATTR_CADT_MAX = 16,
|
||||
/* Create-only specific attributes */
|
||||
IPSET_ATTR_GC,
|
||||
IPSET_ATTR_HASHSIZE,
|
||||
IPSET_ATTR_MAXELEM,
|
||||
IPSET_ATTR_NETMASK,
|
||||
IPSET_ATTR_PROBES,
|
||||
IPSET_ATTR_RESIZE,
|
||||
IPSET_ATTR_SIZE,
|
||||
/* Kernel-only */
|
||||
IPSET_ATTR_ELEMENTS,
|
||||
IPSET_ATTR_REFERENCES,
|
||||
IPSET_ATTR_MEMSIZE,
|
||||
|
||||
__IPSET_ATTR_CREATE_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_CREATE_MAX (__IPSET_ATTR_CREATE_MAX - 1)
|
||||
|
||||
/* ADT specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1,
|
||||
IPSET_ATTR_NAME,
|
||||
IPSET_ATTR_NAMEREF,
|
||||
IPSET_ATTR_IP2,
|
||||
IPSET_ATTR_CIDR2,
|
||||
__IPSET_ATTR_ADT_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
|
||||
|
||||
/* IP specific attributes */
|
||||
enum {
|
||||
IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1,
|
||||
IPSET_ATTR_IPADDR_IPV6,
|
||||
__IPSET_ATTR_IPADDR_MAX,
|
||||
};
|
||||
#define IPSET_ATTR_IPADDR_MAX (__IPSET_ATTR_IPADDR_MAX - 1)
|
||||
|
||||
/* Error codes */
|
||||
enum ipset_errno {
|
||||
IPSET_ERR_PRIVATE = 128,
|
||||
IPSET_ERR_PROTOCOL,
|
||||
IPSET_ERR_FIND_TYPE,
|
||||
IPSET_ERR_MAX_SETS,
|
||||
IPSET_ERR_BUSY,
|
||||
IPSET_ERR_EXIST_SETNAME2,
|
||||
IPSET_ERR_TYPE_MISMATCH,
|
||||
IPSET_ERR_EXIST,
|
||||
IPSET_ERR_INVALID_CIDR,
|
||||
IPSET_ERR_INVALID_NETMASK,
|
||||
IPSET_ERR_INVALID_FAMILY,
|
||||
IPSET_ERR_TIMEOUT,
|
||||
IPSET_ERR_REFERENCED,
|
||||
IPSET_ERR_IPADDR_IPV4,
|
||||
IPSET_ERR_IPADDR_IPV6,
|
||||
|
||||
/* Type specific error codes */
|
||||
IPSET_ERR_TYPE_SPECIFIC = 160,
|
||||
};
|
||||
|
||||
/* Flags at command level */
|
||||
enum ipset_cmd_flags {
|
||||
IPSET_FLAG_BIT_EXIST = 0,
|
||||
IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST),
|
||||
};
|
||||
|
||||
/* Flags at CADT attribute level */
|
||||
enum ipset_cadt_flags {
|
||||
IPSET_FLAG_BIT_BEFORE = 0,
|
||||
IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE),
|
||||
};
|
||||
|
||||
/* Commands with settype-specific attributes */
|
||||
enum ipset_adt {
|
||||
IPSET_ADD,
|
||||
IPSET_DEL,
|
||||
IPSET_TEST,
|
||||
IPSET_ADT_MAX,
|
||||
IPSET_CREATE = IPSET_ADT_MAX,
|
||||
IPSET_CADT_MAX,
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
/* Sets are identified by an index in kernel space. Tweak with ip_set_id_t
|
||||
* and IPSET_INVALID_ID if you want to increase the max number of sets.
|
||||
*/
|
||||
typedef u16 ip_set_id_t;
|
||||
|
||||
#define IPSET_INVALID_ID 65535
|
||||
|
||||
enum ip_set_dim {
|
||||
IPSET_DIM_ZERO = 0,
|
||||
IPSET_DIM_ONE,
|
||||
IPSET_DIM_TWO,
|
||||
IPSET_DIM_THREE,
|
||||
/* Max dimension in elements.
|
||||
* If changed, new revision of iptables match/target is required.
|
||||
*/
|
||||
IPSET_DIM_MAX = 6,
|
||||
};
|
||||
|
||||
/* Option flags for kernel operations */
|
||||
enum ip_set_kopt {
|
||||
IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO),
|
||||
IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
|
||||
IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
|
||||
IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
|
||||
};
|
||||
|
||||
/* Set features */
|
||||
enum ip_set_feature {
|
||||
IPSET_TYPE_IP_FLAG = 0,
|
||||
IPSET_TYPE_IP = (1 << IPSET_TYPE_IP_FLAG),
|
||||
IPSET_TYPE_PORT_FLAG = 1,
|
||||
IPSET_TYPE_PORT = (1 << IPSET_TYPE_PORT_FLAG),
|
||||
IPSET_TYPE_MAC_FLAG = 2,
|
||||
IPSET_TYPE_MAC = (1 << IPSET_TYPE_MAC_FLAG),
|
||||
IPSET_TYPE_IP2_FLAG = 3,
|
||||
IPSET_TYPE_IP2 = (1 << IPSET_TYPE_IP2_FLAG),
|
||||
IPSET_TYPE_NAME_FLAG = 4,
|
||||
IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG),
|
||||
/* Strictly speaking not a feature, but a flag for dumping:
|
||||
* this settype must be dumped last */
|
||||
IPSET_DUMP_LAST_FLAG = 7,
|
||||
IPSET_DUMP_LAST = (1 << IPSET_DUMP_LAST_FLAG),
|
||||
};
|
||||
|
||||
struct ip_set;
|
||||
|
||||
typedef int (*ipset_adtfn)(struct ip_set *set, void *value, u32 timeout);
|
||||
|
||||
/* Set type, variant-specific part */
|
||||
struct ip_set_type_variant {
|
||||
/* Kernelspace: test/add/del entries
|
||||
* returns negative error code,
|
||||
* zero for no match/success to add/delete
|
||||
* positive for matching element */
|
||||
int (*kadt)(struct ip_set *set, const struct sk_buff * skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags);
|
||||
|
||||
/* Userspace: test/add/del entries
|
||||
* returns negative error code,
|
||||
* zero for no match/success to add/delete
|
||||
* positive for matching element */
|
||||
int (*uadt)(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags);
|
||||
|
||||
/* Low level add/del/test functions */
|
||||
ipset_adtfn adt[IPSET_ADT_MAX];
|
||||
|
||||
/* When adding entries and set is full, try to resize the set */
|
||||
int (*resize)(struct ip_set *set, bool retried);
|
||||
/* Destroy the set */
|
||||
void (*destroy)(struct ip_set *set);
|
||||
/* Flush the elements */
|
||||
void (*flush)(struct ip_set *set);
|
||||
/* Expire entries before listing */
|
||||
void (*expire)(struct ip_set *set);
|
||||
/* List set header data */
|
||||
int (*head)(struct ip_set *set, struct sk_buff *skb);
|
||||
/* List elements */
|
||||
int (*list)(const struct ip_set *set, struct sk_buff *skb,
|
||||
struct netlink_callback *cb);
|
||||
|
||||
/* Return true if "b" set is the same as "a"
|
||||
* according to the create set parameters */
|
||||
bool (*same_set)(const struct ip_set *a, const struct ip_set *b);
|
||||
};
|
||||
|
||||
/* The core set type structure */
|
||||
struct ip_set_type {
|
||||
struct list_head list;
|
||||
|
||||
/* Typename */
|
||||
char name[IPSET_MAXNAMELEN];
|
||||
/* Protocol version */
|
||||
u8 protocol;
|
||||
/* Set features to control swapping */
|
||||
u8 features;
|
||||
/* Set type dimension */
|
||||
u8 dimension;
|
||||
/* Supported family: may be AF_UNSPEC for both AF_INET/AF_INET6 */
|
||||
u8 family;
|
||||
/* Type revision */
|
||||
u8 revision;
|
||||
|
||||
/* Create set */
|
||||
int (*create)(struct ip_set *set,
|
||||
struct nlattr *head, int len, u32 flags);
|
||||
|
||||
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
|
||||
struct module *me;
|
||||
};
|
||||
|
||||
extern int ip_set_type_register(struct ip_set_type *set_type);
|
||||
extern void ip_set_type_unregister(struct ip_set_type *set_type);
|
||||
|
||||
/* A generic IP set */
|
||||
struct ip_set {
|
||||
/* The name of the set */
|
||||
char name[IPSET_MAXNAMELEN];
|
||||
/* Lock protecting the set data */
|
||||
rwlock_t lock;
|
||||
/* References to the set */
|
||||
atomic_t ref;
|
||||
/* The core set type */
|
||||
const struct ip_set_type *type;
|
||||
/* The type variant doing the real job */
|
||||
const struct ip_set_type_variant *variant;
|
||||
/* The actual INET family of the set */
|
||||
u8 family;
|
||||
/* The type specific data */
|
||||
void *data;
|
||||
};
|
||||
|
||||
/* register and unregister set references */
|
||||
extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);
|
||||
extern void ip_set_put_byindex(ip_set_id_t index);
|
||||
extern const char * ip_set_name_byindex(ip_set_id_t index);
|
||||
extern ip_set_id_t ip_set_nfnl_get(const char *name);
|
||||
extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index);
|
||||
extern void ip_set_nfnl_put(ip_set_id_t index);
|
||||
|
||||
/* API for iptables set match, and SET target */
|
||||
extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb,
|
||||
u8 family, u8 dim, u8 flags);
|
||||
extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,
|
||||
u8 family, u8 dim, u8 flags);
|
||||
extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
|
||||
u8 family, u8 dim, u8 flags);
|
||||
|
||||
/* Allocate members */
|
||||
static inline void *
|
||||
ip_set_alloc(size_t size, gfp_t gfp_mask)
|
||||
{
|
||||
void *members = NULL;
|
||||
|
||||
if (size < KMALLOC_MAX_SIZE)
|
||||
members = kzalloc(size, gfp_mask | __GFP_NOWARN);
|
||||
|
||||
if (members) {
|
||||
pr_debug("%p: allocated with kmalloc", members);
|
||||
return members;
|
||||
}
|
||||
|
||||
members = __vmalloc(size, gfp_mask | __GFP_ZERO, PAGE_KERNEL);
|
||||
if (!members)
|
||||
return NULL;
|
||||
pr_debug("%p: allocated with vmalloc", members);
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip_set_free(void *members)
|
||||
{
|
||||
pr_debug("%p: free with %s", members,
|
||||
is_vmalloc_addr(members) ? "vfree" : "kfree");
|
||||
if (is_vmalloc_addr(members))
|
||||
vfree(members);
|
||||
else
|
||||
kfree(members);
|
||||
}
|
||||
|
||||
/* Ignore IPSET_ERR_EXIST errors if asked to do so? */
|
||||
static inline bool
|
||||
ip_set_eexist(int ret, u32 flags)
|
||||
{
|
||||
return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST);
|
||||
}
|
||||
|
||||
/* Useful converters */
|
||||
static inline u32
|
||||
ip_set_get_h32(const struct nlattr *attr)
|
||||
{
|
||||
u32 value = nla_get_u32(attr);
|
||||
|
||||
return attr->nla_type & NLA_F_NET_BYTEORDER ? ntohl(value) : value;
|
||||
}
|
||||
|
||||
static inline u16
|
||||
ip_set_get_h16(const struct nlattr *attr)
|
||||
{
|
||||
u16 value = nla_get_u16(attr);
|
||||
|
||||
return attr->nla_type & NLA_F_NET_BYTEORDER ? ntohs(value) : value;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
ip_set_get_n32(const struct nlattr *attr)
|
||||
{
|
||||
u32 value = nla_get_u32(attr);
|
||||
|
||||
return attr->nla_type & NLA_F_NET_BYTEORDER ? value : htonl(value);
|
||||
}
|
||||
|
||||
static inline u16
|
||||
ip_set_get_n16(const struct nlattr *attr)
|
||||
{
|
||||
u16 value = nla_get_u16(attr);
|
||||
|
||||
return attr->nla_type & NLA_F_NET_BYTEORDER ? value : htons(value);
|
||||
}
|
||||
|
||||
static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = {
|
||||
[IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY,
|
||||
.len = sizeof(struct in6_addr) },
|
||||
};
|
||||
|
||||
static inline int
|
||||
ip_set_get_ipaddr4(struct nlattr *attr[], int type, u32 *ipaddr)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1] = {};
|
||||
|
||||
if (!attr[type])
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX,
|
||||
nla_data(attr[type]), nla_len(attr[type]),
|
||||
ipaddr_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
if (!tb[IPSET_ATTR_IPADDR_IPV4])
|
||||
return -IPSET_ERR_IPADDR_IPV4;
|
||||
|
||||
*ipaddr = ip_set_get_n32(tb[IPSET_ATTR_IPADDR_IPV4]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
ip_set_get_ipaddr6(struct nlattr *attr[], int type, union nf_inet_addr *ipaddr)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1] = {};
|
||||
|
||||
if (!attr[type])
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX,
|
||||
nla_data(attr[type]), nla_len(attr[type]),
|
||||
ipaddr_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
if (!tb[IPSET_ATTR_IPADDR_IPV6])
|
||||
return -IPSET_ERR_IPADDR_IPV6;
|
||||
|
||||
memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]),
|
||||
sizeof(struct in6_addr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ipset_nest_start(skb, attr) nla_nest_start(skb, attr | NLA_F_NESTED)
|
||||
#define ipset_nest_end(skb, start) nla_nest_end(skb, start)
|
||||
|
||||
#define NLA_PUT_NET32(skb, type, value) \
|
||||
NLA_PUT_BE32(skb, type | NLA_F_NET_BYTEORDER, value)
|
||||
|
||||
#define NLA_PUT_NET16(skb, type, value) \
|
||||
NLA_PUT_BE16(skb, type | NLA_F_NET_BYTEORDER, value)
|
||||
|
||||
#define NLA_PUT_IPADDR4(skb, type, ipaddr) \
|
||||
do { \
|
||||
struct nlattr *__nested = ipset_nest_start(skb, type); \
|
||||
\
|
||||
if (!__nested) \
|
||||
goto nla_put_failure; \
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_IPADDR_IPV4, ipaddr); \
|
||||
ipset_nest_end(skb, __nested); \
|
||||
} while (0)
|
||||
|
||||
#define NLA_PUT_IPADDR6(skb, type, ipaddrptr) \
|
||||
do { \
|
||||
struct nlattr *__nested = ipset_nest_start(skb, type); \
|
||||
\
|
||||
if (!__nested) \
|
||||
goto nla_put_failure; \
|
||||
NLA_PUT(skb, IPSET_ATTR_IPADDR_IPV6, \
|
||||
sizeof(struct in6_addr), ipaddrptr); \
|
||||
ipset_nest_end(skb, __nested); \
|
||||
} while (0)
|
||||
|
||||
/* Get address from skbuff */
|
||||
static inline u32
|
||||
ip4addr(const struct sk_buff *skb, bool src)
|
||||
{
|
||||
return src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip4addrptr(const struct sk_buff *skb, bool src, u32 *addr)
|
||||
{
|
||||
*addr = src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr)
|
||||
{
|
||||
memcpy(addr, src ? &ipv6_hdr(skb)->saddr : &ipv6_hdr(skb)->daddr,
|
||||
sizeof(*addr));
|
||||
}
|
||||
|
||||
/* Calculate the bytes required to store the inclusive range of a-b */
|
||||
static inline int
|
||||
bitmap_bytes(u32 a, u32 b)
|
||||
{
|
||||
return 4 * ((((b - a + 8) / 8) + 3) / 4);
|
||||
}
|
||||
|
||||
/* Prefixlen maps */
|
||||
extern const union nf_inet_addr prefixlen_netmask_map[];
|
||||
extern const union nf_inet_addr prefixlen_hostmask_map[];
|
||||
|
||||
#define NETMASK(n) prefixlen_netmask_map[n].ip
|
||||
#define NETMASK6(n) prefixlen_netmask_map[n].ip6
|
||||
#define HOSTMASK(n) prefixlen_hostmask_map[n].ip
|
||||
#define HOSTMASK6(n) prefixlen_hostmask_map[n].ip6
|
||||
|
||||
/* Interface to iptables/ip6tables */
|
||||
|
||||
#define SO_IP_SET 83
|
||||
|
||||
union ip_set_name_index {
|
||||
char name[IPSET_MAXNAMELEN];
|
||||
ip_set_id_t index;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */
|
||||
struct ip_set_req_get_set {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
union ip_set_name_index set;
|
||||
};
|
||||
|
||||
#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */
|
||||
/* Uses ip_set_req_get_set */
|
||||
|
||||
#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */
|
||||
struct ip_set_req_version {
|
||||
unsigned op;
|
||||
unsigned version;
|
||||
};
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /*_IP_SET_H */
|
||||
1074
extensions/ipset-5/ip_set_ahash.h
Normal file
1074
extensions/ipset-5/ip_set_ahash.h
Normal file
File diff suppressed because it is too large
Load Diff
31
extensions/ipset-5/ip_set_bitmap.h
Normal file
31
extensions/ipset-5/ip_set_bitmap.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef __IP_SET_BITMAP_H
|
||||
#define __IP_SET_BITMAP_H
|
||||
|
||||
/* Bitmap type specific error codes */
|
||||
enum {
|
||||
/* The element is out of the range of the set */
|
||||
IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* The range exceeds the size limit of the set type */
|
||||
IPSET_ERR_BITMAP_RANGE_SIZE,
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define IPSET_BITMAP_MAX_RANGE 0x0000FFFF
|
||||
|
||||
/* Common functions */
|
||||
|
||||
static inline u32
|
||||
range_to_mask(u32 from, u32 to, u8 *bits)
|
||||
{
|
||||
u32 mask = 0xFFFFFFFE;
|
||||
|
||||
*bits = 32;
|
||||
while (--(*bits) > 0 && mask && (to & mask) != from)
|
||||
mask <<= 1;
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __IP_SET_BITMAP_H */
|
||||
727
extensions/ipset-5/ip_set_bitmap_ip.c
Normal file
727
extensions/ipset-5/ip_set_bitmap_ip.c
Normal file
@@ -0,0 +1,727 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the bitmap:ip type */
|
||||
|
||||
#include "ip_set_kernel.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmap.h"
|
||||
#define IP_SET_BITMAP_TIMEOUT
|
||||
#include "ip_set_timeout.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:ip type of IP sets");
|
||||
MODULE_ALIAS("ip_set_bitmap:ip");
|
||||
|
||||
/* Base variant */
|
||||
|
||||
struct bitmap_ip {
|
||||
void *members; /* the set members */
|
||||
u32 first_ip; /* host byte order, included in range */
|
||||
u32 last_ip; /* host byte order, included in range */
|
||||
u32 elements; /* number of max elements in the set */
|
||||
u32 hosts; /* number of hosts in a subnet */
|
||||
size_t memsize; /* members size */
|
||||
u8 netmask; /* subnet netmask */
|
||||
};
|
||||
|
||||
static inline u32
|
||||
ip_to_id(const struct bitmap_ip *map, u32 ip)
|
||||
{
|
||||
return ((ip & HOSTMASK(map->netmask)) - map->first_ip)/map->hosts;
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_test(const struct bitmap_ip *map, u32 id)
|
||||
{
|
||||
return !!test_bit(id, map->members);
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_add(struct bitmap_ip *map, u32 id)
|
||||
{
|
||||
if (test_and_set_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_del(struct bitmap_ip *map, u32 id)
|
||||
{
|
||||
if (!test_and_clear_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
u32 ip;
|
||||
|
||||
ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
ip = ip_to_id(map, ip);
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
return bitmap_ip_test(map, ip);
|
||||
case IPSET_ADD:
|
||||
return bitmap_ip_add(map, ip);
|
||||
case IPSET_DEL:
|
||||
return bitmap_ip_del(map, ip);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct nla_policy bitmap_ip_adt_policy[IPSET_ATTR_ADT_MAX+1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
u32 ip, ip_to, id;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
bitmap_ip_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
ip = ntohl(ip);
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
/* Set was defined without timeout support:
|
||||
* don't ignore the attribute silently */
|
||||
if (tb[IPSET_ATTR_TIMEOUT])
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
|
||||
if (adt == IPSET_TEST)
|
||||
return bitmap_ip_test(map, ip_to_id(map, ip));
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
ip_to = ntohl(ip_to);
|
||||
if (ip > ip_to) {
|
||||
swap(ip, ip_to);
|
||||
if (ip < map->first_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
}
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip &= HOSTMASK(cidr);
|
||||
ip_to = ip | ~HOSTMASK(cidr);
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
if (ip_to > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
for (; !before(ip_to, ip); ip += map->hosts) {
|
||||
id = ip_to_id(map, ip);
|
||||
ret = adt == IPSET_ADD ? bitmap_ip_add(map, id)
|
||||
: bitmap_ip_del(map, id);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip *map = set->data;
|
||||
|
||||
memset(map->members, 0, map->memsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
|
||||
if (map->netmask != 32)
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ip *map = set->data;
|
||||
struct nlattr *atd, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] < map->elements; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!bitmap_ip_test(map, id))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id * map->hosts));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct bitmap_ip *x = a->data;
|
||||
const struct bitmap_ip *y = b->data;
|
||||
|
||||
return x->first_ip == y->first_ip
|
||||
&& x->last_ip == y->last_ip
|
||||
&& x->netmask == y->netmask;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant bitmap_ip = {
|
||||
.kadt = bitmap_ip_kadt,
|
||||
.uadt = bitmap_ip_uadt,
|
||||
.destroy = bitmap_ip_destroy,
|
||||
.flush = bitmap_ip_flush,
|
||||
.head = bitmap_ip_head,
|
||||
.list = bitmap_ip_list,
|
||||
.same_set = bitmap_ip_same_set,
|
||||
};
|
||||
|
||||
/* Timeout variant */
|
||||
|
||||
struct bitmap_ip_timeout {
|
||||
unsigned long *members; /* the set members */
|
||||
u32 first_ip; /* host byte order, included in range */
|
||||
u32 last_ip; /* host byte order, included in range */
|
||||
u32 elements; /* number of max elements in the set */
|
||||
u32 hosts; /* number of hosts in a subnet */
|
||||
size_t memsize; /* members size */
|
||||
u8 netmask; /* subnet netmask */
|
||||
|
||||
u32 timeout; /* timeout parameter */
|
||||
struct timer_list gc; /* garbage collection */
|
||||
};
|
||||
|
||||
static inline bool
|
||||
bitmap_ip_timeout_test(const struct bitmap_ip_timeout *map, u32 id)
|
||||
{
|
||||
return ip_set_timeout_test(map->members[id]);
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_timeout_add(struct bitmap_ip_timeout *map,
|
||||
u32 id, u32 timeout)
|
||||
{
|
||||
if (bitmap_ip_timeout_test(map, id))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
map->members[id] = ip_set_timeout_set(timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ip_timeout_del(struct bitmap_ip_timeout *map, u32 id)
|
||||
{
|
||||
int ret = -IPSET_ERR_EXIST;
|
||||
|
||||
if (bitmap_ip_timeout_test(map, id))
|
||||
ret = 0;
|
||||
|
||||
map->members[id] = IPSET_ELEM_UNSET;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_timeout_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
u32 ip;
|
||||
|
||||
ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
ip = ip_to_id((const struct bitmap_ip *)map, ip);
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
return bitmap_ip_timeout_test(map, ip);
|
||||
case IPSET_ADD:
|
||||
return bitmap_ip_timeout_add(map, ip, map->timeout);
|
||||
case IPSET_DEL:
|
||||
return bitmap_ip_timeout_del(map, ip);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
u32 ip, ip_to, id, timeout = map->timeout;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
bitmap_ip_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
ip = ntohl(ip);
|
||||
|
||||
if (ip < map->first_ip || ip > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (adt == IPSET_TEST)
|
||||
return bitmap_ip_timeout_test(map,
|
||||
ip_to_id((const struct bitmap_ip *)map, ip));
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
ip_to = ntohl(ip_to);
|
||||
if (ip > ip_to) {
|
||||
swap(ip, ip_to);
|
||||
if (ip < map->first_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
}
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip &= HOSTMASK(cidr);
|
||||
ip_to = ip | ~HOSTMASK(cidr);
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
if (ip_to > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT])
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
for (; !before(ip_to, ip); ip += map->hosts) {
|
||||
id = ip_to_id((const struct bitmap_ip *)map, ip);
|
||||
ret = adt == IPSET_ADD
|
||||
? bitmap_ip_timeout_add(map, id, timeout)
|
||||
: bitmap_ip_timeout_del(map, id);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_timeout_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
|
||||
del_timer_sync(&map->gc);
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ip_timeout_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
|
||||
memset(map->members, IPSET_ELEM_UNSET, map->memsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_timeout_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_ip_timeout *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
|
||||
if (map->netmask != 32)
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_timeout_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ip_timeout *map = set->data;
|
||||
struct nlattr *adt, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
const unsigned long *table = map->members;
|
||||
|
||||
adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!adt)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] < map->elements; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!bitmap_ip_timeout_test(map, id))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, adt);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id * map->hosts));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(table[id])));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, adt);
|
||||
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, adt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
bitmap_ip_timeout_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct bitmap_ip_timeout *x = a->data;
|
||||
const struct bitmap_ip_timeout *y = b->data;
|
||||
|
||||
return x->first_ip == y->first_ip
|
||||
&& x->last_ip == y->last_ip
|
||||
&& x->netmask == y->netmask
|
||||
&& x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant bitmap_ip_timeout = {
|
||||
.kadt = bitmap_ip_timeout_kadt,
|
||||
.uadt = bitmap_ip_timeout_uadt,
|
||||
.destroy = bitmap_ip_timeout_destroy,
|
||||
.flush = bitmap_ip_timeout_flush,
|
||||
.head = bitmap_ip_timeout_head,
|
||||
.list = bitmap_ip_timeout_list,
|
||||
.same_set = bitmap_ip_timeout_same_set,
|
||||
};
|
||||
|
||||
static void
|
||||
bitmap_ip_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
unsigned long *table = map->members;
|
||||
u32 id;
|
||||
|
||||
/* We run parallel with other readers (test element)
|
||||
* but adding/deleting new entries is locked out */
|
||||
read_lock_bh(&set->lock);
|
||||
for (id = 0; id < map->elements; id++)
|
||||
if (ip_set_timeout_expired(table[id]))
|
||||
table[id] = IPSET_ELEM_UNSET;
|
||||
read_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bitmap_ip_gc_init(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ip_timeout *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = bitmap_ip_gc;
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
/* Create bitmap:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
bitmap_ip_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static bool
|
||||
init_map_ip(struct ip_set *set, struct bitmap_ip *map,
|
||||
u32 first_ip, u32 last_ip,
|
||||
u32 elements, u32 hosts, u8 netmask)
|
||||
{
|
||||
map->members = ip_set_alloc(map->memsize, GFP_KERNEL);
|
||||
if (!map->members)
|
||||
return false;
|
||||
map->first_ip = first_ip;
|
||||
map->last_ip = last_ip;
|
||||
map->elements = elements;
|
||||
map->hosts = hosts;
|
||||
map->netmask = netmask;
|
||||
|
||||
set->data = map;
|
||||
set->family = AF_INET;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len,
|
||||
u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
u32 first_ip, last_ip, hosts, elements;
|
||||
u8 netmask = 32;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
bitmap_ip_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &first_ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
first_ip = ntohl(first_ip);
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &last_ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
last_ip = htonl(last_ip);
|
||||
if (first_ip > last_ip) {
|
||||
u32 tmp = first_ip;
|
||||
|
||||
first_ip = last_ip;
|
||||
last_ip = tmp;
|
||||
}
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr >= 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
last_ip = first_ip | ~HOSTMASK(cidr);
|
||||
} else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_NETMASK]) {
|
||||
netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
|
||||
|
||||
if (netmask > 32)
|
||||
return -IPSET_ERR_INVALID_NETMASK;
|
||||
|
||||
first_ip &= HOSTMASK(netmask);
|
||||
last_ip |= ~HOSTMASK(netmask);
|
||||
}
|
||||
|
||||
if (netmask == 32) {
|
||||
hosts = 1;
|
||||
elements = last_ip - first_ip + 1;
|
||||
} else {
|
||||
u8 mask_bits;
|
||||
u32 mask;
|
||||
|
||||
mask = range_to_mask(first_ip, last_ip, &mask_bits);
|
||||
|
||||
if ((!mask && (first_ip || last_ip != 0xFFFFFFFF))
|
||||
|| netmask <= mask_bits)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
pr_debug("mask_bits %u, netmask %u", mask_bits, netmask);
|
||||
hosts = 2 << (32 - netmask - 1);
|
||||
elements = 2 << (netmask - mask_bits - 1);
|
||||
}
|
||||
if (elements > IPSET_BITMAP_MAX_RANGE + 1)
|
||||
return -IPSET_ERR_BITMAP_RANGE_SIZE;
|
||||
|
||||
pr_debug("hosts %u, elements %u", hosts, elements);
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
struct bitmap_ip_timeout *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->memsize = elements * sizeof(unsigned long);
|
||||
|
||||
if (!init_map_ip(set, (struct bitmap_ip *)map,
|
||||
first_ip, last_ip,
|
||||
elements, hosts, netmask)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
set->variant = &bitmap_ip_timeout;
|
||||
|
||||
bitmap_ip_gc_init(set);
|
||||
} else {
|
||||
struct bitmap_ip *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->memsize = bitmap_bytes(0, elements - 1);
|
||||
|
||||
if (!init_map_ip(set, map,
|
||||
first_ip, last_ip,
|
||||
elements, hosts, netmask)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
set->variant = &bitmap_ip;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type bitmap_ip_type __read_mostly = {
|
||||
.name = "bitmap:ip",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = AF_INET,
|
||||
.revision = 0,
|
||||
.create = bitmap_ip_create,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
bitmap_ip_init(void)
|
||||
{
|
||||
return ip_set_type_register(&bitmap_ip_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
bitmap_ip_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&bitmap_ip_type);
|
||||
}
|
||||
|
||||
module_init(bitmap_ip_init);
|
||||
module_exit(bitmap_ip_fini);
|
||||
660
extensions/ipset-5/ip_set_bitmap_ipmac.c
Normal file
660
extensions/ipset-5/ip_set_bitmap_ipmac.c
Normal file
@@ -0,0 +1,660 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the bitmap:ip,mac type */
|
||||
|
||||
#include "ip_set_kernel.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_bitmap.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:ip,mac type of IP sets");
|
||||
MODULE_ALIAS("ip_set_bitmap:ip,mac");
|
||||
|
||||
enum {
|
||||
MAC_EMPTY, /* element is not set */
|
||||
MAC_FILLED, /* element is set with MAC */
|
||||
MAC_UNSET, /* element is set, without MAC */
|
||||
};
|
||||
|
||||
/* Type structure */
|
||||
struct bitmap_ipmac {
|
||||
void *members; /* the set members */
|
||||
u32 first_ip; /* host byte order, included in range */
|
||||
u32 last_ip; /* host byte order, included in range */
|
||||
u32 timeout; /* timeout value */
|
||||
struct timer_list gc; /* garbage collector */
|
||||
size_t dsize; /* size of element */
|
||||
};
|
||||
|
||||
/* ADT structure for generic function args */
|
||||
struct ipmac {
|
||||
u32 id; /* id in array */
|
||||
unsigned char *ether; /* ethernet address */
|
||||
};
|
||||
|
||||
/* Member element without and with timeout */
|
||||
|
||||
struct ipmac_elem {
|
||||
unsigned char ether[ETH_ALEN];
|
||||
unsigned char match;
|
||||
} __attribute__ ((aligned));
|
||||
|
||||
struct ipmac_telem {
|
||||
unsigned char ether[ETH_ALEN];
|
||||
unsigned char match;
|
||||
unsigned long timeout;
|
||||
} __attribute__ ((aligned));
|
||||
|
||||
static inline void *
|
||||
bitmap_ipmac_elem(const struct bitmap_ipmac *map, u32 id)
|
||||
{
|
||||
return (void *)((char *)map->members + id * map->dsize);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
bitmap_timeout(const struct bitmap_ipmac *map, u32 id)
|
||||
{
|
||||
const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
|
||||
|
||||
return ip_set_timeout_test(elem->timeout);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
bitmap_expired(const struct bitmap_ipmac *map, u32 id)
|
||||
{
|
||||
const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
|
||||
|
||||
return ip_set_timeout_expired(elem->timeout);
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_ipmac_exist(const struct ipmac_telem *elem)
|
||||
{
|
||||
return elem->match == MAC_UNSET
|
||||
|| (elem->match == MAC_FILLED
|
||||
&& !ip_set_timeout_expired(elem->timeout));
|
||||
}
|
||||
|
||||
/* Base variant */
|
||||
|
||||
static int
|
||||
bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
switch (elem->match) {
|
||||
case MAC_UNSET:
|
||||
/* Trigger kernel to fill out the ethernet address */
|
||||
return -EAGAIN;
|
||||
case MAC_FILLED:
|
||||
return data->ether == NULL
|
||||
|| compare_ether_addr(data->ether, elem->ether) == 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
switch (elem->match) {
|
||||
case MAC_UNSET:
|
||||
if (!data->ether)
|
||||
/* Already added without ethernet address */
|
||||
return -IPSET_ERR_EXIST;
|
||||
/* Fill the MAC address */
|
||||
memcpy(elem->ether, data->ether, ETH_ALEN);
|
||||
elem->match = MAC_FILLED;
|
||||
break;
|
||||
case MAC_FILLED:
|
||||
return -IPSET_ERR_EXIST;
|
||||
case MAC_EMPTY:
|
||||
if (data->ether) {
|
||||
memcpy(elem->ether, data->ether, ETH_ALEN);
|
||||
elem->match = MAC_FILLED;
|
||||
} else
|
||||
elem->match = MAC_UNSET;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
if (elem->match == MAC_EMPTY)
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
elem->match = MAC_EMPTY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac_elem *elem;
|
||||
struct nlattr *atd, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
u32 last = map->last_ip - map->first_ip;
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
elem = bitmap_ipmac_elem(map, id);
|
||||
if (elem->match == MAC_EMPTY)
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id));
|
||||
if (elem->match == MAC_FILLED)
|
||||
NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
|
||||
elem->ether);
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Timeout variant */
|
||||
|
||||
static int
|
||||
bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
switch (elem->match) {
|
||||
case MAC_UNSET:
|
||||
/* Trigger kernel to fill out the ethernet address */
|
||||
return -EAGAIN;
|
||||
case MAC_FILLED:
|
||||
return (data->ether == NULL
|
||||
|| compare_ether_addr(data->ether, elem->ether) == 0)
|
||||
&& !bitmap_expired(map, data->id);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
switch (elem->match) {
|
||||
case MAC_UNSET:
|
||||
if (!data->ether)
|
||||
/* Already added without ethernet address */
|
||||
return -IPSET_ERR_EXIST;
|
||||
/* Fill the MAC address and activate the timer */
|
||||
memcpy(elem->ether, data->ether, ETH_ALEN);
|
||||
elem->match = MAC_FILLED;
|
||||
if (timeout == map->timeout)
|
||||
/* Timeout was not specified, get stored one */
|
||||
timeout = elem->timeout;
|
||||
elem->timeout = ip_set_timeout_set(timeout);
|
||||
break;
|
||||
case MAC_FILLED:
|
||||
if (!bitmap_expired(map, data->id))
|
||||
return -IPSET_ERR_EXIST;
|
||||
/* Fall through */
|
||||
case MAC_EMPTY:
|
||||
if (data->ether) {
|
||||
memcpy(elem->ether, data->ether, ETH_ALEN);
|
||||
elem->match = MAC_FILLED;
|
||||
} else
|
||||
elem->match = MAC_UNSET;
|
||||
/* If MAC is unset yet, we store plain timeout value
|
||||
* because the timer is not activated yet
|
||||
* and we can reuse it later when MAC is filled out,
|
||||
* possibly by the kernel */
|
||||
elem->timeout = data->ether ? ip_set_timeout_set(timeout)
|
||||
: timeout;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac *data = value;
|
||||
struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id);
|
||||
|
||||
if (elem->match == MAC_EMPTY || bitmap_expired(map, data->id))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
elem->match = MAC_EMPTY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_tlist(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
const struct ipmac_telem *elem;
|
||||
struct nlattr *atd, *nested;
|
||||
u32 id, first = cb->args[2];
|
||||
u32 timeout, last = map->last_ip - map->first_ip;
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
elem = bitmap_ipmac_elem(map, id);
|
||||
if (!bitmap_ipmac_exist(elem))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP,
|
||||
htonl(map->first_ip + id));
|
||||
if (elem->match == MAC_FILLED)
|
||||
NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
|
||||
elem->ether);
|
||||
timeout = elem->match == MAC_UNSET ? elem->timeout
|
||||
: ip_set_timeout_get(elem->timeout);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct ipmac data;
|
||||
|
||||
data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
|
||||
if (data.id < map->first_ip || data.id > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
/* Backward compatibility: we don't check the second flag */
|
||||
if (skb_mac_header(skb) < skb->head
|
||||
|| (skb_mac_header(skb) + ETH_HLEN) > skb->data)
|
||||
return -EINVAL;
|
||||
|
||||
data.id -= map->first_ip;
|
||||
data.ether = eth_hdr(skb)->h_source;
|
||||
|
||||
return adtfn(set, &data, map->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy
|
||||
bitmap_ipmac_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_ETHER] = { .type = NLA_BINARY, .len = ETH_ALEN },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct ipmac data;
|
||||
u32 timeout = map->timeout;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
bitmap_ipmac_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.id);
|
||||
if (ret)
|
||||
return ret;
|
||||
data.id = ntohl(data.id);
|
||||
|
||||
if (data.id < map->first_ip || data.id > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_ETHER])
|
||||
data.ether = nla_data(tb[IPSET_ATTR_ETHER]);
|
||||
else
|
||||
data.ether = NULL;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(map->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
data.id -= map->first_ip;
|
||||
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ipmac_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
|
||||
if (with_timeout(map->timeout))
|
||||
del_timer_sync(&map->gc);
|
||||
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_ipmac_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
|
||||
memset(map->members, 0,
|
||||
(map->last_ip - map->first_ip + 1) * map->dsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_ipmac *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map)
|
||||
+ (map->last_ip - map->first_ip + 1) * map->dsize));
|
||||
if (with_timeout(map->timeout))
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static bool
|
||||
bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct bitmap_ipmac *x = a->data;
|
||||
const struct bitmap_ipmac *y = b->data;
|
||||
|
||||
return x->first_ip == y->first_ip
|
||||
&& x->last_ip == y->last_ip
|
||||
&& x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
const struct ip_set_type_variant bitmap_ipmac = {
|
||||
.kadt = bitmap_ipmac_kadt,
|
||||
.uadt = bitmap_ipmac_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_ipmac_add,
|
||||
[IPSET_DEL] = bitmap_ipmac_del,
|
||||
[IPSET_TEST] = bitmap_ipmac_test,
|
||||
},
|
||||
.destroy = bitmap_ipmac_destroy,
|
||||
.flush = bitmap_ipmac_flush,
|
||||
.head = bitmap_ipmac_head,
|
||||
.list = bitmap_ipmac_list,
|
||||
.same_set = bitmap_ipmac_same_set,
|
||||
};
|
||||
|
||||
const struct ip_set_type_variant bitmap_tipmac = {
|
||||
.kadt = bitmap_ipmac_kadt,
|
||||
.uadt = bitmap_ipmac_uadt,
|
||||
.adt = {
|
||||
[IPSET_ADD] = bitmap_ipmac_tadd,
|
||||
[IPSET_DEL] = bitmap_ipmac_tdel,
|
||||
[IPSET_TEST] = bitmap_ipmac_ttest,
|
||||
},
|
||||
.destroy = bitmap_ipmac_destroy,
|
||||
.flush = bitmap_ipmac_flush,
|
||||
.head = bitmap_ipmac_head,
|
||||
.list = bitmap_ipmac_tlist,
|
||||
.same_set = bitmap_ipmac_same_set,
|
||||
};
|
||||
|
||||
static void
|
||||
bitmap_ipmac_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
struct ipmac_telem *elem;
|
||||
u32 id, last = map->last_ip - map->first_ip;
|
||||
|
||||
/* We run parallel with other readers (test element)
|
||||
* but adding/deleting new entries is locked out */
|
||||
read_lock_bh(&set->lock);
|
||||
for (id = 0; id <= last; id++) {
|
||||
elem = bitmap_ipmac_elem(map, id);
|
||||
if (elem->match == MAC_FILLED
|
||||
&& ip_set_timeout_expired(elem->timeout))
|
||||
elem->match = MAC_EMPTY;
|
||||
}
|
||||
read_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bitmap_ipmac_gc_init(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_ipmac *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = bitmap_ipmac_gc;
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
/* Create bitmap:ip,mac type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
bitmap_ipmac_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static bool
|
||||
init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
|
||||
u32 first_ip, u32 last_ip)
|
||||
{
|
||||
map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize,
|
||||
GFP_KERNEL);
|
||||
if (!map->members)
|
||||
return false;
|
||||
map->first_ip = first_ip;
|
||||
map->last_ip = last_ip;
|
||||
map->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
set->data = map;
|
||||
set->family = AF_INET;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len,
|
||||
u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
u32 first_ip, last_ip, elements;
|
||||
struct bitmap_ipmac *map;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
bitmap_ipmac_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &first_ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
first_ip = ntohl(first_ip);
|
||||
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &last_ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
last_ip = ntohl(last_ip);
|
||||
if (first_ip > last_ip) {
|
||||
u32 tmp = first_ip;
|
||||
|
||||
first_ip = last_ip;
|
||||
last_ip = tmp;
|
||||
}
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr >= 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
last_ip = first_ip | ~HOSTMASK(cidr);
|
||||
} else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
elements = last_ip - first_ip + 1;
|
||||
|
||||
if (elements > IPSET_BITMAP_MAX_RANGE + 1)
|
||||
return -IPSET_ERR_BITMAP_RANGE_SIZE;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
map->dsize = sizeof(struct ipmac_telem);
|
||||
|
||||
if (!init_map_ipmac(set, map, first_ip, last_ip)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = &bitmap_tipmac;
|
||||
|
||||
bitmap_ipmac_gc_init(set);
|
||||
} else {
|
||||
map->dsize = sizeof(struct ipmac_elem);
|
||||
|
||||
if (!init_map_ipmac(set, map, first_ip, last_ip)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
set->variant = &bitmap_ipmac;
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ip_set_type bitmap_ipmac_type = {
|
||||
.name = "bitmap:ip,mac",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_MAC,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = AF_INET,
|
||||
.revision = 0,
|
||||
.create = bitmap_ipmac_create,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
bitmap_ipmac_init(void)
|
||||
{
|
||||
return ip_set_type_register(&bitmap_ipmac_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
bitmap_ipmac_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&bitmap_ipmac_type);
|
||||
}
|
||||
|
||||
module_init(bitmap_ipmac_init);
|
||||
module_exit(bitmap_ipmac_fini);
|
||||
649
extensions/ipset-5/ip_set_bitmap_port.c
Normal file
649
extensions/ipset-5/ip_set_bitmap_port.c
Normal file
@@ -0,0 +1,649 @@
|
||||
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the bitmap:port type */
|
||||
|
||||
#include "ip_set_kernel.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/udp.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/timer.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_bitmap.h"
|
||||
#include "ip_set_getport.h"
|
||||
#define IP_SET_BITMAP_TIMEOUT
|
||||
#include "ip_set_timeout.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("bitmap:port type of IP sets");
|
||||
MODULE_ALIAS("ip_set_bitmap:port");
|
||||
|
||||
/* Base variant */
|
||||
|
||||
struct bitmap_port {
|
||||
void *members; /* the set members */
|
||||
u16 first_port; /* host byte order, included in range */
|
||||
u16 last_port; /* host byte order, included in range */
|
||||
size_t memsize; /* members size */
|
||||
};
|
||||
|
||||
static inline int
|
||||
bitmap_port_test(const struct bitmap_port *map, u16 id)
|
||||
{
|
||||
return !!test_bit(id, map->members);
|
||||
}
|
||||
|
||||
static inline int
|
||||
bitmap_port_add(struct bitmap_port *map, u16 id)
|
||||
{
|
||||
if (test_and_set_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_del(struct bitmap_port *map, u16 id)
|
||||
{
|
||||
if (!test_and_clear_bit(id, map->members))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
u16 port = 0;
|
||||
|
||||
if (!get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &port))
|
||||
return -EINVAL;
|
||||
|
||||
port = ntohs(port);
|
||||
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
port -= map->first_port;
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
return bitmap_port_test(map, port);
|
||||
case IPSET_ADD:
|
||||
return bitmap_port_add(map, port);
|
||||
case IPSET_DEL:
|
||||
return bitmap_port_del(map, port);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct nla_policy bitmap_port_adt_policy[IPSET_ATTR_ADT_MAX+1] = {
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
u32 port; /* wraparound */
|
||||
u16 id, port_to;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
bitmap_port_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT])
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
|
||||
if (adt == IPSET_TEST)
|
||||
return bitmap_port_test(map, port - map->first_port);
|
||||
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to) {
|
||||
swap(port, port_to);
|
||||
if (port < map->first_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
}
|
||||
} else
|
||||
port_to = port;
|
||||
|
||||
if (port_to > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
id = port - map->first_port;
|
||||
ret = adt == IPSET_ADD ? bitmap_port_add(map, id)
|
||||
: bitmap_port_del(map, id);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port *map = set->data;
|
||||
|
||||
memset(map->members, 0, map->memsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port));
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_port *map = set->data;
|
||||
struct nlattr *atd, *nested;
|
||||
u16 id, first = cb->args[2];
|
||||
u16 last = map->last_port - map->first_port;
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!test_bit(id, map->members))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
|
||||
htons(map->first_port + id));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct bitmap_port *x = a->data;
|
||||
const struct bitmap_port *y = b->data;
|
||||
|
||||
return x->first_port == y->first_port
|
||||
&& x->last_port == y->last_port;
|
||||
}
|
||||
|
||||
const struct ip_set_type_variant bitmap_port = {
|
||||
.kadt = bitmap_port_kadt,
|
||||
.uadt = bitmap_port_uadt,
|
||||
.destroy = bitmap_port_destroy,
|
||||
.flush = bitmap_port_flush,
|
||||
.head = bitmap_port_head,
|
||||
.list = bitmap_port_list,
|
||||
.same_set = bitmap_port_same_set,
|
||||
};
|
||||
|
||||
/* Timeout variant */
|
||||
|
||||
struct bitmap_port_timeout {
|
||||
unsigned long *members; /* the set members */
|
||||
u16 first_port; /* host byte order, included in range */
|
||||
u16 last_port; /* host byte order, included in range */
|
||||
size_t memsize; /* members size */
|
||||
|
||||
u32 timeout; /* timeout parameter */
|
||||
struct timer_list gc; /* garbage collection */
|
||||
};
|
||||
|
||||
static inline bool
|
||||
bitmap_port_timeout_test(const struct bitmap_port_timeout *map, u16 id)
|
||||
{
|
||||
return ip_set_timeout_test(map->members[id]);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_add(const struct bitmap_port_timeout *map,
|
||||
u16 id, u32 timeout)
|
||||
{
|
||||
if (bitmap_port_timeout_test(map, id))
|
||||
return -IPSET_ERR_EXIST;
|
||||
|
||||
map->members[id] = ip_set_timeout_set(timeout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_del(const struct bitmap_port_timeout *map,
|
||||
u16 id)
|
||||
{
|
||||
int ret = -IPSET_ERR_EXIST;
|
||||
|
||||
if (bitmap_port_timeout_test(map, id))
|
||||
ret = 0;
|
||||
|
||||
map->members[id] = IPSET_ELEM_UNSET;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
u16 port = 0;
|
||||
|
||||
if (!get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &port))
|
||||
return -EINVAL;
|
||||
|
||||
port = ntohs(port);
|
||||
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
port -= map->first_port;
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
return bitmap_port_timeout_test(map, port);
|
||||
case IPSET_ADD:
|
||||
return bitmap_port_timeout_add(map, port, map->timeout);
|
||||
case IPSET_DEL:
|
||||
return bitmap_port_timeout_del(map, port);
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct bitmap_port_timeout *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
u16 id, port_to;
|
||||
u32 port, timeout = map->timeout; /* wraparound */
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
bitmap_port_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (port < map->first_port || port > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (adt == IPSET_TEST)
|
||||
return bitmap_port_timeout_test(map, port - map->first_port);
|
||||
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to) {
|
||||
swap(port, port_to);
|
||||
if (port < map->first_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
}
|
||||
} else
|
||||
port_to = port;
|
||||
|
||||
if (port_to > map->last_port)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT])
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
id = port - map->first_port;
|
||||
ret = adt == IPSET_ADD
|
||||
? bitmap_port_timeout_add(map, id, timeout)
|
||||
: bitmap_port_timeout_del(map, id);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_timeout_destroy(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
|
||||
del_timer_sync(&map->gc);
|
||||
ip_set_free(map->members);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bitmap_port_timeout_flush(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
|
||||
memset(map->members, 0, map->memsize);
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct bitmap_port_timeout *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port));
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT , htonl(map->timeout));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->memsize));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_timeout_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct bitmap_port_timeout *map = set->data;
|
||||
struct nlattr *adt, *nested;
|
||||
u16 id, first = cb->args[2];
|
||||
u16 last = map->last_port - map->first_port;
|
||||
const unsigned long *table = map->members;
|
||||
|
||||
adt = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!adt)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] <= last; cb->args[2]++) {
|
||||
id = cb->args[2];
|
||||
if (!bitmap_port_timeout_test(map, id))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (id == first) {
|
||||
nla_nest_cancel(skb, adt);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT,
|
||||
htons(map->first_port + id));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(table[id])));
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
ipset_nest_end(skb, adt);
|
||||
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, adt);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
bitmap_port_timeout_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct bitmap_port_timeout *x = a->data;
|
||||
const struct bitmap_port_timeout *y = b->data;
|
||||
|
||||
return x->first_port == y->first_port
|
||||
&& x->last_port == y->last_port
|
||||
&& x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
const struct ip_set_type_variant bitmap_port_timeout = {
|
||||
.kadt = bitmap_port_timeout_kadt,
|
||||
.uadt = bitmap_port_timeout_uadt,
|
||||
.destroy = bitmap_port_timeout_destroy,
|
||||
.flush = bitmap_port_timeout_flush,
|
||||
.head = bitmap_port_timeout_head,
|
||||
.list = bitmap_port_timeout_list,
|
||||
.same_set = bitmap_port_timeout_same_set,
|
||||
};
|
||||
|
||||
static void
|
||||
bitmap_port_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
unsigned long *table = map->members;
|
||||
u32 id; /* wraparound */
|
||||
u16 last = map->last_port - map->first_port;
|
||||
|
||||
/* We run parallel with other readers (test element)
|
||||
* but adding/deleting new entries is locked out */
|
||||
read_lock_bh(&set->lock);
|
||||
for (id = 0; id <= last; id++)
|
||||
if (ip_set_timeout_expired(table[id]))
|
||||
table[id] = IPSET_ELEM_UNSET;
|
||||
read_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static inline void
|
||||
bitmap_port_gc_init(struct ip_set *set)
|
||||
{
|
||||
struct bitmap_port_timeout *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = bitmap_port_gc;
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
/* Create bitmap:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
bitmap_port_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static bool
|
||||
init_map_port(struct ip_set *set, struct bitmap_port *map,
|
||||
u16 first_port, u16 last_port)
|
||||
{
|
||||
map->members = ip_set_alloc(map->memsize, GFP_KERNEL);
|
||||
if (!map->members)
|
||||
return false;
|
||||
map->first_port = first_port;
|
||||
map->last_port = last_port;
|
||||
|
||||
set->data = map;
|
||||
set->family = AF_UNSPEC;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
bitmap_port_create(struct ip_set *set, struct nlattr *head, int len,
|
||||
u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
u16 first_port, last_port;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
bitmap_port_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (first_port > last_port) {
|
||||
u16 tmp = first_port;
|
||||
|
||||
first_port = last_port;
|
||||
last_port = tmp;
|
||||
}
|
||||
} else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
struct bitmap_port_timeout *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->memsize = (last_port - first_port + 1)
|
||||
* sizeof(unsigned long);
|
||||
|
||||
if (!init_map_port(set, (struct bitmap_port *) map,
|
||||
first_port, last_port)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
set->variant = &bitmap_port_timeout;
|
||||
|
||||
bitmap_port_gc_init(set);
|
||||
} else {
|
||||
struct bitmap_port *map;
|
||||
|
||||
map = kzalloc(sizeof(*map), GFP_KERNEL);
|
||||
if (!map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->memsize = bitmap_bytes(0, last_port - first_port);
|
||||
pr_debug("memsize: %zu", map->memsize);
|
||||
if (!init_map_port(set, map, first_port, last_port)) {
|
||||
kfree(map);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
set->variant = &bitmap_port;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ip_set_type bitmap_port_type = {
|
||||
.name = "bitmap:port",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_PORT,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = bitmap_port_create,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
bitmap_port_init(void)
|
||||
{
|
||||
return ip_set_type_register(&bitmap_port_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
bitmap_port_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&bitmap_port_type);
|
||||
}
|
||||
|
||||
module_init(bitmap_port_init);
|
||||
module_exit(bitmap_port_fini);
|
||||
1164
extensions/ipset-5/ip_set_chash.h
Normal file
1164
extensions/ipset-5/ip_set_chash.h
Normal file
File diff suppressed because it is too large
Load Diff
126
extensions/ipset-5/ip_set_getport.h
Normal file
126
extensions/ipset-5/ip_set_getport.h
Normal file
@@ -0,0 +1,126 @@
|
||||
#ifndef _IP_SET_GETPORT_H
|
||||
#define _IP_SET_GETPORT_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/icmpv6.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <net/ip.h>
|
||||
|
||||
#define IPSET_INVALID_PORT 65536
|
||||
|
||||
/* We must handle non-linear skbs */
|
||||
static inline bool
|
||||
get_port(const struct sk_buff *skb, int protocol, unsigned int protooff,
|
||||
bool src, u16 *port, u8 *proto)
|
||||
{
|
||||
switch (protocol) {
|
||||
case IPPROTO_TCP: {
|
||||
struct tcphdr _tcph;
|
||||
const struct tcphdr *th;
|
||||
|
||||
th = skb_header_pointer(skb, protooff, sizeof(_tcph), &_tcph);
|
||||
if (th == NULL)
|
||||
/* No choice either */
|
||||
return false;
|
||||
|
||||
*port = src ? th->source : th->dest;
|
||||
break;
|
||||
}
|
||||
case IPPROTO_UDP: {
|
||||
struct udphdr _udph;
|
||||
const struct udphdr *uh;
|
||||
|
||||
uh = skb_header_pointer(skb, protooff, sizeof(_udph), &_udph);
|
||||
if (uh == NULL)
|
||||
/* No choice either */
|
||||
return false;
|
||||
|
||||
*port = src ? uh->source : uh->dest;
|
||||
break;
|
||||
}
|
||||
case IPPROTO_ICMP: {
|
||||
struct icmphdr _icmph;
|
||||
const struct icmphdr *ic;
|
||||
|
||||
ic = skb_header_pointer(skb, protooff, sizeof(_icmph), &_icmph);
|
||||
if (ic == NULL)
|
||||
return false;
|
||||
|
||||
*port = (ic->type << 8) & ic->code;
|
||||
break;
|
||||
}
|
||||
case IPPROTO_ICMPV6: {
|
||||
struct icmp6hdr _icmph;
|
||||
const struct icmp6hdr *ic;
|
||||
|
||||
ic = skb_header_pointer(skb, protooff, sizeof(_icmph), &_icmph);
|
||||
if (ic == NULL)
|
||||
return false;
|
||||
|
||||
*port = (ic->icmp6_type << 8) & ic->icmp6_code;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*proto = protocol;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
get_ip4_port(const struct sk_buff *skb, bool src, u16 *port, u8 *proto)
|
||||
{
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
unsigned int protooff = ip_hdrlen(skb);
|
||||
int protocol = iph->protocol;
|
||||
|
||||
/* See comments at tcp_match in ip_tables.c */
|
||||
if (protocol <= 0 || (ntohs(iph->frag_off) & IP_OFFSET))
|
||||
return false;
|
||||
|
||||
return get_port(skb, protocol, protooff, src, port, proto);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
get_ip6_port(const struct sk_buff *skb, bool src, u16 *port, u8 *proto)
|
||||
{
|
||||
unsigned int protooff = 0;
|
||||
int protocol;
|
||||
unsigned short fragoff;
|
||||
|
||||
protocol = ipv6_find_hdr(skb, &protooff, -1, &fragoff);
|
||||
if (protocol <= 0 || fragoff)
|
||||
return false;
|
||||
|
||||
return get_port(skb, protocol, protooff, src, port, proto);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
get_ip_port(const struct sk_buff *skb, u8 pf, bool src, u16 *port)
|
||||
{
|
||||
bool ret;
|
||||
u8 proto;
|
||||
|
||||
switch (pf) {
|
||||
case AF_INET:
|
||||
ret = get_ip4_port(skb, src, port, &proto);
|
||||
case AF_INET6:
|
||||
ret = get_ip6_port(skb, src, port, &proto);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (!ret)
|
||||
return ret;
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /*_IP_SET_GETPORT_H*/
|
||||
26
extensions/ipset-5/ip_set_hash.h
Normal file
26
extensions/ipset-5/ip_set_hash.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef __IP_SET_HASH_H
|
||||
#define __IP_SET_HASH_H
|
||||
|
||||
/* Hash type specific error codes */
|
||||
enum {
|
||||
/* Hash is full */
|
||||
IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* Null-valued element */
|
||||
IPSET_ERR_HASH_ELEM,
|
||||
/* Invalid protocol */
|
||||
IPSET_ERR_INVALID_PROTO,
|
||||
/* Protocol missing but must be specified */
|
||||
IPSET_ERR_MISSING_PROTO,
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define IPSET_DEFAULT_HASHSIZE 1024
|
||||
#define IPSET_MIMINAL_HASHSIZE 64
|
||||
#define IPSET_DEFAULT_MAXELEM 65536
|
||||
#define IPSET_DEFAULT_PROBES 4
|
||||
#define IPSET_DEFAULT_RESIZE 100
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __IP_SET_HASH_H */
|
||||
484
extensions/ipset-5/ip_set_hash_ip.c
Normal file
484
extensions/ipset-5/ip_set_hash_ip.c
Normal file
@@ -0,0 +1,484 @@
|
||||
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the hash:ip type */
|
||||
|
||||
#include "ip_set_kernel.h"
|
||||
#include "jhash.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_hash.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:ip type of IP sets");
|
||||
MODULE_ALIAS("ip_set_hash:ip");
|
||||
|
||||
/* Type specific function prefix */
|
||||
#define TYPE hash_ip
|
||||
|
||||
static bool
|
||||
hash_ip_same_set(const struct ip_set *a, const struct ip_set *b);
|
||||
|
||||
#define hash_ip4_same_set hash_ip_same_set
|
||||
#define hash_ip6_same_set hash_ip_same_set
|
||||
|
||||
/* The type variant functions: IPv4 */
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_ip4_elem {
|
||||
u32 ip;
|
||||
};
|
||||
|
||||
/* Member elements with timeout support */
|
||||
struct hash_ip4_telem {
|
||||
u32 ip;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ip4_data_equal(const struct hash_ip4_elem *ip1,
|
||||
const struct hash_ip4_elem *ip2)
|
||||
{
|
||||
return ip1->ip == ip2->ip;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ip4_data_isnull(const struct hash_ip4_elem *elem)
|
||||
{
|
||||
return elem->ip == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ip4_data_copy(struct hash_ip4_elem *dst, const struct hash_ip4_elem *src)
|
||||
{
|
||||
dst->ip = src->ip;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ip4_data_swap(struct hash_ip4_elem *dst, struct hash_ip4_elem *src)
|
||||
{
|
||||
swap(dst->ip, src->ip);
|
||||
}
|
||||
|
||||
/* Zero valued IP addresses cannot be stored */
|
||||
static inline void
|
||||
hash_ip4_data_zero_out(struct hash_ip4_elem *elem)
|
||||
{
|
||||
elem->ip = 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ip4_data_list(struct sk_buff *skb, const struct hash_ip4_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ip4_data_tlist(struct sk_buff *skb, const struct hash_ip4_elem *data)
|
||||
{
|
||||
const struct hash_ip4_telem *tdata =
|
||||
(const struct hash_ip4_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(tdata->timeout)));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IP_SET_HASH_WITH_NETMASK
|
||||
#define PF 4
|
||||
#define HOST_MASK 32
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static int
|
||||
hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
u32 ip;
|
||||
|
||||
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip);
|
||||
ip &= NETMASK(h->netmask);
|
||||
if (ip == 0)
|
||||
return -EINVAL;
|
||||
|
||||
return adtfn(set, &ip, h->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy hash_ip4_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
u32 ip, nip, ip_to, hosts, timeout = h->timeout;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
hash_ip4_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ip &= NETMASK(h->netmask);
|
||||
if (ip == 0)
|
||||
return -IPSET_ERR_HASH_ELEM;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST)
|
||||
return adtfn(set, &ip, timeout);
|
||||
|
||||
ip = ntohl(ip);
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
ip_to = ntohl(ip_to);
|
||||
if (ip > ip_to)
|
||||
swap(ip, ip_to);
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip &= HOSTMASK(cidr);
|
||||
ip_to = ip | ~HOSTMASK(cidr);
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
|
||||
|
||||
for (; !before(ip_to, ip); ip += hosts) {
|
||||
nip = htonl(ip);
|
||||
ret = adtfn(set, &nip, timeout);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ip_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct ip_set_hash *x = a->data;
|
||||
const struct ip_set_hash *y = b->data;
|
||||
|
||||
/* Resizing changes htable_bits, so we ignore it */
|
||||
return x->maxelem == y->maxelem
|
||||
&& x->timeout == y->timeout
|
||||
&& x->netmask == y->netmask;
|
||||
}
|
||||
|
||||
/* The type variant functions: IPv6 */
|
||||
|
||||
struct hash_ip6_elem {
|
||||
union nf_inet_addr ip;
|
||||
};
|
||||
|
||||
struct hash_ip6_telem {
|
||||
union nf_inet_addr ip;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
|
||||
const struct hash_ip6_elem *ip2)
|
||||
{
|
||||
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ip6_data_isnull(const struct hash_ip6_elem *elem)
|
||||
{
|
||||
return ipv6_addr_any(&elem->ip.in6);
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ip6_data_copy(struct hash_ip6_elem *dst, const struct hash_ip6_elem *src)
|
||||
{
|
||||
ipv6_addr_copy(&dst->ip.in6, &src->ip.in6);
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ip6_data_swap(struct hash_ip6_elem *dst, struct hash_ip6_elem *src)
|
||||
{
|
||||
struct in6_addr tmp;
|
||||
|
||||
ipv6_addr_copy(&tmp, &dst->ip.in6);
|
||||
ipv6_addr_copy(&dst->ip.in6, &src->ip.in6);
|
||||
ipv6_addr_copy(&src->ip.in6, &tmp);
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ip6_data_zero_out(struct hash_ip6_elem *elem)
|
||||
{
|
||||
ipv6_addr_set(&elem->ip.in6, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
|
||||
{
|
||||
ip->ip6[0] &= NETMASK6(prefix)[0];
|
||||
ip->ip6[1] &= NETMASK6(prefix)[1];
|
||||
ip->ip6[2] &= NETMASK6(prefix)[2];
|
||||
ip->ip6[3] &= NETMASK6(prefix)[3];
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ip6_data_tlist(struct sk_buff *skb, const struct hash_ip6_elem *data)
|
||||
{
|
||||
const struct hash_ip6_telem *e =
|
||||
(const struct hash_ip6_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(e->timeout)));
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef PF
|
||||
#undef HOST_MASK
|
||||
|
||||
#define PF 6
|
||||
#define HOST_MASK 128
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static int
|
||||
hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
union nf_inet_addr ip;
|
||||
|
||||
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip.in6);
|
||||
ip6_netmask(&ip, h->netmask);
|
||||
if (ipv6_addr_any(&ip.in6))
|
||||
return -EINVAL;
|
||||
|
||||
return adtfn(set, &ip, h->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ip6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
union nf_inet_addr ip;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
hash_ip6_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ip6_netmask(&ip, h->netmask);
|
||||
if (ipv6_addr_any(&ip.in6))
|
||||
return -IPSET_ERR_HASH_ELEM;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
ret = adtfn(set, &ip, timeout);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ip_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_NETMASK] = { .type = NLA_U8 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 netmask, hbits;
|
||||
struct ip_set_hash *h;
|
||||
|
||||
if (!(set->family == AF_INET || set->family == AF_INET6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
netmask = set->family == AF_INET ? 32 : 128;
|
||||
pr_debug("Create set %s with family %s",
|
||||
set->name, set->family == AF_INET ? "inet" : "inet6");
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
hash_ip_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_HASHSIZE]) {
|
||||
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
|
||||
if (hashsize < IPSET_MIMINAL_HASHSIZE)
|
||||
hashsize = IPSET_MIMINAL_HASHSIZE;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_MAXELEM])
|
||||
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
|
||||
|
||||
if (tb[IPSET_ATTR_NETMASK]) {
|
||||
netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
|
||||
|
||||
if ((set->family == AF_INET && netmask > 32)
|
||||
|| (set->family == AF_INET6 && netmask > 128)
|
||||
|| netmask == 0)
|
||||
return -IPSET_ERR_INVALID_NETMASK;
|
||||
}
|
||||
|
||||
h = kzalloc(sizeof(*h), GFP_KERNEL);
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->maxelem = maxelem;
|
||||
h->netmask = netmask;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table->htable_bits = hbits;
|
||||
|
||||
set->data = h;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = set->family == AF_INET
|
||||
? &hash_ip4_tvariant : &hash_ip6_tvariant;
|
||||
|
||||
if (set->family == AF_INET)
|
||||
hash_ip4_gc_init(set);
|
||||
else
|
||||
hash_ip6_gc_init(set);
|
||||
} else {
|
||||
set->variant = set->family == AF_INET
|
||||
? &hash_ip4_variant : &hash_ip6_variant;
|
||||
}
|
||||
|
||||
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
|
||||
set->name, jhash_size(h->table->htable_bits),
|
||||
h->table->htable_bits, h->maxelem, set->data, h->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type hash_ip_type __read_mostly = {
|
||||
.name = "hash:ip",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = hash_ip_create,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
hash_ip_init(void)
|
||||
{
|
||||
return ip_set_type_register(&hash_ip_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
hash_ip_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&hash_ip_type);
|
||||
}
|
||||
|
||||
module_init(hash_ip_init);
|
||||
module_exit(hash_ip_fini);
|
||||
569
extensions/ipset-5/ip_set_hash_ipport.c
Normal file
569
extensions/ipset-5/ip_set_hash_ipport.c
Normal file
@@ -0,0 +1,569 @@
|
||||
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the hash:ip,port type */
|
||||
|
||||
#include "ip_set_kernel.h"
|
||||
#include "jhash.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_getport.h"
|
||||
#include "ip_set_hash.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:ip,port type of IP sets");
|
||||
MODULE_ALIAS("ip_set_hash:ip,port");
|
||||
|
||||
/* Type specific function prefix */
|
||||
#define TYPE hash_ipport
|
||||
|
||||
static bool
|
||||
hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b);
|
||||
|
||||
#define hash_ipport4_same_set hash_ipport_same_set
|
||||
#define hash_ipport6_same_set hash_ipport_same_set
|
||||
|
||||
/* The type variant functions: IPv4 */
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_ipport4_elem {
|
||||
u32 ip;
|
||||
u16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
};
|
||||
|
||||
/* Member elements with timeout support */
|
||||
struct hash_ipport4_telem {
|
||||
u32 ip;
|
||||
u16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
|
||||
const struct hash_ipport4_elem *ip2)
|
||||
{
|
||||
return ip1->ip == ip2->ip
|
||||
&& ip1->port == ip2->port
|
||||
&& ip1->proto == ip2->proto;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipport4_data_isnull(const struct hash_ipport4_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipport4_data_copy(struct hash_ipport4_elem *dst,
|
||||
const struct hash_ipport4_elem *src)
|
||||
{
|
||||
dst->ip = src->ip;
|
||||
dst->port = src->port;
|
||||
dst->proto = src->proto;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipport4_data_swap(struct hash_ipport4_elem *dst,
|
||||
struct hash_ipport4_elem *src)
|
||||
{
|
||||
swap(dst->ip, src->ip);
|
||||
swap(dst->port, src->port);
|
||||
swap(dst->proto, src->proto);
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipport4_data_zero_out(struct hash_ipport4_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipport4_data_list(struct sk_buff *skb,
|
||||
const struct hash_ipport4_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipport4_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_ipport4_elem *data)
|
||||
{
|
||||
const struct hash_ipport4_telem *tdata =
|
||||
(const struct hash_ipport4_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(tdata->timeout)));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define PF 4
|
||||
#define HOST_MASK 32
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static int
|
||||
hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipport4_elem data = { };
|
||||
|
||||
if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ipport_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipport4_elem data = { };
|
||||
u32 ip, ip_to, p, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
hash_ipport_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMP:
|
||||
break;
|
||||
default:
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST
|
||||
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|
||||
|| !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR]
|
||||
|| tb[IPSET_ATTR_PORT_TO])) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
ip = ntohl(data.ip);
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
ip_to = ntohl(ip_to);
|
||||
if (ip > ip_to)
|
||||
swap(ip, ip_to);
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip &= HOSTMASK(cidr);
|
||||
ip_to = ip | ~HOSTMASK(cidr);
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
port = ntohs(data.port);
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
} else
|
||||
port_to = port;
|
||||
|
||||
for (; !before(ip_to, ip); ip++)
|
||||
for (p = port; p <= port_to; p++) {
|
||||
data.ip = htonl(ip);
|
||||
data.port = htons(p);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct ip_set_hash *x = a->data;
|
||||
const struct ip_set_hash *y = b->data;
|
||||
|
||||
/* Resizing changes htable_bits, so we ignore it */
|
||||
return x->maxelem == y->maxelem
|
||||
&& x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
/* The type variant functions: IPv6 */
|
||||
|
||||
struct hash_ipport6_elem {
|
||||
union nf_inet_addr ip;
|
||||
u16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
};
|
||||
|
||||
struct hash_ipport6_telem {
|
||||
union nf_inet_addr ip;
|
||||
u16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
|
||||
const struct hash_ipport6_elem *ip2)
|
||||
{
|
||||
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
|
||||
&& ip1->port == ip2->port
|
||||
&& ip1->proto == ip2->proto;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipport6_data_isnull(const struct hash_ipport6_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipport6_data_copy(struct hash_ipport6_elem *dst,
|
||||
const struct hash_ipport6_elem *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipport6_data_swap(struct hash_ipport6_elem *dst,
|
||||
struct hash_ipport6_elem *src)
|
||||
{
|
||||
struct hash_ipport6_elem tmp;
|
||||
|
||||
memcpy(&tmp, dst, sizeof(tmp));
|
||||
memcpy(dst, src, sizeof(tmp));
|
||||
memcpy(src, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipport6_data_zero_out(struct hash_ipport6_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipport6_data_list(struct sk_buff *skb,
|
||||
const struct hash_ipport6_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipport6_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_ipport6_elem *data)
|
||||
{
|
||||
const struct hash_ipport6_telem *e =
|
||||
(const struct hash_ipport6_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(e->timeout)));
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef PF
|
||||
#undef HOST_MASK
|
||||
|
||||
#define PF 6
|
||||
#define HOST_MASK 128
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static int
|
||||
hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipport6_elem data = { };
|
||||
|
||||
if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipport6_elem data = { };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
hash_ipport_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMPV6:
|
||||
break;
|
||||
default:
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST
|
||||
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|
||||
|| !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
port = ntohs(data.port);
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ipport_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
|
||||
if (!(set->family == AF_INET || set->family == AF_INET6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
hash_ipport_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_HASHSIZE]) {
|
||||
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
|
||||
if (hashsize < IPSET_MIMINAL_HASHSIZE)
|
||||
hashsize = IPSET_MIMINAL_HASHSIZE;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_MAXELEM])
|
||||
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
|
||||
|
||||
h = kzalloc(sizeof(*h), GFP_KERNEL);
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->maxelem = maxelem;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table->htable_bits = hbits;
|
||||
|
||||
set->data = h;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = set->family == AF_INET
|
||||
? &hash_ipport4_tvariant : &hash_ipport6_tvariant;
|
||||
|
||||
if (set->family == AF_INET)
|
||||
hash_ipport4_gc_init(set);
|
||||
else
|
||||
hash_ipport6_gc_init(set);
|
||||
} else {
|
||||
set->variant = set->family == AF_INET
|
||||
? &hash_ipport4_variant : &hash_ipport6_variant;
|
||||
}
|
||||
|
||||
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
|
||||
set->name, jhash_size(h->table->htable_bits),
|
||||
h->table->htable_bits, h->maxelem, set->data, h->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type hash_ipport_type __read_mostly = {
|
||||
.name = "hash:ip,port",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = hash_ipport_create,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
hash_ipport_init(void)
|
||||
{
|
||||
return ip_set_type_register(&hash_ipport_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
hash_ipport_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&hash_ipport_type);
|
||||
}
|
||||
|
||||
module_init(hash_ipport_init);
|
||||
module_exit(hash_ipport_fini);
|
||||
590
extensions/ipset-5/ip_set_hash_ipportip.c
Normal file
590
extensions/ipset-5/ip_set_hash_ipportip.c
Normal file
@@ -0,0 +1,590 @@
|
||||
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the hash:ip,port,ip type */
|
||||
|
||||
#include "ip_set_kernel.h"
|
||||
#include "jhash.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_getport.h"
|
||||
#include "ip_set_hash.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:ip,port,ip type of IP sets");
|
||||
MODULE_ALIAS("ip_set_hash:ip,port,ip");
|
||||
|
||||
/* Type specific function prefix */
|
||||
#define TYPE hash_ipportip
|
||||
|
||||
static bool
|
||||
hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b);
|
||||
|
||||
#define hash_ipportip4_same_set hash_ipportip_same_set
|
||||
#define hash_ipportip6_same_set hash_ipportip_same_set
|
||||
|
||||
/* The type variant functions: IPv4 */
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_ipportip4_elem {
|
||||
u32 ip;
|
||||
u32 ip2;
|
||||
u16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
};
|
||||
|
||||
/* Member elements with timeout support */
|
||||
struct hash_ipportip4_telem {
|
||||
u32 ip;
|
||||
u32 ip2;
|
||||
u16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
|
||||
const struct hash_ipportip4_elem *ip2)
|
||||
{
|
||||
return ip1->ip == ip2->ip
|
||||
&& ip1->ip2 == ip2->ip2
|
||||
&& ip1->port == ip2->port
|
||||
&& ip1->proto == ip2->proto;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportip4_data_isnull(const struct hash_ipportip4_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportip4_data_copy(struct hash_ipportip4_elem *dst,
|
||||
const struct hash_ipportip4_elem *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportip4_data_swap(struct hash_ipportip4_elem *dst,
|
||||
struct hash_ipportip4_elem *src)
|
||||
{
|
||||
struct hash_ipportip4_elem tmp;
|
||||
|
||||
memcpy(&tmp, dst, sizeof(tmp));
|
||||
memcpy(dst, src, sizeof(tmp));
|
||||
memcpy(src, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportip4_data_zero_out(struct hash_ipportip4_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportip4_data_list(struct sk_buff *skb,
|
||||
const struct hash_ipportip4_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportip4_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_ipportip4_elem *data)
|
||||
{
|
||||
const struct hash_ipportip4_telem *tdata =
|
||||
(const struct hash_ipportip4_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(tdata->timeout)));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define PF 4
|
||||
#define HOST_MASK 32
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static int
|
||||
hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportip4_elem data = { };
|
||||
|
||||
if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ipportip_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP2] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportip4_elem data = { };
|
||||
u32 ip, ip_to, p, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
hash_ipportip_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP2, &data.ip2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMP:
|
||||
break;
|
||||
default:
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST
|
||||
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|
||||
|| !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR]
|
||||
|| tb[IPSET_ATTR_PORT_TO])) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
ip = ntohl(data.ip);
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
ip_to = ntohl(ip_to);
|
||||
if (ip > ip_to)
|
||||
swap(ip, ip_to);
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip &= HOSTMASK(cidr);
|
||||
ip_to = ip | ~HOSTMASK(cidr);
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
port = ntohs(data.port);
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
} else
|
||||
port_to = port;
|
||||
|
||||
for (; !before(ip_to, ip); ip++)
|
||||
for (p = port; p <= port_to; p++) {
|
||||
data.ip = htonl(ip);
|
||||
data.port = htons(p);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct ip_set_hash *x = a->data;
|
||||
const struct ip_set_hash *y = b->data;
|
||||
|
||||
/* Resizing changes htable_bits, so we ignore it */
|
||||
return x->maxelem == y->maxelem
|
||||
&& x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
/* The type variant functions: IPv6 */
|
||||
|
||||
struct hash_ipportip6_elem {
|
||||
union nf_inet_addr ip;
|
||||
union nf_inet_addr ip2;
|
||||
u16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
};
|
||||
|
||||
struct hash_ipportip6_telem {
|
||||
union nf_inet_addr ip;
|
||||
union nf_inet_addr ip2;
|
||||
u16 port;
|
||||
u8 proto;
|
||||
u8 padding;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
|
||||
const struct hash_ipportip6_elem *ip2)
|
||||
{
|
||||
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
|
||||
&& ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0
|
||||
&& ip1->port == ip2->port
|
||||
&& ip1->proto == ip2->proto;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportip6_data_isnull(const struct hash_ipportip6_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportip6_data_copy(struct hash_ipportip6_elem *dst,
|
||||
const struct hash_ipportip6_elem *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportip6_data_swap(struct hash_ipportip6_elem *dst,
|
||||
struct hash_ipportip6_elem *src)
|
||||
{
|
||||
struct hash_ipportip6_elem tmp;
|
||||
|
||||
memcpy(&tmp, dst, sizeof(tmp));
|
||||
memcpy(dst, src, sizeof(tmp));
|
||||
memcpy(src, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportip6_data_zero_out(struct hash_ipportip6_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportip6_data_list(struct sk_buff *skb,
|
||||
const struct hash_ipportip6_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportip6_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_ipportip6_elem *data)
|
||||
{
|
||||
const struct hash_ipportip6_telem *e =
|
||||
(const struct hash_ipportip6_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(e->timeout)));
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef PF
|
||||
#undef HOST_MASK
|
||||
|
||||
#define PF 6
|
||||
#define HOST_MASK 128
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static int
|
||||
hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportip6_elem data = { };
|
||||
|
||||
if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportip6_elem data = { };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
hash_ipportip_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP2, &data.ip2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMPV6:
|
||||
break;
|
||||
default:
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST
|
||||
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|
||||
|| !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
port = ntohs(data.port);
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ipportip_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ipportip_create(struct ip_set *set, struct nlattr *head,
|
||||
int len, u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
|
||||
if (!(set->family == AF_INET || set->family == AF_INET6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
hash_ipportip_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_HASHSIZE]) {
|
||||
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
|
||||
if (hashsize < IPSET_MIMINAL_HASHSIZE)
|
||||
hashsize = IPSET_MIMINAL_HASHSIZE;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_MAXELEM])
|
||||
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
|
||||
|
||||
h = kzalloc(sizeof(*h), GFP_KERNEL);
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->maxelem = maxelem;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table->htable_bits = hbits;
|
||||
|
||||
set->data = h;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = set->family == AF_INET
|
||||
? &hash_ipportip4_tvariant : &hash_ipportip6_tvariant;
|
||||
|
||||
if (set->family == AF_INET)
|
||||
hash_ipportip4_gc_init(set);
|
||||
else
|
||||
hash_ipportip6_gc_init(set);
|
||||
} else {
|
||||
set->variant = set->family == AF_INET
|
||||
? &hash_ipportip4_variant : &hash_ipportip6_variant;
|
||||
}
|
||||
|
||||
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
|
||||
set->name, jhash_size(h->table->htable_bits),
|
||||
h->table->htable_bits, h->maxelem, set->data, h->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type hash_ipportip_type __read_mostly = {
|
||||
.name = "hash:ip,port,ip",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
|
||||
.dimension = IPSET_DIM_THREE,
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = hash_ipportip_create,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
hash_ipportip_init(void)
|
||||
{
|
||||
return ip_set_type_register(&hash_ipportip_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
hash_ipportip_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&hash_ipportip_type);
|
||||
}
|
||||
|
||||
module_init(hash_ipportip_init);
|
||||
module_exit(hash_ipportip_fini);
|
||||
656
extensions/ipset-5/ip_set_hash_ipportnet.c
Normal file
656
extensions/ipset-5/ip_set_hash_ipportnet.c
Normal file
@@ -0,0 +1,656 @@
|
||||
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the hash:ip,port,net type */
|
||||
|
||||
#include "ip_set_kernel.h"
|
||||
#include "jhash.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_getport.h"
|
||||
#include "ip_set_hash.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:ip,port,net type of IP sets");
|
||||
MODULE_ALIAS("ip_set_hash:ip,port,net");
|
||||
|
||||
/* Type specific function prefix */
|
||||
#define TYPE hash_ipportnet
|
||||
|
||||
static bool
|
||||
hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b);
|
||||
|
||||
#define hash_ipportnet4_same_set hash_ipportnet_same_set
|
||||
#define hash_ipportnet6_same_set hash_ipportnet_same_set
|
||||
|
||||
/* The type variant functions: IPv4 */
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_ipportnet4_elem {
|
||||
u32 ip;
|
||||
u32 ip2;
|
||||
u16 port;
|
||||
u8 cidr;
|
||||
u8 proto;
|
||||
};
|
||||
|
||||
/* Member elements with timeout support */
|
||||
struct hash_ipportnet4_telem {
|
||||
u32 ip;
|
||||
u32 ip2;
|
||||
u16 port;
|
||||
u8 cidr;
|
||||
u8 proto;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
|
||||
const struct hash_ipportnet4_elem *ip2)
|
||||
{
|
||||
return ip1->ip == ip2->ip
|
||||
&& ip1->ip2 == ip2->ip2
|
||||
&& ip1->cidr == ip2->cidr
|
||||
&& ip1->port == ip2->port
|
||||
&& ip1->proto == ip2->proto;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportnet4_data_isnull(const struct hash_ipportnet4_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst,
|
||||
const struct hash_ipportnet4_elem *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet4_data_swap(struct hash_ipportnet4_elem *dst,
|
||||
struct hash_ipportnet4_elem *src)
|
||||
{
|
||||
struct hash_ipportnet4_elem tmp;
|
||||
|
||||
memcpy(&tmp, dst, sizeof(tmp));
|
||||
memcpy(dst, src, sizeof(tmp));
|
||||
memcpy(src, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr)
|
||||
{
|
||||
elem->ip2 &= NETMASK(cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportnet4_data_list(struct sk_buff *skb,
|
||||
const struct hash_ipportnet4_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportnet4_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_ipportnet4_elem *data)
|
||||
{
|
||||
const struct hash_ipportnet4_telem *tdata =
|
||||
(const struct hash_ipportnet4_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(tdata->timeout)));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IP_SET_HASH_WITH_PROTO
|
||||
#define IP_SET_HASH_WITH_NETS
|
||||
|
||||
#define PF 4
|
||||
#define HOST_MASK 32
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static int
|
||||
hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportnet4_elem data =
|
||||
{ .cidr = h->nets[0].cidr || HOST_MASK };
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2);
|
||||
data.ip2 &= NETMASK(data.cidr);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ipportnet_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_IP2] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_CIDR2] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
|
||||
u32 ip, ip_to, p, port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
hash_ipportnet_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP2, &data.ip2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR2])
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
|
||||
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
|
||||
data.ip2 &= NETMASK(data.cidr);
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMP:
|
||||
break;
|
||||
default:
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST
|
||||
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|
||||
|| !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR]
|
||||
|| tb[IPSET_ATTR_PORT_TO])) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
ip = ntohl(data.ip);
|
||||
if (tb[IPSET_ATTR_IP_TO]) {
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP_TO, &ip_to);
|
||||
if (ret)
|
||||
return ret;
|
||||
ip_to = ntohl(ip_to);
|
||||
if (ip > ip_to)
|
||||
swap(ip, ip_to);
|
||||
} else if (tb[IPSET_ATTR_CIDR]) {
|
||||
u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (cidr > 32)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip &= HOSTMASK(cidr);
|
||||
ip_to = ip | ~HOSTMASK(cidr);
|
||||
} else
|
||||
ip_to = ip;
|
||||
|
||||
port = ntohs(data.port);
|
||||
if (tb[IPSET_ATTR_PORT_TO]) {
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
} else
|
||||
port_to = port;
|
||||
|
||||
for (; !before(ip_to, ip); ip++)
|
||||
for (p = port; p <= port_to; p++) {
|
||||
data.ip = htonl(ip);
|
||||
data.port = htons(p);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct ip_set_hash *x = a->data;
|
||||
const struct ip_set_hash *y = b->data;
|
||||
|
||||
/* Resizing changes htable_bits, so we ignore it */
|
||||
return x->maxelem == y->maxelem
|
||||
&& x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
/* The type variant functions: IPv6 */
|
||||
|
||||
struct hash_ipportnet6_elem {
|
||||
union nf_inet_addr ip;
|
||||
union nf_inet_addr ip2;
|
||||
u16 port;
|
||||
u8 cidr;
|
||||
u8 proto;
|
||||
};
|
||||
|
||||
struct hash_ipportnet6_telem {
|
||||
union nf_inet_addr ip;
|
||||
union nf_inet_addr ip2;
|
||||
u16 port;
|
||||
u8 cidr;
|
||||
u8 proto;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
|
||||
const struct hash_ipportnet6_elem *ip2)
|
||||
{
|
||||
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
|
||||
&& ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0
|
||||
&& ip1->cidr == ip2->cidr
|
||||
&& ip1->port == ip2->port
|
||||
&& ip1->proto == ip2->proto;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportnet6_data_isnull(const struct hash_ipportnet6_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst,
|
||||
const struct hash_ipportnet6_elem *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet6_data_swap(struct hash_ipportnet6_elem *dst,
|
||||
struct hash_ipportnet6_elem *src)
|
||||
{
|
||||
struct hash_ipportnet6_elem tmp;
|
||||
|
||||
memcpy(&tmp, dst, sizeof(tmp));
|
||||
memcpy(dst, src, sizeof(tmp));
|
||||
memcpy(src, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
|
||||
{
|
||||
ip->ip6[0] &= NETMASK6(prefix)[0];
|
||||
ip->ip6[1] &= NETMASK6(prefix)[1];
|
||||
ip->ip6[2] &= NETMASK6(prefix)[2];
|
||||
ip->ip6[3] &= NETMASK6(prefix)[3];
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr)
|
||||
{
|
||||
ip6_netmask(&elem->ip2, cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportnet6_data_list(struct sk_buff *skb,
|
||||
const struct hash_ipportnet6_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_ipportnet6_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_ipportnet6_elem *data)
|
||||
{
|
||||
const struct hash_ipportnet6_telem *e =
|
||||
(const struct hash_ipportnet6_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(e->timeout)));
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef PF
|
||||
#undef HOST_MASK
|
||||
|
||||
#define PF 6
|
||||
#define HOST_MASK 128
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static int
|
||||
hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportnet6_elem data =
|
||||
{ .cidr = h->nets[0].cidr || HOST_MASK };
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
|
||||
ip6_netmask(&data.ip2, data.cidr);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_ipportnet6_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
hash_ipportnet_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP2, &data.ip2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR2])
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
|
||||
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
|
||||
ip6_netmask(&data.ip2, data.cidr);
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMPV6:
|
||||
break;
|
||||
default:
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST
|
||||
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|
||||
|| !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
port = ntohs(data.port);
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
hash_ipportnet_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_ipportnet_create(struct ip_set *set, struct nlattr *head,
|
||||
int len, u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
|
||||
if (!(set->family == AF_INET || set->family == AF_INET6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
hash_ipportnet_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_HASHSIZE]) {
|
||||
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
|
||||
if (hashsize < IPSET_MIMINAL_HASHSIZE)
|
||||
hashsize = IPSET_MIMINAL_HASHSIZE;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_MAXELEM])
|
||||
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
|
||||
|
||||
h = kzalloc(sizeof(*h)
|
||||
+ sizeof(struct ip_set_hash_nets)
|
||||
* (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->maxelem = maxelem;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table->htable_bits = hbits;
|
||||
|
||||
set->data = h;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = set->family == AF_INET
|
||||
? &hash_ipportnet4_tvariant
|
||||
: &hash_ipportnet6_tvariant;
|
||||
|
||||
if (set->family == AF_INET)
|
||||
hash_ipportnet4_gc_init(set);
|
||||
else
|
||||
hash_ipportnet6_gc_init(set);
|
||||
} else {
|
||||
set->variant = set->family == AF_INET
|
||||
? &hash_ipportnet4_variant : &hash_ipportnet6_variant;
|
||||
}
|
||||
|
||||
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
|
||||
set->name, jhash_size(h->table->htable_bits),
|
||||
h->table->htable_bits, h->maxelem, set->data, h->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type hash_ipportnet_type __read_mostly = {
|
||||
.name = "hash:ip,port,net",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
|
||||
.dimension = IPSET_DIM_THREE,
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = hash_ipportnet_create,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
hash_ipportnet_init(void)
|
||||
{
|
||||
return ip_set_type_register(&hash_ipportnet_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
hash_ipportnet_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&hash_ipportnet_type);
|
||||
}
|
||||
|
||||
module_init(hash_ipportnet_init);
|
||||
module_exit(hash_ipportnet_fini);
|
||||
485
extensions/ipset-5/ip_set_hash_net.c
Normal file
485
extensions/ipset-5/ip_set_hash_net.c
Normal file
@@ -0,0 +1,485 @@
|
||||
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the hash:net type */
|
||||
|
||||
#include "ip_set_kernel.h"
|
||||
#include "jhash.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_hash.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:net type of IP sets");
|
||||
MODULE_ALIAS("ip_set_hash:net");
|
||||
|
||||
/* Type specific function prefix */
|
||||
#define TYPE hash_net
|
||||
|
||||
static bool
|
||||
hash_net_same_set(const struct ip_set *a, const struct ip_set *b);
|
||||
|
||||
#define hash_net4_same_set hash_net_same_set
|
||||
#define hash_net6_same_set hash_net_same_set
|
||||
|
||||
/* The type variant functions: IPv4 */
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_net4_elem {
|
||||
u32 ip;
|
||||
u16 padding0;
|
||||
u8 padding1;
|
||||
u8 cidr;
|
||||
};
|
||||
|
||||
/* Member elements with timeout support */
|
||||
struct hash_net4_telem {
|
||||
u32 ip;
|
||||
u16 padding0;
|
||||
u8 padding1;
|
||||
u8 cidr;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_net4_data_equal(const struct hash_net4_elem *ip1,
|
||||
const struct hash_net4_elem *ip2)
|
||||
{
|
||||
return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_net4_data_isnull(const struct hash_net4_elem *elem)
|
||||
{
|
||||
return elem->cidr == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_net4_data_copy(struct hash_net4_elem *dst,
|
||||
const struct hash_net4_elem *src)
|
||||
{
|
||||
dst->ip = src->ip;
|
||||
dst->cidr = src->cidr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_net4_data_swap(struct hash_net4_elem *dst,
|
||||
struct hash_net4_elem *src)
|
||||
{
|
||||
swap(dst->ip, src->ip);
|
||||
swap(dst->cidr, src->cidr);
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_net4_data_netmask(struct hash_net4_elem *elem, u8 cidr)
|
||||
{
|
||||
elem->ip &= NETMASK(cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
/* Zero CIDR values cannot be stored */
|
||||
static inline void
|
||||
hash_net4_data_zero_out(struct hash_net4_elem *elem)
|
||||
{
|
||||
elem->cidr = 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_net4_data_tlist(struct sk_buff *skb, const struct hash_net4_elem *data)
|
||||
{
|
||||
const struct hash_net4_telem *tdata =
|
||||
(const struct hash_net4_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, tdata->cidr);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(tdata->timeout)));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IP_SET_HASH_WITH_NETS
|
||||
|
||||
#define PF 4
|
||||
#define HOST_MASK 32
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static int
|
||||
hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_net4_elem data = { .cidr = h->nets[0].cidr || HOST_MASK };
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
data.ip &= NETMASK(data.cidr);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy hash_net_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_net4_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_net4_elem data = { .cidr = HOST_MASK };
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
hash_net_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR])
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
|
||||
data.ip &= NETMASK(data.cidr);
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_net_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct ip_set_hash *x = a->data;
|
||||
const struct ip_set_hash *y = b->data;
|
||||
|
||||
/* Resizing changes htable_bits, so we ignore it */
|
||||
return x->maxelem == y->maxelem
|
||||
&& x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
/* The type variant functions: IPv6 */
|
||||
|
||||
struct hash_net6_elem {
|
||||
union nf_inet_addr ip;
|
||||
u16 padding0;
|
||||
u8 padding1;
|
||||
u8 cidr;
|
||||
};
|
||||
|
||||
struct hash_net6_telem {
|
||||
union nf_inet_addr ip;
|
||||
u16 padding0;
|
||||
u8 padding1;
|
||||
u8 cidr;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_net6_data_equal(const struct hash_net6_elem *ip1,
|
||||
const struct hash_net6_elem *ip2)
|
||||
{
|
||||
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
|
||||
&& ip1->cidr == ip2->cidr;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_net6_data_isnull(const struct hash_net6_elem *elem)
|
||||
{
|
||||
return elem->cidr == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_net6_data_copy(struct hash_net6_elem *dst,
|
||||
const struct hash_net6_elem *src)
|
||||
{
|
||||
ipv6_addr_copy(&dst->ip.in6, &src->ip.in6);
|
||||
dst->cidr = src->cidr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_net6_data_swap(struct hash_net6_elem *dst, struct hash_net6_elem *src)
|
||||
{
|
||||
struct hash_net6_elem tmp;
|
||||
|
||||
memcpy(&tmp, dst, sizeof(tmp));
|
||||
memcpy(dst, src, sizeof(tmp));
|
||||
memcpy(src, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_net6_data_zero_out(struct hash_net6_elem *elem)
|
||||
{
|
||||
elem->cidr = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
|
||||
{
|
||||
ip->ip6[0] &= NETMASK6(prefix)[0];
|
||||
ip->ip6[1] &= NETMASK6(prefix)[1];
|
||||
ip->ip6[2] &= NETMASK6(prefix)[2];
|
||||
ip->ip6[3] &= NETMASK6(prefix)[3];
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_net6_data_netmask(struct hash_net6_elem *elem, u8 cidr)
|
||||
{
|
||||
ip6_netmask(&elem->ip, cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_net6_data_list(struct sk_buff *skb, const struct hash_net6_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_net6_data_tlist(struct sk_buff *skb, const struct hash_net6_elem *data)
|
||||
{
|
||||
const struct hash_net6_telem *e =
|
||||
(const struct hash_net6_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, e->cidr);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(e->timeout)));
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef PF
|
||||
#undef HOST_MASK
|
||||
|
||||
#define PF 6
|
||||
#define HOST_MASK 128
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static int
|
||||
hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_net6_elem data = { .cidr = h->nets[0].cidr || HOST_MASK };
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
ip6_netmask(&data.ip, data.cidr);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_net6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_net6_elem data = { .cidr = HOST_MASK };
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
hash_net_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR])
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
|
||||
ip6_netmask(&data.ip, data.cidr);
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
hash_net_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
struct ip_set_hash *h;
|
||||
u8 hbits;
|
||||
|
||||
if (!(set->family == AF_INET || set->family == AF_INET6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
hash_net_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_HASHSIZE]) {
|
||||
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
|
||||
if (hashsize < IPSET_MIMINAL_HASHSIZE)
|
||||
hashsize = IPSET_MIMINAL_HASHSIZE;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_MAXELEM])
|
||||
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
|
||||
|
||||
h = kzalloc(sizeof(*h)
|
||||
+ sizeof(struct ip_set_hash_nets)
|
||||
* (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->maxelem = maxelem;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table->htable_bits = hbits;
|
||||
|
||||
set->data = h;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = set->family == AF_INET
|
||||
? &hash_net4_tvariant : &hash_net6_tvariant;
|
||||
|
||||
if (set->family == AF_INET)
|
||||
hash_net4_gc_init(set);
|
||||
else
|
||||
hash_net6_gc_init(set);
|
||||
} else {
|
||||
set->variant = set->family == AF_INET
|
||||
? &hash_net4_variant : &hash_net6_variant;
|
||||
}
|
||||
|
||||
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
|
||||
set->name, jhash_size(h->table->htable_bits),
|
||||
h->table->htable_bits, h->maxelem, set->data, h->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type hash_net_type __read_mostly = {
|
||||
.name = "hash:net",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = hash_net_create,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
hash_net_init(void)
|
||||
{
|
||||
return ip_set_type_register(&hash_net_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
hash_net_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&hash_net_type);
|
||||
}
|
||||
|
||||
module_init(hash_net_init);
|
||||
module_exit(hash_net_fini);
|
||||
605
extensions/ipset-5/ip_set_hash_netport.c
Normal file
605
extensions/ipset-5/ip_set_hash_netport.c
Normal file
@@ -0,0 +1,605 @@
|
||||
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the hash:net,port type */
|
||||
|
||||
#include "ip_set_kernel.h"
|
||||
#include "jhash.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/random.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_getport.h"
|
||||
#include "ip_set_hash.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("hash:net,port type of IP sets");
|
||||
MODULE_ALIAS("ip_set_hash:net,port");
|
||||
|
||||
/* Type specific function prefix */
|
||||
#define TYPE hash_netport
|
||||
|
||||
static bool
|
||||
hash_netport_same_set(const struct ip_set *a, const struct ip_set *b);
|
||||
|
||||
#define hash_netport4_same_set hash_netport_same_set
|
||||
#define hash_netport6_same_set hash_netport_same_set
|
||||
|
||||
/* The type variant functions: IPv4 */
|
||||
|
||||
/* Member elements without timeout */
|
||||
struct hash_netport4_elem {
|
||||
u32 ip;
|
||||
u16 port;
|
||||
u8 proto;
|
||||
u8 cidr;
|
||||
};
|
||||
|
||||
/* Member elements with timeout support */
|
||||
struct hash_netport4_telem {
|
||||
u32 ip;
|
||||
u16 port;
|
||||
u8 proto;
|
||||
u8 cidr;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
|
||||
const struct hash_netport4_elem *ip2)
|
||||
{
|
||||
return ip1->ip == ip2->ip
|
||||
&& ip1->port == ip2->port
|
||||
&& ip1->proto == ip2->proto
|
||||
&& ip1->cidr == ip2->cidr;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_netport4_data_isnull(const struct hash_netport4_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport4_data_copy(struct hash_netport4_elem *dst,
|
||||
const struct hash_netport4_elem *src)
|
||||
{
|
||||
dst->ip = src->ip;
|
||||
dst->port = src->port;
|
||||
dst->proto = src->proto;
|
||||
dst->cidr = src->cidr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport4_data_swap(struct hash_netport4_elem *dst,
|
||||
struct hash_netport4_elem *src)
|
||||
{
|
||||
swap(dst->ip, src->ip);
|
||||
swap(dst->port, src->port);
|
||||
swap(dst->proto, src->proto);
|
||||
swap(dst->cidr, src->cidr);
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr)
|
||||
{
|
||||
elem->ip &= NETMASK(cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport4_data_zero_out(struct hash_netport4_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_netport4_data_list(struct sk_buff *skb,
|
||||
const struct hash_netport4_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_netport4_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_netport4_elem *data)
|
||||
{
|
||||
const struct hash_netport4_telem *tdata =
|
||||
(const struct hash_netport4_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(tdata->timeout)));
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define IP_SET_HASH_WITH_PROTO
|
||||
#define IP_SET_HASH_WITH_NETS
|
||||
|
||||
#define PF 4
|
||||
#define HOST_MASK 32
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static int
|
||||
hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netport4_elem data = {
|
||||
.cidr = h->nets[0].cidr || HOST_MASK };
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
if (!get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip);
|
||||
data.ip &= NETMASK(data.cidr);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static const struct nla_policy
|
||||
hash_netport_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
|
||||
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
|
||||
[IPSET_ATTR_PORT] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PORT_TO] = { .type = NLA_U16 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netport4_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
hash_netport_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr4(tb, IPSET_ATTR_IP, &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR])
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
data.ip &= NETMASK(data.cidr);
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMP:
|
||||
break;
|
||||
default:
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST
|
||||
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|
||||
|| !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
port = ntohs(data.port);
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
hash_netport_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct ip_set_hash *x = a->data;
|
||||
const struct ip_set_hash *y = b->data;
|
||||
|
||||
/* Resizing changes htable_bits, so we ignore it */
|
||||
return x->maxelem == y->maxelem
|
||||
&& x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
/* The type variant functions: IPv6 */
|
||||
|
||||
struct hash_netport6_elem {
|
||||
union nf_inet_addr ip;
|
||||
u16 port;
|
||||
u8 proto;
|
||||
u8 cidr;
|
||||
};
|
||||
|
||||
struct hash_netport6_telem {
|
||||
union nf_inet_addr ip;
|
||||
u16 port;
|
||||
u8 proto;
|
||||
u8 cidr;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
|
||||
const struct hash_netport6_elem *ip2)
|
||||
{
|
||||
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0
|
||||
&& ip1->port == ip2->port
|
||||
&& ip1->proto == ip2->proto
|
||||
&& ip1->cidr == ip2->cidr;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_netport6_data_isnull(const struct hash_netport6_elem *elem)
|
||||
{
|
||||
return elem->proto == 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport6_data_copy(struct hash_netport6_elem *dst,
|
||||
const struct hash_netport6_elem *src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(*dst));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport6_data_swap(struct hash_netport6_elem *dst,
|
||||
struct hash_netport6_elem *src)
|
||||
{
|
||||
struct hash_netport6_elem tmp;
|
||||
|
||||
memcpy(&tmp, dst, sizeof(tmp));
|
||||
memcpy(dst, src, sizeof(tmp));
|
||||
memcpy(src, &tmp, sizeof(tmp));
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport6_data_zero_out(struct hash_netport6_elem *elem)
|
||||
{
|
||||
elem->proto = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
|
||||
{
|
||||
ip->ip6[0] &= NETMASK6(prefix)[0];
|
||||
ip->ip6[1] &= NETMASK6(prefix)[1];
|
||||
ip->ip6[2] &= NETMASK6(prefix)[2];
|
||||
ip->ip6[3] &= NETMASK6(prefix)[3];
|
||||
}
|
||||
|
||||
static inline void
|
||||
hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr)
|
||||
{
|
||||
ip6_netmask(&elem->ip, cidr);
|
||||
elem->cidr = cidr;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_netport6_data_list(struct sk_buff *skb,
|
||||
const struct hash_netport6_elem *data)
|
||||
{
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
hash_netport6_data_tlist(struct sk_buff *skb,
|
||||
const struct hash_netport6_elem *data)
|
||||
{
|
||||
const struct hash_netport6_telem *e =
|
||||
(const struct hash_netport6_telem *)data;
|
||||
|
||||
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
|
||||
NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
|
||||
NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(e->timeout)));
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef PF
|
||||
#undef HOST_MASK
|
||||
|
||||
#define PF 6
|
||||
#define HOST_MASK 128
|
||||
#include "ip_set_ahash.h"
|
||||
|
||||
static int
|
||||
hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netport6_elem data = {
|
||||
.cidr = h->nets[0].cidr || HOST_MASK };
|
||||
|
||||
if (data.cidr == 0)
|
||||
return -EINVAL;
|
||||
if (adt == IPSET_TEST)
|
||||
data.cidr = HOST_MASK;
|
||||
|
||||
if (!get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC,
|
||||
&data.port, &data.proto))
|
||||
return -EINVAL;
|
||||
|
||||
ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
|
||||
ip6_netmask(&data.ip, data.cidr);
|
||||
|
||||
return adtfn(set, &data, h->timeout);
|
||||
}
|
||||
|
||||
static int
|
||||
hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
const struct ip_set_hash *h = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct hash_netport6_elem data = { .cidr = HOST_MASK };
|
||||
u32 port, port_to;
|
||||
u32 timeout = h->timeout;
|
||||
int ret;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
hash_netport_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
ret = ip_set_get_ipaddr6(tb, IPSET_ATTR_IP, &data.ip);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (tb[IPSET_ATTR_CIDR])
|
||||
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
|
||||
if (!data.cidr)
|
||||
return -IPSET_ERR_INVALID_CIDR;
|
||||
ip6_netmask(&data.ip, data.cidr);
|
||||
|
||||
if (tb[IPSET_ATTR_PORT])
|
||||
data.port = ip_set_get_n16(tb[IPSET_ATTR_PORT]);
|
||||
else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_PROTO]) {
|
||||
data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
|
||||
|
||||
if (data.proto == 0)
|
||||
return -IPSET_ERR_INVALID_PROTO;
|
||||
} else
|
||||
return -IPSET_ERR_MISSING_PROTO;
|
||||
|
||||
switch (data.proto) {
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_ICMPV6:
|
||||
break;
|
||||
default:
|
||||
data.port = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout(h->timeout))
|
||||
return -IPSET_ERR_TIMEOUT;
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
if (adt == IPSET_TEST
|
||||
|| !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP)
|
||||
|| !tb[IPSET_ATTR_PORT_TO]) {
|
||||
ret = adtfn(set, &data, timeout);
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
port = ntohs(data.port);
|
||||
port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
|
||||
if (port > port_to)
|
||||
swap(port, port_to);
|
||||
|
||||
for (; port <= port_to; port++) {
|
||||
data.port = htons(port);
|
||||
ret = adtfn(set, &data, timeout);
|
||||
|
||||
if (ret && !ip_set_eexist(ret, flags))
|
||||
return ret;
|
||||
else
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Create hash:ip type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
hash_netport_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int
|
||||
hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
struct ip_set_hash *h;
|
||||
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
|
||||
u8 hbits;
|
||||
|
||||
if (!(set->family == AF_INET || set->family == AF_INET6))
|
||||
return -IPSET_ERR_INVALID_FAMILY;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
hash_netport_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_HASHSIZE]) {
|
||||
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
|
||||
if (hashsize < IPSET_MIMINAL_HASHSIZE)
|
||||
hashsize = IPSET_MIMINAL_HASHSIZE;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_MAXELEM])
|
||||
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
|
||||
|
||||
h = kzalloc(sizeof(*h)
|
||||
+ sizeof(struct ip_set_hash_nets)
|
||||
* (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
|
||||
if (!h)
|
||||
return -ENOMEM;
|
||||
|
||||
h->maxelem = maxelem;
|
||||
get_random_bytes(&h->initval, sizeof(h->initval));
|
||||
h->timeout = IPSET_NO_TIMEOUT;
|
||||
|
||||
hbits = htable_bits(hashsize);
|
||||
h->table = ip_set_alloc(
|
||||
sizeof(struct htable)
|
||||
+ jhash_size(hbits) * sizeof(struct hbucket),
|
||||
GFP_KERNEL);
|
||||
if (!h->table) {
|
||||
kfree(h);
|
||||
return -ENOMEM;
|
||||
}
|
||||
h->table->htable_bits = hbits;
|
||||
|
||||
set->data = h;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
|
||||
set->variant = set->family == AF_INET
|
||||
? &hash_netport4_tvariant : &hash_netport6_tvariant;
|
||||
|
||||
if (set->family == AF_INET)
|
||||
hash_netport4_gc_init(set);
|
||||
else
|
||||
hash_netport6_gc_init(set);
|
||||
} else {
|
||||
set->variant = set->family == AF_INET
|
||||
? &hash_netport4_variant : &hash_netport6_variant;
|
||||
}
|
||||
|
||||
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)",
|
||||
set->name, jhash_size(h->table->htable_bits),
|
||||
h->table->htable_bits, h->maxelem, set->data, h->table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type hash_netport_type __read_mostly = {
|
||||
.name = "hash:net,port",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = hash_netport_create,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
hash_netport_init(void)
|
||||
{
|
||||
return ip_set_type_register(&hash_netport_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
hash_netport_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&hash_netport_type);
|
||||
}
|
||||
|
||||
module_init(hash_netport_init);
|
||||
module_exit(hash_netport_fini);
|
||||
15
extensions/ipset-5/ip_set_kernel.h
Normal file
15
extensions/ipset-5/ip_set_kernel.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef _IP_SET_KERNEL_H
|
||||
#define _IP_SET_KERNEL_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#ifdef CONFIG_DEBUG_KERNEL
|
||||
/* Complete debug messages */
|
||||
#define pr_fmt(fmt) "%s %s[%i]: " fmt "\n", __FILE__, __func__, __LINE__
|
||||
#endif
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /*_IP_SET_H */
|
||||
27
extensions/ipset-5/ip_set_list.h
Normal file
27
extensions/ipset-5/ip_set_list.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef __IP_SET_LIST_H
|
||||
#define __IP_SET_LIST_H
|
||||
|
||||
/* List type specific error codes */
|
||||
enum {
|
||||
/* Set name to be added/deleted/tested does not exist. */
|
||||
IPSET_ERR_NAME = IPSET_ERR_TYPE_SPECIFIC,
|
||||
/* list:set type is not permitted to add */
|
||||
IPSET_ERR_LOOP,
|
||||
/* Missing reference set */
|
||||
IPSET_ERR_BEFORE,
|
||||
/* Reference set does not exist */
|
||||
IPSET_ERR_NAMEREF,
|
||||
/* Set is full */
|
||||
IPSET_ERR_LIST_FULL,
|
||||
/* Reference set is not added to the set */
|
||||
IPSET_ERR_REF_EXIST,
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define IP_SET_LIST_DEFAULT_SIZE 8
|
||||
#define IP_SET_LIST_MIN_SIZE 4
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* __IP_SET_LIST_H */
|
||||
589
extensions/ipset-5/ip_set_list_set.c
Normal file
589
extensions/ipset-5/ip_set_list_set.c
Normal file
@@ -0,0 +1,589 @@
|
||||
/* Copyright (C) 2008-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module implementing an IP set type: the list:set type */
|
||||
|
||||
#include "ip_set_kernel.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/errno.h>
|
||||
|
||||
#include "ip_set.h"
|
||||
#include "ip_set_timeout.h"
|
||||
#include "ip_set_list.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("list:set type of IP sets");
|
||||
MODULE_ALIAS("ip_set_list:set");
|
||||
|
||||
/* Member elements without and with timeout */
|
||||
struct set_elem {
|
||||
ip_set_id_t id;
|
||||
};
|
||||
|
||||
struct set_telem {
|
||||
ip_set_id_t id;
|
||||
unsigned long timeout;
|
||||
};
|
||||
|
||||
/* Type structure */
|
||||
struct list_set {
|
||||
size_t dsize; /* element size */
|
||||
u32 size; /* size of set list array */
|
||||
u32 timeout; /* timeout value */
|
||||
struct timer_list gc; /* garbage collection */
|
||||
struct set_elem members[0]; /* the set members */
|
||||
};
|
||||
|
||||
static inline struct set_elem *
|
||||
list_set_elem(const struct list_set *map, u32 id)
|
||||
{
|
||||
return (struct set_elem *)((char *)map->members + id * map->dsize);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
list_set_timeout(const struct list_set *map, u32 id)
|
||||
{
|
||||
const struct set_telem *elem =
|
||||
(const struct set_telem *) list_set_elem(map, id);
|
||||
|
||||
return ip_set_timeout_test(elem->timeout);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
list_set_expired(const struct list_set *map, u32 id)
|
||||
{
|
||||
const struct set_telem *elem =
|
||||
(const struct set_telem *) list_set_elem(map, id);
|
||||
|
||||
return ip_set_timeout_expired(elem->timeout);
|
||||
}
|
||||
|
||||
static inline int
|
||||
list_set_exist(const struct set_telem *elem)
|
||||
{
|
||||
return elem->id != IPSET_INVALID_ID
|
||||
&& !ip_set_timeout_expired(elem->timeout);
|
||||
}
|
||||
|
||||
/* Set list without and with timeout */
|
||||
|
||||
static int
|
||||
list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
enum ipset_adt adt, u8 pf, u8 dim, u8 flags)
|
||||
{
|
||||
struct list_set *map = set->data;
|
||||
struct set_elem *elem;
|
||||
u32 i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < map->size; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
if (elem->id == IPSET_INVALID_ID)
|
||||
return 0;
|
||||
if (with_timeout(map->timeout) && list_set_expired(map, i))
|
||||
continue;
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
ret = ip_set_test(elem->id, skb, pf, dim, flags);
|
||||
if (ret > 0)
|
||||
return ret;
|
||||
break;
|
||||
case IPSET_ADD:
|
||||
ret = ip_set_add(elem->id, skb, pf, dim, flags);
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
break;
|
||||
case IPSET_DEL:
|
||||
ret = ip_set_del(elem->id, skb, pf, dim, flags);
|
||||
if (ret == 0)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct nla_policy list_set_adt_policy[IPSET_ATTR_ADT_MAX+1] = {
|
||||
[IPSET_ATTR_NAME] = { .type = NLA_STRING,
|
||||
.len = IPSET_MAXNAMELEN },
|
||||
[IPSET_ATTR_NAMEREF] = { .type = NLA_STRING,
|
||||
.len = IPSET_MAXNAMELEN },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static inline bool
|
||||
next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id)
|
||||
{
|
||||
const struct set_elem *elem;
|
||||
|
||||
if (i + 1 < map->size) {
|
||||
elem = list_set_elem(map, i + 1);
|
||||
return !!(elem->id == id
|
||||
&& !(with_timeout(map->timeout)
|
||||
&& list_set_expired(map, i + 1)));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_elem_add(struct list_set *map, u32 i, ip_set_id_t id)
|
||||
{
|
||||
struct set_elem *e;
|
||||
|
||||
for (; i < map->size; i++) {
|
||||
e = list_set_elem(map, i);
|
||||
swap(e->id, id);
|
||||
if (e->id == IPSET_INVALID_ID)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id,
|
||||
unsigned long timeout)
|
||||
{
|
||||
struct set_telem *e;
|
||||
|
||||
for (; i < map->size; i++) {
|
||||
e = (struct set_telem *)list_set_elem(map, i);
|
||||
swap(e->id, id);
|
||||
if (e->id == IPSET_INVALID_ID)
|
||||
break;
|
||||
swap(e->timeout, timeout);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
|
||||
unsigned long timeout)
|
||||
{
|
||||
const struct set_elem *e = list_set_elem(map, i);
|
||||
|
||||
if (i == map->size - 1 && e->id != IPSET_INVALID_ID)
|
||||
/* Last element replaced: e.g. add new,before,last */
|
||||
ip_set_put_byindex(e->id);
|
||||
if (with_timeout(map->timeout))
|
||||
list_elem_tadd(map, i, id, timeout);
|
||||
else
|
||||
list_elem_add(map, i, id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_del(struct list_set *map, ip_set_id_t id, u32 i)
|
||||
{
|
||||
struct set_elem *a = list_set_elem(map, i), *b;
|
||||
|
||||
ip_set_put_byindex(id);
|
||||
|
||||
for (; i < map->size - 1; i++) {
|
||||
b = list_set_elem(map, i + 1);
|
||||
a->id = b->id;
|
||||
if (with_timeout(map->timeout))
|
||||
((struct set_telem *)a)->timeout =
|
||||
((struct set_telem *)b)->timeout;
|
||||
a = b;
|
||||
if (a->id == IPSET_INVALID_ID)
|
||||
break;
|
||||
}
|
||||
/* Last element */
|
||||
a->id = IPSET_INVALID_ID;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_uadt(struct ip_set *set, struct nlattr *head, int len,
|
||||
enum ipset_adt adt, u32 *lineno, u32 flags)
|
||||
{
|
||||
struct list_set *map = set->data;
|
||||
struct nlattr *tb[IPSET_ATTR_ADT_MAX+1];
|
||||
bool with_timeout = with_timeout(map->timeout);
|
||||
int before = 0;
|
||||
u32 timeout = map->timeout;
|
||||
ip_set_id_t id, refid = IPSET_INVALID_ID;
|
||||
const struct set_elem *elem;
|
||||
struct ip_set *s;
|
||||
u32 i;
|
||||
int ret = 0;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len,
|
||||
list_set_adt_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_LINENO])
|
||||
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
|
||||
|
||||
if (tb[IPSET_ATTR_NAME]) {
|
||||
id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s);
|
||||
if (id == IPSET_INVALID_ID)
|
||||
return -IPSET_ERR_NAME;
|
||||
/* "Loop detection" */
|
||||
if (s->type->features & IPSET_TYPE_NAME) {
|
||||
ret = -IPSET_ERR_LOOP;
|
||||
goto finish;
|
||||
}
|
||||
} else
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_CADT_FLAGS]) {
|
||||
u32 f = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
|
||||
before = f & IPSET_FLAG_BEFORE;
|
||||
}
|
||||
|
||||
if (before && !tb[IPSET_ATTR_NAMEREF]) {
|
||||
ret = -IPSET_ERR_BEFORE;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (tb[IPSET_ATTR_NAMEREF]) {
|
||||
refid = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAMEREF]),
|
||||
&s);
|
||||
if (refid == IPSET_INVALID_ID) {
|
||||
ret = -IPSET_ERR_NAMEREF;
|
||||
goto finish;
|
||||
}
|
||||
if (!before)
|
||||
before = -1;
|
||||
}
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!with_timeout) {
|
||||
ret = -IPSET_ERR_TIMEOUT;
|
||||
goto finish;
|
||||
}
|
||||
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
|
||||
}
|
||||
|
||||
switch (adt) {
|
||||
case IPSET_TEST:
|
||||
for (i = 0; i < map->size && !ret; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
if (elem->id == IPSET_INVALID_ID
|
||||
|| (before != 0 && i + 1 >= map->size))
|
||||
break;
|
||||
else if (with_timeout && list_set_expired(map, i))
|
||||
continue;
|
||||
else if (before > 0 && elem->id == id)
|
||||
ret = next_id_eq(map, i, refid);
|
||||
else if (before < 0 && elem->id == refid)
|
||||
ret = next_id_eq(map, i, id);
|
||||
else if (before == 0 && elem->id == id)
|
||||
ret = 1;
|
||||
}
|
||||
break;
|
||||
case IPSET_ADD:
|
||||
for (i = 0; i < map->size && !ret; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
if (elem->id == id
|
||||
&& !(with_timeout && list_set_expired(map, i)))
|
||||
ret = -IPSET_ERR_EXIST;
|
||||
}
|
||||
if (ret == -IPSET_ERR_EXIST)
|
||||
break;
|
||||
ret = -IPSET_ERR_LIST_FULL;
|
||||
for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
if (elem->id == IPSET_INVALID_ID)
|
||||
ret = before != 0 ? -IPSET_ERR_REF_EXIST
|
||||
: list_set_add(map, i, id, timeout);
|
||||
else if (elem->id != refid)
|
||||
continue;
|
||||
else if (with_timeout && list_set_expired(map, i))
|
||||
ret = -IPSET_ERR_REF_EXIST;
|
||||
else if (before)
|
||||
ret = list_set_add(map, i, id, timeout);
|
||||
else if (i + 1 < map->size)
|
||||
ret = list_set_add(map, i + 1, id, timeout);
|
||||
}
|
||||
break;
|
||||
case IPSET_DEL:
|
||||
ret = -IPSET_ERR_EXIST;
|
||||
for (i = 0; i < map->size && ret == -IPSET_ERR_EXIST; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
if (elem->id == IPSET_INVALID_ID) {
|
||||
ret = before != 0 ? -IPSET_ERR_REF_EXIST
|
||||
: -IPSET_ERR_EXIST;
|
||||
break;
|
||||
} else if (with_timeout && list_set_expired(map, i))
|
||||
continue;
|
||||
else if (elem->id == id
|
||||
&& (before == 0
|
||||
|| (before > 0
|
||||
&& next_id_eq(map, i, refid))))
|
||||
ret = list_set_del(map, id, i);
|
||||
else if (before < 0
|
||||
&& elem->id == refid
|
||||
&& next_id_eq(map, i, id))
|
||||
ret = list_set_del(map, id, i + 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
finish:
|
||||
if (refid != IPSET_INVALID_ID)
|
||||
ip_set_put_byindex(refid);
|
||||
if (adt != IPSET_ADD || ret)
|
||||
ip_set_put_byindex(id);
|
||||
|
||||
return ip_set_eexist(ret, flags) ? 0 : ret;
|
||||
}
|
||||
|
||||
static void
|
||||
list_set_flush(struct ip_set *set)
|
||||
{
|
||||
struct list_set *map = set->data;
|
||||
struct set_elem *elem;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < map->size; i++) {
|
||||
elem = list_set_elem(map, i);
|
||||
if (elem->id != IPSET_INVALID_ID) {
|
||||
ip_set_put_byindex(elem->id);
|
||||
elem->id = IPSET_INVALID_ID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
list_set_destroy(struct ip_set *set)
|
||||
{
|
||||
struct list_set *map = set->data;
|
||||
|
||||
if (with_timeout(map->timeout))
|
||||
del_timer_sync(&map->gc);
|
||||
list_set_flush(set);
|
||||
kfree(map);
|
||||
|
||||
set->data = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_head(struct ip_set *set, struct sk_buff *skb)
|
||||
{
|
||||
const struct list_set *map = set->data;
|
||||
struct nlattr *nested;
|
||||
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size));
|
||||
if (with_timeout(map->timeout))
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
|
||||
htonl(atomic_read(&set->ref) - 1));
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
|
||||
htonl(sizeof(*map) + map->size * map->dsize));
|
||||
ipset_nest_end(skb, nested);
|
||||
|
||||
return 0;
|
||||
nla_put_failure:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_list(const struct ip_set *set,
|
||||
struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
const struct list_set *map = set->data;
|
||||
struct nlattr *atd, *nested;
|
||||
u32 i, first = cb->args[2];
|
||||
const struct set_elem *e;
|
||||
|
||||
atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
|
||||
if (!atd)
|
||||
return -EFAULT;
|
||||
for (; cb->args[2] < map->size; cb->args[2]++) {
|
||||
i = cb->args[2];
|
||||
e = list_set_elem(map, i);
|
||||
if (e->id == IPSET_INVALID_ID)
|
||||
goto finish;
|
||||
if (with_timeout(map->timeout) && list_set_expired(map, i))
|
||||
continue;
|
||||
nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
|
||||
if (!nested) {
|
||||
if (i == first) {
|
||||
nla_nest_cancel(skb, atd);
|
||||
return -EFAULT;
|
||||
} else
|
||||
goto nla_put_failure;
|
||||
}
|
||||
NLA_PUT_STRING(skb, IPSET_ATTR_NAME,
|
||||
ip_set_name_byindex(e->id));
|
||||
if (with_timeout(map->timeout)) {
|
||||
const struct set_telem *te =
|
||||
(const struct set_telem *) e;
|
||||
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
|
||||
htonl(ip_set_timeout_get(te->timeout)));
|
||||
}
|
||||
ipset_nest_end(skb, nested);
|
||||
}
|
||||
finish:
|
||||
ipset_nest_end(skb, atd);
|
||||
/* Set listing finished */
|
||||
cb->args[2] = 0;
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nla_nest_cancel(skb, nested);
|
||||
ipset_nest_end(skb, atd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
list_set_same_set(const struct ip_set *a, const struct ip_set *b)
|
||||
{
|
||||
const struct list_set *x = a->data;
|
||||
const struct list_set *y = b->data;
|
||||
|
||||
return x->size == y->size
|
||||
&& x->timeout == y->timeout;
|
||||
}
|
||||
|
||||
static const struct ip_set_type_variant list_set = {
|
||||
.kadt = list_set_kadt,
|
||||
.uadt = list_set_uadt,
|
||||
.destroy = list_set_destroy,
|
||||
.flush = list_set_flush,
|
||||
.head = list_set_head,
|
||||
.list = list_set_list,
|
||||
.same_set = list_set_same_set,
|
||||
};
|
||||
|
||||
static void
|
||||
list_set_gc(unsigned long ul_set)
|
||||
{
|
||||
struct ip_set *set = (struct ip_set *) ul_set;
|
||||
struct list_set *map = set->data;
|
||||
struct set_telem *e;
|
||||
u32 i;
|
||||
|
||||
/* We run parallel with other readers (test element)
|
||||
* but adding/deleting new entries is locked out */
|
||||
read_lock_bh(&set->lock);
|
||||
for (i = map->size - 1; i >= 0; i--) {
|
||||
e = (struct set_telem *) list_set_elem(map, i);
|
||||
if (e->id != IPSET_INVALID_ID
|
||||
&& list_set_expired(map, i))
|
||||
list_set_del(map, e->id, i);
|
||||
}
|
||||
read_unlock_bh(&set->lock);
|
||||
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
static inline void
|
||||
list_set_gc_init(struct ip_set *set)
|
||||
{
|
||||
struct list_set *map = set->data;
|
||||
|
||||
init_timer(&map->gc);
|
||||
map->gc.data = (unsigned long) set;
|
||||
map->gc.function = list_set_gc;
|
||||
map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
|
||||
add_timer(&map->gc);
|
||||
}
|
||||
|
||||
/* Create list:set type of sets */
|
||||
|
||||
static const struct nla_policy
|
||||
list_set_create_policy[IPSET_ATTR_CREATE_MAX+1] = {
|
||||
[IPSET_ATTR_SIZE] = { .type = NLA_U32 },
|
||||
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static inline bool
|
||||
init_list_set(struct ip_set *set, u32 size, size_t dsize,
|
||||
unsigned long timeout)
|
||||
{
|
||||
struct list_set *map;
|
||||
struct set_elem *e;
|
||||
u32 i;
|
||||
|
||||
map = kzalloc(sizeof(*map) + size * dsize, GFP_KERNEL);
|
||||
if (!map)
|
||||
return false;
|
||||
|
||||
map->size = size;
|
||||
map->dsize = dsize;
|
||||
map->timeout = timeout;
|
||||
set->data = map;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
e = list_set_elem(map, i);
|
||||
e->id = IPSET_INVALID_ID;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
list_set_create(struct ip_set *set, struct nlattr *head, int len,
|
||||
u32 flags)
|
||||
{
|
||||
struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1];
|
||||
u32 size = IP_SET_LIST_DEFAULT_SIZE;
|
||||
|
||||
if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len,
|
||||
list_set_create_policy))
|
||||
return -IPSET_ERR_PROTOCOL;
|
||||
|
||||
if (tb[IPSET_ATTR_SIZE])
|
||||
size = ip_set_get_h32(tb[IPSET_ATTR_SIZE]);
|
||||
if (size < IP_SET_LIST_MIN_SIZE)
|
||||
size = IP_SET_LIST_MIN_SIZE;
|
||||
|
||||
if (tb[IPSET_ATTR_TIMEOUT]) {
|
||||
if (!init_list_set(set, size, sizeof(struct set_telem),
|
||||
ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT])))
|
||||
return -ENOMEM;
|
||||
|
||||
list_set_gc_init(set);
|
||||
} else {
|
||||
if (!init_list_set(set, size, sizeof(struct set_elem),
|
||||
IPSET_NO_TIMEOUT))
|
||||
return -ENOMEM;
|
||||
}
|
||||
set->variant = &list_set;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ip_set_type list_set_type __read_mostly = {
|
||||
.name = "list:set",
|
||||
.protocol = IPSET_PROTOCOL,
|
||||
.features = IPSET_TYPE_NAME | IPSET_DUMP_LAST,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.family = AF_UNSPEC,
|
||||
.revision = 0,
|
||||
.create = list_set_create,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init
|
||||
list_set_init(void)
|
||||
{
|
||||
return ip_set_type_register(&list_set_type);
|
||||
}
|
||||
|
||||
static void __exit
|
||||
list_set_fini(void)
|
||||
{
|
||||
ip_set_type_unregister(&list_set_type);
|
||||
}
|
||||
|
||||
module_init(list_set_init);
|
||||
module_exit(list_set_fini);
|
||||
127
extensions/ipset-5/ip_set_timeout.h
Normal file
127
extensions/ipset-5/ip_set_timeout.h
Normal file
@@ -0,0 +1,127 @@
|
||||
#ifndef _IP_SET_TIMEOUT_H
|
||||
#define _IP_SET_TIMEOUT_H
|
||||
|
||||
/* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
/* How often should the gc be run by default */
|
||||
#define IPSET_GC_TIME (3 * 60)
|
||||
|
||||
/* Timeout period depending on the timeout value of the given set */
|
||||
#define IPSET_GC_PERIOD(timeout) \
|
||||
((timeout/3) ? min_t(u32, (timeout)/3, IPSET_GC_TIME) : 1)
|
||||
|
||||
/* Set is defined without timeout support: timeout value may be 0 */
|
||||
#define IPSET_NO_TIMEOUT UINT_MAX
|
||||
|
||||
#define with_timeout(timeout) ((timeout) != IPSET_NO_TIMEOUT)
|
||||
|
||||
static inline unsigned int
|
||||
ip_set_timeout_uget(struct nlattr *tb)
|
||||
{
|
||||
unsigned int timeout = ip_set_get_h32(tb);
|
||||
|
||||
/* Userspace supplied TIMEOUT parameter: adjust crazy size */
|
||||
return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout;
|
||||
}
|
||||
|
||||
#ifdef IP_SET_BITMAP_TIMEOUT
|
||||
|
||||
/* Bitmap specific timeout constants and macros for the entries */
|
||||
|
||||
/* Bitmap entry is unset */
|
||||
#define IPSET_ELEM_UNSET 0
|
||||
/* Bitmap entry is set with no timeout value */
|
||||
#define IPSET_ELEM_PERMANENT (UINT_MAX/2)
|
||||
|
||||
static inline bool
|
||||
ip_set_timeout_test(unsigned long timeout)
|
||||
{
|
||||
return timeout != IPSET_ELEM_UNSET
|
||||
&& (timeout == IPSET_ELEM_PERMANENT
|
||||
|| time_after(timeout, jiffies));
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ip_set_timeout_expired(unsigned long timeout)
|
||||
{
|
||||
return timeout != IPSET_ELEM_UNSET
|
||||
&& timeout != IPSET_ELEM_PERMANENT
|
||||
&& time_before(timeout, jiffies);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
ip_set_timeout_set(u32 timeout)
|
||||
{
|
||||
unsigned long t;
|
||||
|
||||
if (!timeout)
|
||||
return IPSET_ELEM_PERMANENT;
|
||||
|
||||
t = timeout * HZ + jiffies;
|
||||
if (t == IPSET_ELEM_UNSET || t == IPSET_ELEM_PERMANENT)
|
||||
/* Bingo! */
|
||||
t++;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
ip_set_timeout_get(unsigned long timeout)
|
||||
{
|
||||
return timeout == IPSET_ELEM_PERMANENT ? 0 : (timeout - jiffies)/HZ;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Hash specific timeout constants and macros for the entries */
|
||||
|
||||
/* Hash entry is set with no timeout value */
|
||||
#define IPSET_ELEM_PERMANENT 0
|
||||
|
||||
static inline bool
|
||||
ip_set_timeout_test(unsigned long timeout)
|
||||
{
|
||||
return timeout == IPSET_ELEM_PERMANENT
|
||||
|| time_after(timeout, jiffies);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
ip_set_timeout_expired(unsigned long timeout)
|
||||
{
|
||||
return timeout != IPSET_ELEM_PERMANENT
|
||||
&& time_before(timeout, jiffies);
|
||||
}
|
||||
|
||||
static inline unsigned long
|
||||
ip_set_timeout_set(u32 timeout)
|
||||
{
|
||||
unsigned long t;
|
||||
|
||||
if (!timeout)
|
||||
return IPSET_ELEM_PERMANENT;
|
||||
|
||||
t = timeout * HZ + jiffies;
|
||||
if (t == IPSET_ELEM_PERMANENT)
|
||||
/* Bingo! :-) */
|
||||
t++;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static inline u32
|
||||
ip_set_timeout_get(unsigned long timeout)
|
||||
{
|
||||
return timeout == IPSET_ELEM_PERMANENT ? 0 : (timeout - jiffies)/HZ;
|
||||
}
|
||||
#endif /* ! IP_SET_BITMAP_TIMEOUT */
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _IP_SET_TIMEOUT_H */
|
||||
748
extensions/ipset-5/ipset.8
Normal file
748
extensions/ipset-5/ipset.8
Normal file
@@ -0,0 +1,748 @@
|
||||
.\" Man page written by Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
.\"
|
||||
.\" This program is free software; you can redistribute it and/or modify
|
||||
.\" it under the terms of the GNU General Public License as published by
|
||||
.\" the Free Software Foundation; either version 2 of the License, or
|
||||
.\" (at your option) any later version.
|
||||
.\"
|
||||
.\" This program is distributed in the hope that it will be useful,
|
||||
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
.\" GNU General Public License for more details.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU General Public License
|
||||
.\" along with this program; if not, write to the Free Software
|
||||
.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
.TH "IPSET" "8" "Oct 15, 2010" "Jozsef Kadlecsik" ""
|
||||
.SH "NAME"
|
||||
ipset \(em administration tool for IP sets
|
||||
.SH "SYNOPSIS"
|
||||
\fBipset\fR [ \fIOPTIONS\fR ] \fICOMMAND\fR [ \fICOMMAND\-OPTIONS\fR ]
|
||||
.PP
|
||||
COMMANDS := { \fBcreate\fR | \fBadd\fR | \fBdel\fR | \fBtest\fR | \fBdestroy\fR | \fBlist\fR | \fBsave\fR | \fBrestore\fR | \fBflush\fR | \fBrename\fR | \fBswap\fR | \fBhelp\fR | \fBversion\fR | \fB\-\fR }
|
||||
.PP
|
||||
\fIOPTIONS\fR := { \fB\-exist\fR | \fB\-output\fR { \fBplain\fR | \fBsave\fR | \fBxml\fR } | \fB\-quiet\fR | \fB\-resolve\fR | \fB\-sorted\fR }
|
||||
.PP
|
||||
\fBipset\fR \fBcreate\fR \fISETNAME\fR \fITYPENAME\fR [ \fICREATE\-OPTIONS\fR ]
|
||||
.PP
|
||||
\fBipset\fR \fBadd\fR \fISETNAME\fR \fIADD\-ENTRY\fR [ \fIADD\-OPTIONS\fR ]
|
||||
.PP
|
||||
\fBipset\fR \fBdel\fR \fISETNAME\fR \fIDEL\-ENTRY\fR [ \fIDEL\-OPTIONS\fR ]
|
||||
.PP
|
||||
\fBipset\fR \fBtest\fR \fISETNAME\fR \fITEST\-ENTRY\fR [ \fITEST\-OPTIONS\fR ]
|
||||
.PP
|
||||
\fBipset\fR \fBdestroy\fR [ \fISETNAME\fR ]
|
||||
.PP
|
||||
\fBipset\fR \fBlist\fR [ \fISETNAME\fR ]
|
||||
.PP
|
||||
\fBipset\fR \fBsave\fR [ \fISETNAME\fR ]
|
||||
.PP
|
||||
\fBipset\fR \fBrestore\fR
|
||||
.PP
|
||||
\fBipset\fR \fBflush\fR [ \fISETNAME\fR ]
|
||||
.PP
|
||||
\fBipset\fR \fBrename\fR \fISETNAME\-FROM\fR \fISETNAME\-TO\fR
|
||||
.PP
|
||||
\fBipset\fR \fBswap\fR \fISETNAME\-FROM\fR \fISETNAME\-TO\fR
|
||||
.PP
|
||||
\fBipset\fR \fBhelp\fR [ \fITYPENAME\fR ]
|
||||
.PP
|
||||
\fBipset\fR \fBversion\fR
|
||||
.PP
|
||||
\fBipset\fR \fB\-\fR
|
||||
.SH "DESCRIPTION"
|
||||
\fBipset\fR
|
||||
is used to set up, maintain and inspect so called IP sets in the Linux
|
||||
kernel. Depending on the type of the set, an IP set may store IP(v4/v6)
|
||||
addresses, (TCP/UDP) port numbers, IP and MAC address pairs, IP address
|
||||
and port number pairs, etc. See the set type definitions below.
|
||||
.PP
|
||||
\fBIptables\fR
|
||||
matches and targets referring to sets create references, which
|
||||
protect the given sets in the kernel. A set cannot be destroyed
|
||||
while there is a single reference pointing to it.
|
||||
.SH "OPTIONS"
|
||||
The options that are recognized by
|
||||
\fBipset\fR
|
||||
can be divided into several different groups.
|
||||
.SS COMMANDS
|
||||
These options specify the desired action to perform. Only one of them
|
||||
can be specified on the command line unless otherwise specified below.
|
||||
For all the long versions of the command names, you need to use only enough
|
||||
letters to ensure that
|
||||
\fBipset\fR
|
||||
can differentiate it from all other commands. The
|
||||
\fBipset\fR
|
||||
parser follows the order here when looking for the shortest match
|
||||
in the long command names.
|
||||
.TP
|
||||
\fBn\fP, \fBcreate\fP \fISETNAME\fP \fITYPENAME\fP [ \fICREATE\-OPTIONS\fP ]
|
||||
Create a set identified with setname and specified type. The type may require
|
||||
type specific options. If the
|
||||
\fB\-exist\fR
|
||||
option is specified,
|
||||
\fBipset\fR
|
||||
ignores the error otherwise raised when the same set (setname and create parameters
|
||||
are identical) already exists.
|
||||
.TP
|
||||
\fBadd\fP \fISETNAME\fP \fIADD\-ENTRY\fP [ \fIADD\-OPTIONS\fP ]
|
||||
Add a given entry to the set. If the
|
||||
\fB\-exist\fR
|
||||
option is specified,
|
||||
\fBipset\fR
|
||||
ignores if the entry already added to the set.
|
||||
.TP
|
||||
\fBdel\fP \fISETNAME\fP \fIDEL\-ENTRY\fP [ \fIDEL\-OPTIONS\fP ]
|
||||
Delete an entry from a set. If the
|
||||
\fB\-exist\fR
|
||||
option is specified,
|
||||
\fBipset\fR
|
||||
ignores if the entry does not added to (already expired from) the set.
|
||||
.TP
|
||||
\fBtest\fP \fISETNAME\fP \fITEST\-ENTRY\fP [ \fITEST\-OPTIONS\fP ]
|
||||
Test wether an entry is in a set or not. Exit status number is zero
|
||||
if the tested entry is in the set and nonzero if it is missing from
|
||||
the set.
|
||||
.TP
|
||||
\fBx\fP, \fBdestroy\fP [ \fISETNAME\fP ]
|
||||
Destroy the specified set or all the sets if none is given.
|
||||
|
||||
If the set has got reference(s), nothing is done and no set destroyed.
|
||||
.TP
|
||||
\fBlist\fP [ \fISETNAME\fP ]
|
||||
List the header data and the entries for the specified set, or for
|
||||
all sets if none is given. The
|
||||
\fB\-resolve\fP
|
||||
option can be used to force name lookups (which may be slow). When the
|
||||
\fB\-sorted\fP
|
||||
option is given, the entries are listed sorted (if the given set
|
||||
type supports the operation). The option
|
||||
\fB\-output\fR
|
||||
can be used to control the format of the listing:
|
||||
\fBplain\fR, \fBsave\fR or \fBxml\fR.
|
||||
The default is
|
||||
\fBplain\fR.
|
||||
.TP
|
||||
\fBsave\fP [ \fISETNAME\fP ]
|
||||
Save the given set, or all sets if none is given
|
||||
to stdout in a format that
|
||||
\fBrestore\fP
|
||||
can read.
|
||||
.TP
|
||||
\fBrestore\fP
|
||||
Restore a saved session generated by
|
||||
\fBsave\fP.
|
||||
The saved session can be fed from stdin.
|
||||
.TP
|
||||
\fBflush\fP [ \fISETNAME\fP ]
|
||||
Flush all entries from the specified set or flush
|
||||
all sets if none is given.
|
||||
.TP
|
||||
\fBe\fP, \fBrename\fP \fISETNAME\-FROM\fP \fISETNAME\-TO\fP
|
||||
Rename a set. Set identified by
|
||||
\fISETNAME\-TO\fR
|
||||
must not exist.
|
||||
.TP
|
||||
\fBw\fP, \fBswap\fP \fISETNAME\-FROM\fP \fISETNAME\-TO\fP
|
||||
Swap the content of two sets, or in another words,
|
||||
exchange the name of two sets. The referred sets must exist and
|
||||
identical type of sets can be swapped only.
|
||||
.TP
|
||||
\fBhelp\fP [ \fITYPENAME\fP ]
|
||||
Print help and set type specific help if
|
||||
\fITYPENAME\fR
|
||||
is specified.
|
||||
.TP
|
||||
\fBversion\fP
|
||||
Print program version.
|
||||
.TP
|
||||
\fB\-\fP
|
||||
If a dash is specified as command, then
|
||||
\fBipset\fR
|
||||
enters a simple interactive mode and the commands are read from the standard input.
|
||||
The interactive mode can be finished by entering the pseudo\-command
|
||||
\fBquit\fR.
|
||||
.P
|
||||
.SS "OTHER OPTIONS"
|
||||
The following additional options can be specified. The long option names
|
||||
cannot be abbreviated.
|
||||
.TP
|
||||
\fB\-!\fP, \fB\-exist\fP
|
||||
Ignore errors when the exactly the same set is to be created or already
|
||||
added entry is added or missing entry is deleted.
|
||||
.TP
|
||||
\fB\-o\fP, \fB\-output\fP { \fBplain\fR | \fBsave\fR | \fBxml\fR }
|
||||
Select the output format to the
|
||||
\fBlist\fR
|
||||
command.
|
||||
.TP
|
||||
\fB\-q\fP, \fB\-quiet\fP
|
||||
Suppress any output to stdout and stderr.
|
||||
\fBipset\fR
|
||||
will still exit with error if it cannot continue.
|
||||
.TP
|
||||
\fB\-r\fP, \fB\-resolve\fP
|
||||
When listing sets, enforce name lookup. The
|
||||
program will try to display the IP entries resolved to
|
||||
host names which requires
|
||||
\fBslow\fR
|
||||
DNS lookups.
|
||||
.TP
|
||||
\fB\-s\fP, \fB\-sorted\fP
|
||||
Sorted output. When listing sets entries are listed sorted. Not supported yet.
|
||||
.SH "SET TYPES"
|
||||
A set type comprises of the storage method by which the data is stored and
|
||||
the data type(s) which are stored in the set. Therefore the
|
||||
\fITYPENAME\fR
|
||||
parameter of the
|
||||
\fBcreate\fR
|
||||
command follows the syntax
|
||||
|
||||
\fITYPENAME\fR := \fImethod\fR\fB:\fR\fIdatatype\fR[\fB,\fR\fIdatatype\fR[\fB,\fR\fIdatatype\fR]]
|
||||
|
||||
where the current list of the methods are
|
||||
\fBbitmap\fR, \fBhash\fR, and \fBlist\fR and the possible data types
|
||||
are \fBip\fR, \fBmac\fR and \fBport\fR. The dimension of a set
|
||||
is equal to the number of data types in its type name.
|
||||
|
||||
When adding, deleting or testing entries in a set, the same comma separated
|
||||
data syntax must be used for the entry parameter of the commands, i.e
|
||||
|
||||
ipset add foo ipaddr,portnum,ipaddr
|
||||
|
||||
The \fBbitmap\fR and \fBlist\fR types use a fixed sized storage. The \fBhash\fR
|
||||
types use a hash to store the elements. In order to avoid clashes in the hash,
|
||||
a limited number of chaining, and if that is exhausted, the doubling of the hash size
|
||||
is performed when adding entries by the
|
||||
\fBipset\fR
|
||||
command. When entries added by the
|
||||
\fBSET\fR
|
||||
target of
|
||||
\fBiptables/ip6tables\fR,
|
||||
then the hash size is fixed and the set won't be duplicated, even if the new
|
||||
entry cannot be added to the set.
|
||||
|
||||
All set types support the optional
|
||||
|
||||
\fBtimeout\fR \fIvalue\fR
|
||||
|
||||
parameter when creating a set and adding entries. The value of the \fBtimeout\fR
|
||||
parameter for the \fBcreate\fR command means the default timeout value (in seconds)
|
||||
for new entries. If a set is created with timeout support, then the same
|
||||
\fBtimeout\fR option can be used to specify non\-default timeout values
|
||||
when adding entries. Zero timeout value means the entry is added permanent to the set.
|
||||
.SS bitmap:ip
|
||||
The \fBbitmap:ip\fR set type uses a memory range to store either IPv4 host
|
||||
(default) or IPv4 network addresses. A \fBbitmap:ip\fR type of set can store up
|
||||
to 65536 entries.
|
||||
.PP
|
||||
\fICREATE\-OPTIONS\fR := \fBrange\fP \fIfromip\fP\-\fItoip\fR|\fIip\fR/\fIcidr\fR [ \fBnetmask\fP \fIcidr\fP ] [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIADD\-ENTRY\fR := { \fIip\fR | \fIfromip\fR\-\fItoip\fR | \fIip\fR/\fIcidr\fR }
|
||||
.PP
|
||||
\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIDEL\-ENTRY\fR := { \fIip\fR | \fIfromip\fR\-\fItoip\fR | \fIip\fR/\fIcidr\fR }
|
||||
.PP
|
||||
\fITEST\-ENTRY\fR := \fIip\fR
|
||||
.PP
|
||||
Mandatory \fBcreate\fR options:
|
||||
.TP
|
||||
\fBrange\fP \fIfromip\fP\-\fItoip\fR|\fIip\fR/\fIcidr\fR
|
||||
Create the set from the specified inclusive address range expressed in an
|
||||
IPv4 address range or network. The size of the range (in entries) cannot exceed
|
||||
the limit of maximum 65536 elements.
|
||||
.PP
|
||||
Optional \fBcreate\fR options:
|
||||
.TP
|
||||
\fBnetmask\fP \fIcidr\fP
|
||||
When the optional \fBnetmask\fP parameter specified, network addresses will be
|
||||
stored in the set instead of IP host addresses. The \fIcidr\fR prefix value must be
|
||||
between 1\-32.
|
||||
An IP address will be in the set if the network address, which is resulted by
|
||||
masking the address with the specified netmask calculated from the prefix,
|
||||
can be found in the set.
|
||||
.PP
|
||||
The \fBbitmap:ip\fR type supports adding or deleting multiple entries in one
|
||||
command.
|
||||
.PP
|
||||
Examples:
|
||||
.IP
|
||||
ipset create foo bitmap:ip range 192.168.0.0/16
|
||||
.IP
|
||||
ipset add foo 192.168.1/24
|
||||
.IP
|
||||
ipset test foo 192.168.1.1
|
||||
.SS bitmap:ip,mac
|
||||
The \fBbitmap:ip,mac\fR set type uses a memory range to store IPv4 and a MAC address pairs. A \fBbitmap:ip,mac\fR type of set can store up to 65536 entries.
|
||||
.PP
|
||||
\fICREATE\-OPTIONS\fR := \fBrange\fP \fIfromip\fP\-\fItoip\fR|\fIip\fR/\fIcidr\fR [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIADD\-ENTRY\fR := \fIip\fR[,\fImacaddr\fR]
|
||||
.PP
|
||||
\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIDEL\-ENTRY\fR := \fIip\fR[,\fImacaddr\fR]
|
||||
.PP
|
||||
\fITEST\-ENTRY\fR := \fIip\fR[,\fImacaddr\fR]
|
||||
.PP
|
||||
Mandatory options to use when creating a \fBbitmap:ip,mac\fR type of set:
|
||||
.TP
|
||||
\fBrange\fP \fIfromip\fP\-\fItoip\fR|\fIip\fR/\fIcidr\fR
|
||||
Create the set from the specified inclusive address range expressed in an
|
||||
IPv4 address range or network. The size of the range cannot exceed the limit
|
||||
of maximum 65536 entries.
|
||||
.PP
|
||||
The \fBbitmap:ip,mac\fR type is exceptional in the sense that the MAC part can
|
||||
be left out when adding/deleting/testing entries in the set. If we add an entry
|
||||
without the MAC address specified, then when the first time the entry is
|
||||
matched by the kernel, it will automatically fill out the missing MAC address with the
|
||||
source MAC address from the packet. If the entry was specified with a timeout value,
|
||||
the timer starts off when the IP and MAC address pair is complete.
|
||||
.PP
|
||||
Please note, the \fBset\fR match and \fBSET\fR target netfilter kernel modules
|
||||
\fBalways\fR use the source MAC address from the packet to match, add or delete
|
||||
entries from a \fBbitmap:ip,mac\fR type of set.
|
||||
.PP
|
||||
Examples:
|
||||
.IP
|
||||
ipset create foo bitmap:ip,mac range 192.168.0.0/16
|
||||
.IP
|
||||
ipset add foo 192.168.1.1,12:34:56:78:9A:BC
|
||||
.IP
|
||||
ipset test foo 192.168.1.1
|
||||
.SS bitmap:port
|
||||
The \fBbitmap:port\fR set type uses a memory range to store port numbers
|
||||
and such a set can store up to 65536 ports.
|
||||
.PP
|
||||
\fICREATE\-OPTIONS\fR := \fBrange\fP \fIfromport\fP\-\fItoport [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIADD\-ENTRY\fR := { \fIport\fR | \fIfromport\fR\-\fItoport\fR }
|
||||
.PP
|
||||
\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIDEL\-ENTRY\fR := { \fIport\fR | \fIfromport\fR\-\fItoport\fR }
|
||||
.PP
|
||||
\fITEST\-ENTRY\fR := \fIport\fR
|
||||
.PP
|
||||
Mandatory options to use when creating a \fBbitmap:port\fR type of set:
|
||||
.TP
|
||||
\fBrange\fP \fIfromport\fP\-\fItoport\fR
|
||||
Create the set from the specified inclusive port range.
|
||||
.PP
|
||||
Examples:
|
||||
.IP
|
||||
ipset create foo bitmap:port range 0\-1024
|
||||
.IP
|
||||
ipset add foo 80
|
||||
.IP
|
||||
ipset test foo 80
|
||||
.SS hash:ip
|
||||
The \fBhash:ip\fR set type uses a hash to store IP host addresses (default) or
|
||||
network addresses. Zero valued IP address cannot be stored in a \fBhash:ip\fR
|
||||
type of set.
|
||||
.PP
|
||||
\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBnetmask\fP \fIcidr\fP ] [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIADD\-ENTRY\fR := \fIipaddr\fR
|
||||
.PP
|
||||
\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIDEL\-ENTRY\fR := \fIipaddr\fR
|
||||
.PP
|
||||
\fITEST\-ENTRY\fR := \fIipaddr\fR
|
||||
.PP
|
||||
Optional \fBcreate\fR options:
|
||||
.TP
|
||||
\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
|
||||
The protocol family of the IP addresses to be stored in the set. The default is
|
||||
\fBinet\fR, i.e IPv4.
|
||||
.TP
|
||||
\fBhashsize\fR \fIvalue\fR
|
||||
The initial hash size for the set, default is 1024. The hash size must be a power
|
||||
of two, the kernel automatically rounds up non power of two hash sizes to the first
|
||||
correct value.
|
||||
.TP
|
||||
\fBmaxelem\fR \fIvalue\fR
|
||||
The maximal number of elements which can be stored in the set, default 65536.
|
||||
.TP
|
||||
\fBnetmask\fP \fIcidr\fP
|
||||
When the optional \fBnetmask\fP parameter specified, network addresses will be
|
||||
stored in the set instead of IP host addresses. The \fIcidr\fP prefix value must be
|
||||
between 1\-32 for IPv4 and between 1\-128 for IPv6. An IP address will be in the set
|
||||
if the network address, which is resulted by masking the address with the netmask
|
||||
calculated from the prefix, can be found in the set.
|
||||
.PP
|
||||
For the \fBinet\fR family one can add or delete multiple entries by specifying
|
||||
a range or a network:
|
||||
.PP
|
||||
\fIipaddr\fR := { \fIip\fR | \fIfromaddr\fR\-\fItoaddr\fR | \fIip\fR/\fIcidr\fR }
|
||||
.PP
|
||||
Examples:
|
||||
.IP
|
||||
ipset create foo hash:ip netmask 24
|
||||
.IP
|
||||
ipset add foo 192.168.1.1\-192.168.1.2
|
||||
.IP
|
||||
ipset test foo 192.168.1.2
|
||||
.SS hash:net
|
||||
The \fBhash:net\fR set type uses a hash to store different sized IP network addresses.
|
||||
Network address with zero prefix size cannot be stored in this type of sets.
|
||||
.PP
|
||||
\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIADD\-ENTRY\fR := \fIip\fR[/\fIcidr\fR]
|
||||
.PP
|
||||
\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIDEL\-ENTRY\fR := \fIip\fR[/\fIcidr\fR]
|
||||
.PP
|
||||
\fITEST\-ENTRY\fR := \fIip\fR[/\fIcidr\fR]
|
||||
.PP
|
||||
Optional \fBcreate\fR options:
|
||||
.TP
|
||||
\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
|
||||
The protocol family of the IP addresses to be stored in the set. The default is
|
||||
\fBinet\fR, i.e IPv4.
|
||||
.TP
|
||||
\fBhashsize\fR \fIvalue\fR
|
||||
The initial hash size for the set, default is 1024. The hash size must be a power
|
||||
of two, the kernel automatically rounds up non power of two hash sizes to the first
|
||||
correct value.
|
||||
.TP
|
||||
\fBmaxelem\fR \fIvalue\fR
|
||||
The maximal number of elements which can be stored in the set, default 65536.
|
||||
.PP
|
||||
When adding/deleting/testing entries, if the cidr prefix parameter is not specified,
|
||||
then the host prefix value is assumed. When adding/deleting entries, overlapping
|
||||
elements are not checked.
|
||||
.PP
|
||||
From the \fBset\fR netfilter match point of view the searching for a match
|
||||
always starts from the smallest size of netblock (most specific
|
||||
prefix) to the largest one (least specific prefix) added to the set.
|
||||
When adding/deleting IP addresses to the set by the \fBSET\fR netfilter target,
|
||||
it will be added/deleted by the most specific prefix which can be found in the
|
||||
set, or by the host prefix value if the set is empty.
|
||||
.PP
|
||||
The lookup time grows linearly with the number of the different prefix
|
||||
values added to the set.
|
||||
.PP
|
||||
Examples:
|
||||
.IP
|
||||
ipset create foo hash:net
|
||||
.IP
|
||||
ipset add foo 192.168.0/24
|
||||
.IP
|
||||
ipset add foo 10.1.0.0/16
|
||||
.IP
|
||||
ipset test foo 192.168.0/24
|
||||
.SS hash:ip,port
|
||||
The \fBhash:ip,port\fR set type uses a hash to store IP address and port number pairs.
|
||||
The port number is interpreted together with a protocol (default TCP) and zero
|
||||
protocol number cannot be used.
|
||||
.PP
|
||||
\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR
|
||||
.PP
|
||||
\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIDEL\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR
|
||||
.PP
|
||||
\fITEST\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR
|
||||
.PP
|
||||
Optional \fBcreate\fR options:
|
||||
.TP
|
||||
\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
|
||||
The protocol family of the IP addresses to be stored in the set. The default is
|
||||
\fBinet\fR, i.e IPv4.
|
||||
.TP
|
||||
\fBhashsize\fR \fIvalue\fR
|
||||
The initial hash size for the set, default is 1024. The hash size must be a power
|
||||
of two, the kernel automatically rounds up non power of two hash sizes to the first
|
||||
correct value
|
||||
.TP
|
||||
\fBmaxelem\fR \fIvalue\fR
|
||||
The maximal number of elements which can be stored in the set, default 65536.
|
||||
.PP
|
||||
For the \fBinet\fR family one can add or delete multiple entries by specifying
|
||||
a range or a network of IPv4 addresses in the IP address part of the entry:
|
||||
.PP
|
||||
\fIipaddr\fR := { \fIip\fR | \fIfromaddr\fR\-\fItoaddr\fR | \fIip\fR/\fIcidr\fR }
|
||||
.PP
|
||||
The
|
||||
[\fIproto\fR:]\fIport\fR
|
||||
part of the elements may be expressed in the following forms, where the range
|
||||
variations are valid when adding or deleting entries:
|
||||
.TP
|
||||
\fIportname[\-portname]\fR
|
||||
TCP port or range of ports expressed in TCP portname identifiers from /etc/services
|
||||
.TP
|
||||
\fIportnumber[\-portnumber]\fR
|
||||
TCP port or range of ports expressed in TCP port numbers
|
||||
.TP
|
||||
\fBtcp\fR|\fBudp\fR:\fIportname\fR|\fIportnumber\fR[\-\fIportname\fR|\fIportnumber\fR]
|
||||
TCP or UDP port or port range expressed in port name(s) or port number(s)
|
||||
.TP
|
||||
\fBicmp\fR:\fIcodename\fR|\fItype\fR/\fIcode\fR
|
||||
ICMP codename or type/code. The supported ICMP codename identifiers can always
|
||||
be listed by the help command.
|
||||
.TP
|
||||
\fBicmpv6\fR:\fIcodename\fR|\fItype\fR/\fIcode\fR
|
||||
ICMPv6 codename or type/code. The supported ICMPv6 codename identifiers can always
|
||||
be listed by the help command.
|
||||
.TP
|
||||
\fIproto\fR:0
|
||||
All other protocols, as an identifier from /etc/protocols or number. The pseudo
|
||||
port number must be zero.
|
||||
.PP
|
||||
The \fBhash:ip,port\fR type of sets require
|
||||
two \fBsrc\fR/\fBdst\fR parameters of the \fBset\fR match and \fBSET\fR
|
||||
target kernel modules.
|
||||
.PP
|
||||
Examples:
|
||||
.IP
|
||||
ipset create foo hash:ip,port
|
||||
.IP
|
||||
ipset add foo 192.168.1.0/24,80\-82
|
||||
.IP
|
||||
ipset add foo 192.168.1.1,udp:53
|
||||
.IP
|
||||
ipset add foo 192.168.1.1,ospf:0
|
||||
.IP
|
||||
ipset test foo 192.168.1.1,80
|
||||
.SS hash:net,port
|
||||
The \fBhash:net,port\fR set type uses a hash to store different sized IP network
|
||||
address and port pairs. The port number is interpreted together with a protocol
|
||||
(default TCP) and zero protocol number cannot be used. Network
|
||||
address with zero prefix size is not accepted either.
|
||||
.PP
|
||||
\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIADD\-ENTRY\fR := \fIipaddr\fR[/\fIcidr\fR],[\fIproto\fR:]\fIport\fR
|
||||
.PP
|
||||
\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIDEL\-ENTRY\fR := \fIipaddr\fR[/\fIcidr\fR],[\fIproto\fR:]\fIport\fR
|
||||
.PP
|
||||
\fITEST\-ENTRY\fR := \fIipaddr\fR[/\fIcidr\fR],[\fIproto\fR:]\fIport\fR
|
||||
.PP
|
||||
Optional \fBcreate\fR options:
|
||||
.TP
|
||||
\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
|
||||
The protocol family of the IP addresses to be stored in the set. The default is
|
||||
\fBinet\fR, i.e IPv4.
|
||||
.TP
|
||||
\fBhashsize\fR \fIvalue\fR
|
||||
The initial hash size for the set, default is 1024. The hash size must be a power
|
||||
of two, the kernel automatically rounds up non power of two hash sizes to the first
|
||||
correct value.
|
||||
.TP
|
||||
\fBmaxelem\fR \fIvalue\fR
|
||||
The maximal number of elements which can be stored in the set, default 65536.
|
||||
.PP
|
||||
For the
|
||||
[\fIproto\fR:]\fIport\fR
|
||||
part of the elements see the description at the
|
||||
\fBhash:ip,port\fR set type.
|
||||
.PP
|
||||
When adding/deleting/testing entries, if the cidr prefix parameter is not specified,
|
||||
then the host prefix value is assumed. When adding/deleting entries, overlapping
|
||||
elements are not checked.
|
||||
.PP
|
||||
From the \fBset\fR netfilter match point of view the searching for a match
|
||||
always starts from the smallest size of netblock (most specific
|
||||
prefix) to the largest one (least specific prefix) added to the set.
|
||||
When adding/deleting IP
|
||||
addresses to the set by the \fBSET\fR netfilter target, it will be
|
||||
added/deleted by the most specific prefix which can be found in the
|
||||
set, or by the host prefix value if the set is empty.
|
||||
.PP
|
||||
The lookup time grows linearly with the number of the different prefix
|
||||
values added to the set.
|
||||
.PP
|
||||
Examples:
|
||||
.IP
|
||||
ipset create foo hash:net,port
|
||||
.IP
|
||||
ipset add foo 192.168.0/24,25
|
||||
.IP
|
||||
ipset add foo 10.1.0.0/16,80
|
||||
.IP
|
||||
ipset test foo 192.168.0/24,25
|
||||
.SS hash:ip,port,ip
|
||||
The \fBhash:ip,port,ip\fR set type uses a hash to store IP address, port number
|
||||
and a second IP address triples. The port number is interpreted together with a
|
||||
protocol (default TCP) and zero protocol number cannot be used.
|
||||
.PP
|
||||
\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIip\fR
|
||||
.PP
|
||||
\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIDEL\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIip\fR
|
||||
.PP
|
||||
\fITEST\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIip\fR
|
||||
.PP
|
||||
For the first \fIipaddr\fR and
|
||||
[\fIproto\fR:]\fIport\fR
|
||||
parts of the elements see the descriptions at the
|
||||
\fBhash:ip,port\fR set type.
|
||||
.PP
|
||||
Optional \fBcreate\fR options:
|
||||
.TP
|
||||
\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
|
||||
The protocol family of the IP addresses to be stored in the set. The default is
|
||||
\fBinet\fR, i.e IPv4.
|
||||
.TP
|
||||
\fBhashsize\fR \fIvalue\fR
|
||||
The initial hash size for the set, default is 1024. The hash size must be a power
|
||||
of two, the kernel automatically rounds up non power of two hash sizes to the first
|
||||
correct value.
|
||||
.TP
|
||||
\fBmaxelem\fR \fIvalue\fR
|
||||
The maximal number of elements which can be stored in the set, default 65536.
|
||||
.PP
|
||||
The \fBhash:ip,port,ip\fR type of sets require
|
||||
three \fBsrc\fR/\fBdst\fR parameters of the \fBset\fR match and \fBSET\fR
|
||||
target kernel modules.
|
||||
.PP
|
||||
Examples:
|
||||
.IP
|
||||
ipset create foo hash:ip,port,ip
|
||||
.IP
|
||||
ipset add foo 192.168.1.1,80,10.0.0.1
|
||||
.IP
|
||||
ipset test foo 192.168.1.1,udp:53,10.0.0.1
|
||||
.SS hash:ip,port,net
|
||||
The \fBhash:ip,port,net\fR set type uses a hash to store IP address, port number
|
||||
and IP network address triples. The port number is interpreted together with a
|
||||
protocol (default TCP) and zero protocol number cannot be used. Network
|
||||
address with zero prefix size cannot be stored either.
|
||||
.PP
|
||||
\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIip\fR[/\fIcidr\fR]
|
||||
.PP
|
||||
\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIDEL\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIip\fR[/\fIcidr\fR]
|
||||
.PP
|
||||
\fITEST\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIip\fR[/\fIcidr\fR]
|
||||
.PP
|
||||
For the first \fIipaddr\fR and
|
||||
[\fIproto\fR:]\fIport\fR
|
||||
parts of the elements see the descriptions at the
|
||||
\fBhash:ip,port\fR set type.
|
||||
.PP
|
||||
Optional \fBcreate\fR options:
|
||||
.TP
|
||||
\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
|
||||
The protocol family of the IP addresses to be stored in the set. The default is
|
||||
\fBinet\fR, i.e IPv4.
|
||||
.TP
|
||||
\fBhashsize\fR \fIvalue\fR
|
||||
The initial hash size for the set, default is 1024. The hash size must be a power
|
||||
of two, the kernel automatically rounds up non power of two hash sizes to the first
|
||||
correct value.
|
||||
.TP
|
||||
\fBmaxelem\fR \fIvalue\fR
|
||||
The maximal number of elements which can be stored in the set, default 65536.
|
||||
.PP
|
||||
From the \fBset\fR netfilter match point of view the searching for a match
|
||||
always starts from the smallest size of netblock (most specific
|
||||
cidr) to the largest one (least specific cidr) added to the set.
|
||||
When adding/deleting triples
|
||||
to the set by the \fBSET\fR netfilter target, it will be
|
||||
added/deleted by the most specific cidr which can be found in the
|
||||
set, or by the host cidr value if the set is empty.
|
||||
.PP
|
||||
The lookup time grows linearly with the number of the different \fIcidr\fR
|
||||
values added to the set.
|
||||
.PP
|
||||
The \fBhash:ip,port,net\fR type of sets require three \fBsrc\fR/\fBdst\fR parameters of
|
||||
the \fBset\fR match and \fBSET\fR target kernel modules.
|
||||
.PP
|
||||
Examples:
|
||||
.IP
|
||||
ipset create foo hash:ip,port,net
|
||||
.IP
|
||||
ipset add foo 192.168.1,80,10.0.0/24
|
||||
.IP
|
||||
ipset add foo 192.168.2,25,10.1.0.0/16
|
||||
.IP
|
||||
ipset test foo 192.168.1,80.10.0.0/24
|
||||
.SS list:set
|
||||
The \fBlist:set\fR type uses a simple list in which you can store
|
||||
set names.
|
||||
.PP
|
||||
\fICREATE\-OPTIONS\fR := [ \fBsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIADD\-ENTRY\fR := \fIsetname\fR [ { \fBbefore\fR | \fBafter\fR } \fIsetname\fR ]
|
||||
.PP
|
||||
\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
|
||||
.PP
|
||||
\fIDEL\-ENTRY\fR := \fIsetname\fR [ { \fBbefore\fR | \fBafter\fR } \fIsetname\fR ]
|
||||
.PP
|
||||
\fITEST\-ENTRY\fR := \fIsetname\fR [ { \fBbefore\fR | \fBafter\fR } \fIsetname\fR ]
|
||||
.PP
|
||||
Optional \fBcreate\fR options:
|
||||
.TP
|
||||
\fBsize\fR \fIvalue\fR
|
||||
The size of the list, the default is 8.
|
||||
.PP
|
||||
By the \fBipset\fR commad you can add, delete and test set names in a
|
||||
\fBlist:set\fR type of set.
|
||||
.PP
|
||||
By the \fBset\fR match or \fBSET\fR target of netfilter
|
||||
you can test, add or delete entries in the sets added to the \fBlist:set\fR
|
||||
type of set. The match will try to find a matching entry in the sets and
|
||||
the target will try to add an entry to the first set to which it can be added.
|
||||
The number of direction options of the match and target are important: sets which
|
||||
require more parameters than specified are skipped, while sets with equal
|
||||
or less parameters are checked, elements added/deleted. For example if \fIa\fR and
|
||||
\fIb\fR are \fBlist:set\fR type of sets then in the command
|
||||
.IP
|
||||
iptables \-m set \-\-match\-set a src,dst \-j SET \-\-add\-set b src,dst
|
||||
.PP
|
||||
the match and target will skip any set in \fIa\fR and \fIb\fR
|
||||
which stores data triples, but will match all sets with single or double
|
||||
data storage in \fIa\fR set and stop matching at the first successful set,
|
||||
and add src to the first single or src,dst to the first double data storage set
|
||||
in \fIb\fR to which the entry can be added. You can imagine a \fBlist:set\fR
|
||||
type of set as an ordered union of the set elements.
|
||||
.PP
|
||||
Please note: by the \fBipset\fR commad you can add, delete and \fBtest\fR
|
||||
the setnames in a \fBlist:set\fR type of set, and \fBnot\fR the presence of
|
||||
a set's member (such as an IP address).
|
||||
.SH "GENERAL RESTRICTIONS"
|
||||
Zero valued set entries cannot be used with hash methods. Zero protocol value with ports
|
||||
cannot be used.
|
||||
.SH "COMMENTS"
|
||||
If you want to store same size subnets from a given network
|
||||
(say /24 blocks from a /8 network), use the \fBbitmap:ip\fR set type.
|
||||
If you want to store random same size networks (say random /24 blocks),
|
||||
use the \fBhash:ip\fR set type. If you have got random size of netblocks,
|
||||
use \fBhash:net\fR.
|
||||
.PP
|
||||
Backward compatibility is maintained and old \fBipset\fR syntax is still supported.
|
||||
.PP
|
||||
The \fBiptree\fR and \fBiptreemap\fR set types are removed: if you refer to them,
|
||||
they are automatically replaced by \fBhash:ip\fR type of sets.
|
||||
.SH "DIAGNOSTICS"
|
||||
Various error messages are printed to standard error. The exit code
|
||||
is 0 for correct functioning.
|
||||
.SH "BUGS"
|
||||
Bugs? No, just funny features. :\-)
|
||||
OK, just kidding...
|
||||
.SH "SEE ALSO"
|
||||
\fBiptables\fR(8),
|
||||
\fBip6tables\fR(8)
|
||||
.SH "AUTHORS"
|
||||
Jozsef Kadlecsik wrote ipset, which is based on ippool by
|
||||
Joakim Axelsson, Patrick Schaaf and Martin Josefsson.
|
||||
.br
|
||||
Sven Wegener wrote the iptreemap type.
|
||||
.SH "LAST REMARK"
|
||||
\fBI stand on the shoulders of giants.\fR
|
||||
169
extensions/ipset-5/jhash.h
Normal file
169
extensions/ipset-5/jhash.h
Normal file
@@ -0,0 +1,169 @@
|
||||
#ifndef _LINUX_JHASH_H
|
||||
#define _LINUX_JHASH_H
|
||||
|
||||
/* jhash.h: Jenkins hash support.
|
||||
*
|
||||
* Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net)
|
||||
*
|
||||
* http://burtleburtle.net/bob/hash/
|
||||
*
|
||||
* These are the credits from Bob's sources:
|
||||
*
|
||||
* lookup3.c, by Bob Jenkins, May 2006, Public Domain.
|
||||
*
|
||||
* These are functions for producing 32-bit hashes for hash table lookup.
|
||||
* hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
|
||||
* are externally useful functions. Routines to test the hash are included
|
||||
* if SELF_TEST is defined. You can use this free for any purpose. It's in
|
||||
* the public domain. It has no warranty.
|
||||
*
|
||||
* Copyright (C) 2009-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* I've modified Bob's hash to be useful in the Linux kernel, and
|
||||
* any bugs present are my fault.
|
||||
* Jozsef
|
||||
*/
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/unaligned/packed_struct.h>
|
||||
|
||||
/* Best hash sizes are of power of two */
|
||||
#define jhash_size(n) ((u32)1<<(n))
|
||||
/* Mask the hash value, i.e (value & jhash_mask(n)) instead of (value % n) */
|
||||
#define jhash_mask(n) (jhash_size(n)-1)
|
||||
|
||||
/* __jhash_mix -- mix 3 32-bit values reversibly. */
|
||||
#define __jhash_mix(a, b, c) \
|
||||
{ \
|
||||
a -= c; a ^= rol32(c, 4); c += b; \
|
||||
b -= a; b ^= rol32(a, 6); a += c; \
|
||||
c -= b; c ^= rol32(b, 8); b += a; \
|
||||
a -= c; a ^= rol32(c, 16); c += b; \
|
||||
b -= a; b ^= rol32(a, 19); a += c; \
|
||||
c -= b; c ^= rol32(b, 4); b += a; \
|
||||
}
|
||||
|
||||
/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */
|
||||
#define __jhash_final(a, b, c) \
|
||||
{ \
|
||||
c ^= b; c -= rol32(b, 14); \
|
||||
a ^= c; a -= rol32(c, 11); \
|
||||
b ^= a; b -= rol32(a, 25); \
|
||||
c ^= b; c -= rol32(b, 16); \
|
||||
a ^= c; a -= rol32(c, 4); \
|
||||
b ^= a; b -= rol32(a, 14); \
|
||||
c ^= b; c -= rol32(b, 24); \
|
||||
}
|
||||
|
||||
/* An arbitrary initial parameter */
|
||||
#define JHASH_INITVAL 0xdeadbeef
|
||||
|
||||
/* jhash - hash an arbitrary key
|
||||
* @k: sequence of bytes as key
|
||||
* @length: the length of the key
|
||||
* @initval: the previous hash, or an arbitray value
|
||||
*
|
||||
* The generic version, hashes an arbitrary sequence of bytes.
|
||||
* No alignment or length assumptions are made about the input key.
|
||||
*
|
||||
* Returns the hash value of the key. The result depends on endianness.
|
||||
*/
|
||||
static inline u32 jhash(const void *key, u32 length, u32 initval)
|
||||
{
|
||||
u32 a, b, c;
|
||||
const u8 *k = key;
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = JHASH_INITVAL + length + initval;
|
||||
|
||||
/* All but the last block: affect some 32 bits of (a,b,c) */
|
||||
while (length > 12) {
|
||||
a += __get_unaligned_cpu32(k);
|
||||
b += __get_unaligned_cpu32(k + 4);
|
||||
c += __get_unaligned_cpu32(k + 8);
|
||||
__jhash_mix(a, b, c);
|
||||
length -= 12;
|
||||
k += 12;
|
||||
}
|
||||
/* Last block: affect all 32 bits of (c) */
|
||||
/* All the case statements fall through */
|
||||
switch (length) {
|
||||
case 12: c += (u32)k[11]<<24;
|
||||
case 11: c += (u32)k[10]<<16;
|
||||
case 10: c += (u32)k[9]<<8;
|
||||
case 9: c += k[8];
|
||||
case 8: b += (u32)k[7]<<24;
|
||||
case 7: b += (u32)k[6]<<16;
|
||||
case 6: b += (u32)k[5]<<8;
|
||||
case 5: b += k[4];
|
||||
case 4: a += (u32)k[3]<<24;
|
||||
case 3: a += (u32)k[2]<<16;
|
||||
case 2: a += (u32)k[1]<<8;
|
||||
case 1: a += k[0];
|
||||
__jhash_final(a, b, c);
|
||||
case 0: /* Nothing left to add */
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* jhash2 - hash an array of u32's
|
||||
* @k: the key which must be an array of u32's
|
||||
* @length: the number of u32's in the key
|
||||
* @initval: the previous hash, or an arbitray value
|
||||
*
|
||||
* Returns the hash value of the key.
|
||||
*/
|
||||
static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
|
||||
{
|
||||
u32 a, b, c;
|
||||
|
||||
/* Set up the internal state */
|
||||
a = b = c = JHASH_INITVAL + (length<<2) + initval;
|
||||
|
||||
/* Handle most of the key */
|
||||
while (length > 3) {
|
||||
a += k[0];
|
||||
b += k[1];
|
||||
c += k[2];
|
||||
__jhash_mix(a, b, c);
|
||||
length -= 3;
|
||||
k += 3;
|
||||
}
|
||||
|
||||
/* Handle the last 3 u32's: all the case statements fall through */
|
||||
switch (length) {
|
||||
case 3: c += k[2];
|
||||
case 2: b += k[1];
|
||||
case 1: a += k[0];
|
||||
__jhash_final(a, b, c);
|
||||
case 0: /* Nothing left to add */
|
||||
break;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* jhash_3words - hash exactly 3, 2 or 1 word(s) */
|
||||
static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
|
||||
{
|
||||
a += JHASH_INITVAL;
|
||||
b += JHASH_INITVAL;
|
||||
c += initval;
|
||||
|
||||
__jhash_final(a, b, c);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
|
||||
{
|
||||
return jhash_3words(a, b, 0, initval);
|
||||
}
|
||||
|
||||
static inline u32 jhash_1word(u32 a, u32 initval)
|
||||
{
|
||||
return jhash_3words(a, 0, 0, initval);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_JHASH_H */
|
||||
568
extensions/ipset-5/libipset/data.c
Normal file
568
extensions/ipset-5/libipset/data.c
Normal file
@@ -0,0 +1,568 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <assert.h> /* assert */
|
||||
#include <arpa/inet.h> /* ntoh* */
|
||||
#include <net/ethernet.h> /* ETH_ALEN */
|
||||
#include <sys/socket.h> /* AF_ */
|
||||
#include <stdlib.h> /* malloc, free */
|
||||
#include <string.h> /* memset */
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* IPSET_MAXNAMELEN */
|
||||
#include <libipset/debug.h> /* D() */
|
||||
#include <libipset/types.h> /* struct ipset_type */
|
||||
#include <libipset/utils.h> /* inXcpy */
|
||||
#include <libipset/data.h> /* prototypes */
|
||||
|
||||
/* Internal data structure to hold
|
||||
* a) input data entered by the user or
|
||||
* b) data received from kernel
|
||||
*
|
||||
* We always store the data in host order, *except* IP addresses.
|
||||
*/
|
||||
|
||||
struct ipset_data {
|
||||
/* Option bits: which fields are set */
|
||||
uint64_t bits;
|
||||
/* Option bits: which options are ignored */
|
||||
uint64_t ignored;
|
||||
/* Setname */
|
||||
char setname[IPSET_MAXNAMELEN];
|
||||
/* Set type */
|
||||
const struct ipset_type *type;
|
||||
/* Common CADT options */
|
||||
uint8_t cidr;
|
||||
uint8_t family;
|
||||
uint32_t flags; /* command level flags */
|
||||
uint32_t cadt_flags; /* data level flags */
|
||||
uint32_t timeout;
|
||||
union nf_inet_addr ip;
|
||||
union nf_inet_addr ip_to;
|
||||
uint16_t port;
|
||||
uint16_t port_to;
|
||||
union {
|
||||
/* RENAME/SWAP */
|
||||
char setname2[IPSET_MAXNAMELEN];
|
||||
/* CREATE/LIST/SAVE */
|
||||
struct {
|
||||
uint8_t probes;
|
||||
uint8_t resize;
|
||||
uint8_t netmask;
|
||||
uint32_t hashsize;
|
||||
uint32_t maxelem;
|
||||
uint32_t gc;
|
||||
uint32_t size;
|
||||
/* Filled out by kernel */
|
||||
uint32_t references;
|
||||
uint32_t elements;
|
||||
uint32_t memsize;
|
||||
char typename[IPSET_MAXNAMELEN];
|
||||
uint8_t revision_min;
|
||||
uint8_t revision;
|
||||
} create;
|
||||
/* ADT/LIST/SAVE */
|
||||
struct {
|
||||
union nf_inet_addr ip2;
|
||||
uint8_t cidr2;
|
||||
uint8_t proto;
|
||||
char ether[ETH_ALEN];
|
||||
char name[IPSET_MAXNAMELEN];
|
||||
char nameref[IPSET_MAXNAMELEN];
|
||||
} adt;
|
||||
};
|
||||
};
|
||||
|
||||
static void
|
||||
copy_addr(uint8_t family, union nf_inet_addr *ip, const void *value)
|
||||
{
|
||||
if (family == AF_INET)
|
||||
in4cpy(&ip->in, value);
|
||||
else
|
||||
in6cpy(&ip->in6, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_strlcpy - copy the string from src to dst
|
||||
* @dst: the target string buffer
|
||||
* @src: the source string buffer
|
||||
* @len: the length of bytes to copy, including the terminating null byte.
|
||||
*
|
||||
* Copy the string from src to destination, but at most len bytes are
|
||||
* copied. The target is unconditionally terminated by the null byte.
|
||||
*/
|
||||
void
|
||||
ipset_strlcpy(char *dst, const char *src, size_t len)
|
||||
{
|
||||
assert(dst);
|
||||
assert(src);
|
||||
|
||||
strncpy(dst, src, len);
|
||||
dst[len - 1] = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_flags_test - test option bits in the data blob
|
||||
* @data: data blob
|
||||
* @flags: the option flags to test
|
||||
*
|
||||
* Returns true if the options are already set in the data blob.
|
||||
*/
|
||||
bool
|
||||
ipset_data_flags_test(const struct ipset_data *data, uint64_t flags)
|
||||
{
|
||||
assert(data);
|
||||
return !!(data->bits & flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_flags_set - set option bits in the data blob
|
||||
* @data: data blob
|
||||
* @flags: the option flags to set
|
||||
*
|
||||
* The function sets the flags in the data blob so that
|
||||
* the corresponding fields are regarded as if filled with proper data.
|
||||
*/
|
||||
void
|
||||
ipset_data_flags_set(struct ipset_data *data, uint64_t flags)
|
||||
{
|
||||
assert(data);
|
||||
data->bits |= flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_flags_unset - unset option bits in the data blob
|
||||
* @data: data blob
|
||||
* @flags: the option flags to unset
|
||||
*
|
||||
* The function unsets the flags in the data blob.
|
||||
* This is the quick way to clear specific fields.
|
||||
*/
|
||||
void
|
||||
ipset_data_flags_unset(struct ipset_data *data, uint64_t flags)
|
||||
{
|
||||
assert(data);
|
||||
data->bits &= ~flags;
|
||||
}
|
||||
|
||||
#define flag_type_attr(data, opt, flag) \
|
||||
do { \
|
||||
data->flags |= flag; \
|
||||
opt = IPSET_OPT_FLAGS; \
|
||||
} while (0)
|
||||
|
||||
#define cadt_flag_type_attr(data, opt, flag) \
|
||||
do { \
|
||||
data->cadt_flags |= flag; \
|
||||
opt = IPSET_OPT_CADT_FLAGS; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* ipset_data_ignored - test and set ignored bits in the data blob
|
||||
* @data: data blob
|
||||
* @flags: the option flag to be ignored
|
||||
*
|
||||
* Returns true if the option was not already ignored.
|
||||
*/
|
||||
bool
|
||||
ipset_data_ignored(struct ipset_data *data, enum ipset_opt opt)
|
||||
{
|
||||
bool ignored;
|
||||
assert(data);
|
||||
|
||||
ignored = data->ignored & IPSET_FLAG(opt);
|
||||
data->ignored |= IPSET_FLAG(opt);
|
||||
|
||||
return ignored;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_set - put data into the data blob
|
||||
* @data: data blob
|
||||
* @opt: the option kind of the data
|
||||
* @value: the value of the data
|
||||
*
|
||||
* Put a given kind of data into the data blob and mark the
|
||||
* option kind as already set in the blob.
|
||||
*
|
||||
* Returns 0 on success or a negative error code.
|
||||
*/
|
||||
int
|
||||
ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
|
||||
{
|
||||
assert(data);
|
||||
assert(opt != IPSET_OPT_NONE);
|
||||
assert(value);
|
||||
|
||||
switch (opt) {
|
||||
/* Common ones */
|
||||
case IPSET_SETNAME:
|
||||
ipset_strlcpy(data->setname, value, IPSET_MAXNAMELEN);
|
||||
break;
|
||||
case IPSET_OPT_TYPE:
|
||||
data->type = value;
|
||||
break;
|
||||
case IPSET_OPT_FAMILY:
|
||||
data->family = *(const uint8_t *) value;
|
||||
D("family set to %u", data->family);
|
||||
break;
|
||||
/* CADT options */
|
||||
case IPSET_OPT_IP:
|
||||
if (!(data->family == AF_INET || data->family == AF_INET6))
|
||||
return -1;
|
||||
copy_addr(data->family, &data->ip, value);
|
||||
break;
|
||||
case IPSET_OPT_IP_TO:
|
||||
if (!(data->family == AF_INET || data->family == AF_INET6))
|
||||
return -1;
|
||||
copy_addr(data->family, &data->ip_to, value);
|
||||
break;
|
||||
case IPSET_OPT_CIDR:
|
||||
data->cidr = *(const uint8_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_PORT:
|
||||
data->port = *(const uint16_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_PORT_TO:
|
||||
data->port_to = *(const uint16_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_TIMEOUT:
|
||||
data->timeout = *(const uint32_t *) value;
|
||||
break;
|
||||
/* Create-specific options */
|
||||
case IPSET_OPT_GC:
|
||||
data->create.gc = *(const uint32_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_HASHSIZE:
|
||||
data->create.hashsize = *(const uint32_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_MAXELEM:
|
||||
data->create.maxelem = *(const uint32_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_NETMASK:
|
||||
data->create.netmask = *(const uint8_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_PROBES:
|
||||
data->create.probes = *(const uint8_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_RESIZE:
|
||||
data->create.resize = *(const uint8_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_SIZE:
|
||||
data->create.size = *(const uint32_t *) value;
|
||||
break;
|
||||
/* Create-specific options, filled out by the kernel */
|
||||
case IPSET_OPT_ELEMENTS:
|
||||
data->create.elements = *(const uint32_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_REFERENCES:
|
||||
data->create.references = *(const uint32_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_MEMSIZE:
|
||||
data->create.memsize = *(const uint32_t *) value;
|
||||
break;
|
||||
/* Create-specific options, type */
|
||||
case IPSET_OPT_TYPENAME:
|
||||
ipset_strlcpy(data->create.typename, value,
|
||||
IPSET_MAXNAMELEN);
|
||||
break;
|
||||
case IPSET_OPT_REVISION:
|
||||
data->create.revision = *(const uint8_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_REVISION_MIN:
|
||||
data->create.revision_min = *(const uint8_t *) value;
|
||||
break;
|
||||
/* ADT-specific options */
|
||||
case IPSET_OPT_ETHER:
|
||||
memcpy(data->adt.ether, value, ETH_ALEN);
|
||||
break;
|
||||
case IPSET_OPT_NAME:
|
||||
ipset_strlcpy(data->adt.name, value, IPSET_MAXNAMELEN);
|
||||
break;
|
||||
case IPSET_OPT_NAMEREF:
|
||||
ipset_strlcpy(data->adt.nameref, value, IPSET_MAXNAMELEN);
|
||||
break;
|
||||
case IPSET_OPT_IP2:
|
||||
if (!(data->family == AF_INET || data->family == AF_INET6))
|
||||
return -1;
|
||||
copy_addr(data->family, &data->adt.ip2, value);
|
||||
break;
|
||||
case IPSET_OPT_CIDR2:
|
||||
data->adt.cidr2 = *(const uint8_t *) value;
|
||||
break;
|
||||
case IPSET_OPT_PROTO:
|
||||
data->adt.proto = *(const uint8_t *) value;
|
||||
break;
|
||||
/* Swap/rename */
|
||||
case IPSET_OPT_SETNAME2:
|
||||
ipset_strlcpy(data->setname2, value, IPSET_MAXNAMELEN);
|
||||
break;
|
||||
/* flags */
|
||||
case IPSET_OPT_EXIST:
|
||||
flag_type_attr(data, opt, IPSET_FLAG_EXIST);
|
||||
break;
|
||||
case IPSET_OPT_BEFORE:
|
||||
cadt_flag_type_attr(data, opt, IPSET_FLAG_BEFORE);
|
||||
break;
|
||||
case IPSET_OPT_FLAGS:
|
||||
data->flags = *(const uint32_t *)value;
|
||||
break;
|
||||
case IPSET_OPT_CADT_FLAGS:
|
||||
data->cadt_flags = *(const uint32_t *)value;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
};
|
||||
|
||||
ipset_data_flags_set(data, IPSET_FLAG(opt));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_get - get data from the data blob
|
||||
* @data: data blob
|
||||
* @opt: option kind of the requested data
|
||||
*
|
||||
* Returns the pointer to the requested kind of data from the data blob
|
||||
* if it is set. If the option kind is not set or is an unkown type,
|
||||
* NULL is returned.
|
||||
*/
|
||||
const void *
|
||||
ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
|
||||
{
|
||||
assert(data);
|
||||
assert(opt != IPSET_OPT_NONE);
|
||||
|
||||
if (!(opt == IPSET_OPT_TYPENAME || ipset_data_test(data, opt)))
|
||||
return NULL;
|
||||
|
||||
switch (opt) {
|
||||
/* Common ones */
|
||||
case IPSET_SETNAME:
|
||||
return data->setname;
|
||||
case IPSET_OPT_TYPE:
|
||||
return data->type;
|
||||
case IPSET_OPT_TYPENAME:
|
||||
if (ipset_data_test(data, IPSET_OPT_TYPE))
|
||||
return data->type->name;
|
||||
else if (ipset_data_test(data, IPSET_OPT_TYPENAME))
|
||||
return data->create.typename;
|
||||
return NULL;
|
||||
case IPSET_OPT_FAMILY:
|
||||
return &data->family;
|
||||
/* CADT options */
|
||||
case IPSET_OPT_IP:
|
||||
return &data->ip;
|
||||
case IPSET_OPT_IP_TO:
|
||||
return &data->ip_to;
|
||||
case IPSET_OPT_CIDR:
|
||||
return &data->cidr;
|
||||
case IPSET_OPT_PORT:
|
||||
return &data->port;
|
||||
case IPSET_OPT_PORT_TO:
|
||||
return &data->port_to;
|
||||
case IPSET_OPT_TIMEOUT:
|
||||
return &data->timeout;
|
||||
/* Create-specific options */
|
||||
case IPSET_OPT_GC:
|
||||
return &data->create.gc;
|
||||
case IPSET_OPT_HASHSIZE:
|
||||
return &data->create.hashsize;
|
||||
case IPSET_OPT_MAXELEM:
|
||||
return &data->create.maxelem;
|
||||
case IPSET_OPT_NETMASK:
|
||||
return &data->create.netmask;
|
||||
case IPSET_OPT_PROBES:
|
||||
return &data->create.probes;
|
||||
case IPSET_OPT_RESIZE:
|
||||
return &data->create.resize;
|
||||
case IPSET_OPT_SIZE:
|
||||
return &data->create.size;
|
||||
/* Create-specific options, filled out by the kernel */
|
||||
case IPSET_OPT_ELEMENTS:
|
||||
return &data->create.elements;
|
||||
case IPSET_OPT_REFERENCES:
|
||||
return &data->create.references;
|
||||
case IPSET_OPT_MEMSIZE:
|
||||
return &data->create.memsize;
|
||||
/* Create-specific options, TYPE */
|
||||
case IPSET_OPT_REVISION:
|
||||
return &data->create.revision;
|
||||
case IPSET_OPT_REVISION_MIN:
|
||||
return &data->create.revision_min;
|
||||
/* ADT-specific options */
|
||||
case IPSET_OPT_ETHER:
|
||||
return data->adt.ether;
|
||||
case IPSET_OPT_NAME:
|
||||
return data->adt.name;
|
||||
case IPSET_OPT_NAMEREF:
|
||||
return data->adt.nameref;
|
||||
case IPSET_OPT_IP2:
|
||||
return &data->adt.ip2;
|
||||
case IPSET_OPT_CIDR2:
|
||||
return &data->adt.cidr2;
|
||||
case IPSET_OPT_PROTO:
|
||||
return &data->adt.proto;
|
||||
/* Swap/rename */
|
||||
case IPSET_OPT_SETNAME2:
|
||||
return data->setname2;
|
||||
/* flags */
|
||||
case IPSET_OPT_FLAGS:
|
||||
case IPSET_OPT_EXIST:
|
||||
return &data->flags;
|
||||
case IPSET_OPT_CADT_FLAGS:
|
||||
case IPSET_OPT_BEFORE:
|
||||
return &data->cadt_flags;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_sizeof - calculates the size of the data type
|
||||
* @opt: option kind of the data
|
||||
* @family: INET family
|
||||
*
|
||||
* Returns the size required to store the given data type.
|
||||
*/
|
||||
size_t
|
||||
ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
|
||||
{
|
||||
assert(opt != IPSET_OPT_NONE);
|
||||
|
||||
switch (opt) {
|
||||
case IPSET_OPT_IP:
|
||||
case IPSET_OPT_IP_TO:
|
||||
case IPSET_OPT_IP2:
|
||||
return family == AF_INET ? sizeof(uint32_t)
|
||||
: sizeof(struct in6_addr);
|
||||
case IPSET_OPT_PORT:
|
||||
case IPSET_OPT_PORT_TO:
|
||||
return sizeof(uint16_t);
|
||||
case IPSET_SETNAME:
|
||||
case IPSET_OPT_NAME:
|
||||
case IPSET_OPT_NAMEREF:
|
||||
return IPSET_MAXNAMELEN;
|
||||
case IPSET_OPT_TIMEOUT:
|
||||
case IPSET_OPT_GC:
|
||||
case IPSET_OPT_HASHSIZE:
|
||||
case IPSET_OPT_MAXELEM:
|
||||
case IPSET_OPT_SIZE:
|
||||
case IPSET_OPT_ELEMENTS:
|
||||
case IPSET_OPT_REFERENCES:
|
||||
case IPSET_OPT_MEMSIZE:
|
||||
return sizeof(uint32_t);
|
||||
case IPSET_OPT_CIDR:
|
||||
case IPSET_OPT_CIDR2:
|
||||
case IPSET_OPT_NETMASK:
|
||||
case IPSET_OPT_PROBES:
|
||||
case IPSET_OPT_RESIZE:
|
||||
case IPSET_OPT_PROTO:
|
||||
return sizeof(uint8_t);
|
||||
case IPSET_OPT_ETHER:
|
||||
return ETH_ALEN;
|
||||
/* Flags counted once */
|
||||
case IPSET_OPT_BEFORE:
|
||||
return sizeof(uint32_t);
|
||||
default:
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_setname - return the name of the set from the data blob
|
||||
* @data: data blob
|
||||
*
|
||||
* Return the name of the set from the data blob or NULL if the
|
||||
* name not set yet.
|
||||
*/
|
||||
const char *
|
||||
ipset_data_setname(const struct ipset_data *data)
|
||||
{
|
||||
assert(data);
|
||||
return ipset_data_test(data, IPSET_SETNAME) ? data->setname : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_family - return the INET family of the set from the data blob
|
||||
* @data: data blob
|
||||
*
|
||||
* Return the INET family supported by the set from the data blob.
|
||||
* If the family is not set yet, AF_UNSPEC is returned.
|
||||
*/
|
||||
uint8_t
|
||||
ipset_data_family(const struct ipset_data *data)
|
||||
{
|
||||
assert(data);
|
||||
return ipset_data_test(data, IPSET_OPT_FAMILY)
|
||||
? data->family : AF_UNSPEC;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_cidr - return the value of IPSET_OPT_CIDR
|
||||
* @data: data blob
|
||||
*
|
||||
* Return the value of IPSET_OPT_CIDR stored in the data blob.
|
||||
* If it is not set, then the returned value corresponds to
|
||||
* the default one according to the family type or zero.
|
||||
*/
|
||||
uint8_t
|
||||
ipset_data_cidr(const struct ipset_data *data)
|
||||
{
|
||||
assert(data);
|
||||
return ipset_data_test(data, IPSET_OPT_CIDR) ? data->cidr :
|
||||
data->family == AF_INET ? 32 :
|
||||
data->family == AF_INET6 ? 128 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_flags - return which fields are set in the data blob
|
||||
* @data: data blob
|
||||
*
|
||||
* Returns the value of the bit field which elements are set.
|
||||
*/
|
||||
uint64_t
|
||||
ipset_data_flags(const struct ipset_data *data)
|
||||
{
|
||||
assert(data);
|
||||
return data->bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_reset - reset the data blob to unset
|
||||
* @data: data blob
|
||||
*
|
||||
* Resets the data blob to the unset state for every field.
|
||||
*/
|
||||
void
|
||||
ipset_data_reset(struct ipset_data *data)
|
||||
{
|
||||
assert(data);
|
||||
memset(data, 0, sizeof(*data));
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_init - create a new data blob
|
||||
*
|
||||
* Return the new data blob initialized to empty. In case of
|
||||
* an error, NULL is retured.
|
||||
*/
|
||||
struct ipset_data *
|
||||
ipset_data_init(void)
|
||||
{
|
||||
return calloc(1, sizeof(struct ipset_data));
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_data_fini - release a data blob created by ipset_data_init
|
||||
*
|
||||
* Release the data blob created by ipset_data_init previously.
|
||||
*/
|
||||
void
|
||||
ipset_data_fini(struct ipset_data *data)
|
||||
{
|
||||
assert(data);
|
||||
free(data);
|
||||
}
|
||||
79
extensions/ipset-5/libipset/icmp.c
Normal file
79
extensions/ipset-5/libipset/icmp.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/utils.h> /* STRNEQ */
|
||||
#include <libipset/icmp.h> /* prototypes */
|
||||
|
||||
struct icmp_names {
|
||||
const char *name;
|
||||
uint8_t type, code;
|
||||
};
|
||||
|
||||
static const struct icmp_names icmp_typecodes[] = {
|
||||
{ "echo-reply", 0, 0 },
|
||||
{ "pong", 0, 0 },
|
||||
{ "network-unreachable", 3, 0 },
|
||||
{ "host-unreachable", 3, 1 },
|
||||
{ "protocol-unreachable", 3, 2 },
|
||||
{ "port-unreachable", 3, 3 },
|
||||
{ "fragmentation-needed", 3, 4 },
|
||||
{ "source-route-failed", 3, 5 },
|
||||
{ "network-unknown", 3, 6 },
|
||||
{ "host-unknown", 3, 7 },
|
||||
{ "network-prohibited", 3, 9 },
|
||||
{ "host-prohibited", 3, 10 },
|
||||
{ "TOS-network-unreachable", 3, 11 },
|
||||
{ "TOS-host-unreachable", 3, 12 },
|
||||
{ "communication-prohibited", 3, 13 },
|
||||
{ "host-precedence-violation", 3, 14 },
|
||||
{ "precedence-cutoff", 3, 15 },
|
||||
{ "source-quench", 4, 0 },
|
||||
{ "network-redirect", 5, 0 },
|
||||
{ "host-redirect", 5, 1 },
|
||||
{ "TOS-network-redirect", 5, 2 },
|
||||
{ "TOS-host-redirect", 5, 3 },
|
||||
{ "echo-request", 8, 0 },
|
||||
{ "ping", 8, 0 },
|
||||
{ "router-advertisement", 9, 0 },
|
||||
{ "router-solicitation", 10, 0 },
|
||||
{ "ttl-zero-during-transit", 11, 0 },
|
||||
{ "ttl-zero-during-reassembly", 11, 1 },
|
||||
{ "ip-header-bad", 12, 0 },
|
||||
{ "required-option-missing", 12, 1 },
|
||||
{ "timestamp-request", 13, 0 },
|
||||
{ "timestamp-reply", 14, 0 },
|
||||
{ "address-mask-request", 17, 0 },
|
||||
{ "address-mask-reply", 18, 0 },
|
||||
};
|
||||
|
||||
const char * id_to_icmp(uint8_t id)
|
||||
{
|
||||
return id < ARRAY_SIZE(icmp_typecodes) ? icmp_typecodes[id].name : NULL;
|
||||
}
|
||||
|
||||
const char * icmp_to_name(uint8_t type, uint8_t code)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(icmp_typecodes); i++)
|
||||
if (icmp_typecodes[i].type == type && icmp_typecodes[i].code == code)
|
||||
return icmp_typecodes[i].name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int name_to_icmp(const char *str, uint16_t *typecode)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(icmp_typecodes); i++)
|
||||
if (STRNCASEQ(icmp_typecodes[i].name, str, strlen(str))) {
|
||||
*typecode = (icmp_typecodes[i].type << 8) | icmp_typecodes[i].code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
66
extensions/ipset-5/libipset/icmpv6.c
Normal file
66
extensions/ipset-5/libipset/icmpv6.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/utils.h> /* STRNEQ */
|
||||
#include <libipset/icmpv6.h> /* prototypes */
|
||||
|
||||
struct icmpv6_names {
|
||||
const char *name;
|
||||
uint8_t type, code;
|
||||
};
|
||||
|
||||
static const struct icmpv6_names icmpv6_typecodes[] = {
|
||||
{ "no-route", 1, 0 },
|
||||
{ "communication-prohibited", 1, 1 },
|
||||
{ "address-unreachable", 1, 3 },
|
||||
{ "port-unreachable", 1, 4 },
|
||||
{ "packet-too-big", 2, 0 },
|
||||
{ "ttl-zero-during-transit", 3, 0 },
|
||||
{ "ttl-zero-during-reassembly", 3, 1 },
|
||||
{ "bad-header", 4, 0 },
|
||||
{ "unknown-header-type", 4, 1 },
|
||||
{ "unknown-option", 4, 2 },
|
||||
{ "echo-request", 128, 0 },
|
||||
{ "ping", 128, 0 },
|
||||
{ "echo-reply", 129, 0 },
|
||||
{ "pong", 129, 0 },
|
||||
{ "router-solicitation", 133, 0 },
|
||||
{ "router-advertisement", 134, 0 },
|
||||
{ "neighbour-solicitation", 135, 0 },
|
||||
{ "neigbour-solicitation", 135, 0 },
|
||||
{ "neighbour-advertisement", 136, 0 },
|
||||
{ "neigbour-advertisement", 136, 0 },
|
||||
{ "redirect", 137, 0 },
|
||||
};
|
||||
|
||||
const char * id_to_icmpv6(uint8_t id)
|
||||
{
|
||||
return id < ARRAY_SIZE(icmpv6_typecodes) ? icmpv6_typecodes[id].name : NULL;
|
||||
}
|
||||
|
||||
const char * icmpv6_to_name(uint8_t type, uint8_t code)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(icmpv6_typecodes); i++)
|
||||
if (icmpv6_typecodes[i].type == type && icmpv6_typecodes[i].code == code)
|
||||
return icmpv6_typecodes[i].name;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int name_to_icmpv6(const char *str, uint16_t *typecode)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(icmpv6_typecodes); i++)
|
||||
if (STRNCASEQ(icmpv6_typecodes[i].name, str, strlen(str))) {
|
||||
*typecode = (icmpv6_typecodes[i].type << 8) | icmpv6_typecodes[i].code;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
258
extensions/ipset-5/libipset/mnl.c
Normal file
258
extensions/ipset-5/libipset/mnl.c
Normal file
@@ -0,0 +1,258 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <assert.h> /* assert */
|
||||
#include <errno.h> /* errno */
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h> /* calloc, free */
|
||||
#include <time.h> /* time */
|
||||
#include <arpa/inet.h> /* hto* */
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
|
||||
#include <libipset/debug.h> /* D() */
|
||||
#include <libipset/session.h> /* ipset_session_handle */
|
||||
#include <libipset/ui.h> /* IPSET_ENV_EXIST */
|
||||
#include <libipset/utils.h> /* UNUSED */
|
||||
#include <libipset/mnl.h> /* prototypes */
|
||||
|
||||
#include <libmnl/libmnl.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <linux/netlink.h>
|
||||
|
||||
#ifndef NFNL_SUBSYS_IPSET
|
||||
#define NFNL_SUBSYS_IPSET 6
|
||||
#endif
|
||||
|
||||
/* Internal data structure for the kernel-userspace communication parameters */
|
||||
struct ipset_handle {
|
||||
struct mnl_socket *h; /* the mnl socket */
|
||||
unsigned int seq; /* netlink message sequence number */
|
||||
unsigned int portid; /* the socket port identifier */
|
||||
mnl_cb_t *cb_ctl; /* control block callbacks */
|
||||
void *data; /* data pointer */
|
||||
unsigned int genl_id; /* genetlink ID of ip_set */
|
||||
};
|
||||
|
||||
/* Netlink flags of the commands */
|
||||
static const uint16_t cmdflags[] = {
|
||||
[IPSET_CMD_CREATE-1] = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL,
|
||||
[IPSET_CMD_DESTROY-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_FLUSH-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_RENAME-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_SWAP-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_LIST-1] = NLM_F_REQUEST,
|
||||
[IPSET_CMD_SAVE-1] = NLM_F_REQUEST,
|
||||
[IPSET_CMD_ADD-1] = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL,
|
||||
[IPSET_CMD_DEL-1] = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL,
|
||||
[IPSET_CMD_TEST-1] = NLM_F_REQUEST|NLM_F_ACK,
|
||||
[IPSET_CMD_HEADER-1] = NLM_F_REQUEST,
|
||||
[IPSET_CMD_TYPE-1] = NLM_F_REQUEST,
|
||||
[IPSET_CMD_PROTOCOL-1] = NLM_F_REQUEST,
|
||||
};
|
||||
|
||||
/**
|
||||
* ipset_get_nlmsg_type - get ipset netlink message type
|
||||
* @nlh: pointer to the netlink message header
|
||||
*
|
||||
* Returns the ipset netlink message type, i.e. the ipset command.
|
||||
*/
|
||||
int
|
||||
ipset_get_nlmsg_type(const struct nlmsghdr *nlh)
|
||||
{
|
||||
const struct genlmsghdr *ghdr = mnl_nlmsg_get_payload(nlh);
|
||||
|
||||
return ghdr->cmd;
|
||||
}
|
||||
|
||||
static void
|
||||
ipset_mnl_fill_hdr(struct ipset_handle *handle, enum ipset_cmd cmd,
|
||||
void *buffer, size_t len UNUSED, uint8_t envflags)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct genlmsghdr *ghdr;
|
||||
|
||||
assert(handle);
|
||||
assert(buffer);
|
||||
assert(cmd > IPSET_CMD_NONE && cmd < IPSET_MSG_MAX);
|
||||
|
||||
nlh = mnl_nlmsg_put_header(buffer);
|
||||
nlh->nlmsg_type = handle->genl_id;
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||
if (cmdflags[cmd-1] & NLM_F_ACK)
|
||||
nlh->nlmsg_flags |= NLM_F_ACK;
|
||||
nlh->nlmsg_seq = handle->seq = time(NULL);
|
||||
|
||||
ghdr = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr));
|
||||
ghdr->cmd = cmd;
|
||||
/* (ge)netlink is dumb, NLM_F_CREATE and NLM_F_DUMP overlap, get misinterpreted. */
|
||||
ghdr->reserved = cmdflags[cmd-1];
|
||||
if (envflags & IPSET_ENV_EXIST)
|
||||
ghdr->reserved &= ~NLM_F_EXCL;
|
||||
}
|
||||
|
||||
static int
|
||||
ipset_mnl_query(struct ipset_handle *handle, void *buffer, size_t len)
|
||||
{
|
||||
struct nlmsghdr *nlh = buffer;
|
||||
int ret;
|
||||
|
||||
assert(handle);
|
||||
assert(buffer);
|
||||
|
||||
if (mnl_socket_sendto(handle->h, nlh, nlh->nlmsg_len) < 0)
|
||||
return -ECOMM;
|
||||
|
||||
D("message sent");
|
||||
ret = mnl_socket_recvfrom(handle->h, buffer, len);
|
||||
D("message received, ret: %d", ret);
|
||||
while (ret > 0) {
|
||||
ret = mnl_cb_run2(buffer, ret,
|
||||
handle->seq, handle->portid,
|
||||
handle->cb_ctl[NLMSG_MIN_TYPE],
|
||||
handle->data,
|
||||
handle->cb_ctl, NLMSG_MIN_TYPE);
|
||||
D("nfln_cb_run2, ret: %d", ret);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ret = mnl_socket_recvfrom(handle->h, buffer, len);
|
||||
D("message received, ret: %d", ret);
|
||||
}
|
||||
return ret > 0 ? 0 : ret;
|
||||
}
|
||||
|
||||
static int ipset_mnl_getid_acb(const struct nlattr *attr, void *datap)
|
||||
{
|
||||
const struct nlattr **tb = datap;
|
||||
uint16_t type = mnl_attr_get_type(attr);
|
||||
|
||||
if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
|
||||
return MNL_CB_OK;
|
||||
tb[type] = attr;
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
static int ipset_mnl_getid_cb(const struct nlmsghdr *nlhdr, void *datap)
|
||||
{
|
||||
struct ipset_handle *h = datap;
|
||||
const struct nlattr *tb[CTRL_ATTR_MAX+1] = {0};
|
||||
const struct genlmsghdr *ghdr = mnl_nlmsg_get_payload(nlhdr);
|
||||
int ret;
|
||||
|
||||
ret = mnl_attr_parse(nlhdr, sizeof(*ghdr), ipset_mnl_getid_acb, tb);
|
||||
if (ret != MNL_CB_OK)
|
||||
return ret;
|
||||
if (tb[CTRL_ATTR_FAMILY_ID] != NULL)
|
||||
h->genl_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]);
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the GENL identifier for the ip_set subsystem, and store it in
|
||||
* @h->genl_id. On success, 0 is returned, otherwise error encoded as
|
||||
* negative number.
|
||||
*/
|
||||
static int ipset_mnl_getid(struct ipset_handle *h, bool modprobe)
|
||||
{
|
||||
size_t buf_size = 8192; //MNL_SOCKET_BUFFER_SIZE;
|
||||
struct nlmsghdr *nlhdr;
|
||||
struct genlmsghdr *ghdr;
|
||||
char *buf;
|
||||
int ret = -ENOENT;
|
||||
|
||||
h->genl_id = 0;
|
||||
|
||||
if (modprobe) {
|
||||
/* genetlink has no autoloading like nfnetlink... */
|
||||
system("/sbin/modprobe -q ip_set");
|
||||
}
|
||||
|
||||
buf = malloc(buf_size);
|
||||
if (buf == NULL)
|
||||
return -errno;
|
||||
|
||||
nlhdr = mnl_nlmsg_put_header(buf);
|
||||
nlhdr->nlmsg_type = GENL_ID_CTRL;
|
||||
nlhdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
|
||||
ghdr = mnl_nlmsg_put_extra_header(nlhdr, sizeof(struct genlmsghdr));
|
||||
ghdr->cmd = CTRL_CMD_GETFAMILY;
|
||||
ghdr->version = 2;
|
||||
if (!mnl_attr_put_strz_check(nlhdr, buf_size,
|
||||
CTRL_ATTR_FAMILY_NAME, "ip_set"))
|
||||
goto out;
|
||||
|
||||
ret = mnl_socket_sendto(h->h, buf, nlhdr->nlmsg_len);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
ret = mnl_socket_recvfrom(h->h, buf, buf_size);
|
||||
while (ret > 0) {
|
||||
ret = mnl_cb_run(buf, ret, 0, 0, ipset_mnl_getid_cb, h);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ret = mnl_socket_recvfrom(h->h, buf, buf_size);
|
||||
}
|
||||
if (h->genl_id == 0 && !modprobe)
|
||||
/* Redo, with modprobe this time. */
|
||||
ret = ipset_mnl_getid(h, true);
|
||||
if (h->genl_id > 0)
|
||||
ret = 0;
|
||||
out:
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct ipset_handle *
|
||||
ipset_mnl_init(mnl_cb_t *cb_ctl, void *data)
|
||||
{
|
||||
struct ipset_handle *handle;
|
||||
|
||||
assert(cb_ctl);
|
||||
assert(data);
|
||||
|
||||
handle = calloc(1, sizeof(*handle));
|
||||
if (!handle)
|
||||
return NULL;
|
||||
|
||||
handle->h = mnl_socket_open(NETLINK_GENERIC);
|
||||
if (!handle->h)
|
||||
goto free_handle;
|
||||
|
||||
if (mnl_socket_bind(handle->h, 0, MNL_SOCKET_AUTOPID) < 0)
|
||||
goto close_nl;
|
||||
|
||||
handle->portid = mnl_socket_get_portid(handle->h);
|
||||
handle->cb_ctl = cb_ctl;
|
||||
handle->data = data;
|
||||
|
||||
if (ipset_mnl_getid(handle, false) < 0)
|
||||
goto close_nl;
|
||||
return handle;
|
||||
|
||||
close_nl:
|
||||
mnl_socket_close(handle->h);
|
||||
free_handle:
|
||||
free(handle);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
ipset_mnl_fini(struct ipset_handle *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
if (handle->h)
|
||||
mnl_socket_close(handle->h);
|
||||
|
||||
free(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ipset_transport ipset_mnl_transport = {
|
||||
.init = ipset_mnl_init,
|
||||
.fini = ipset_mnl_fini,
|
||||
.fill_hdr = ipset_mnl_fill_hdr,
|
||||
.query = ipset_mnl_query,
|
||||
};
|
||||
1526
extensions/ipset-5/libipset/parse.c
Normal file
1526
extensions/ipset-5/libipset/parse.c
Normal file
File diff suppressed because it is too large
Load Diff
743
extensions/ipset-5/libipset/print.c
Normal file
743
extensions/ipset-5/libipset/print.c
Normal file
@@ -0,0 +1,743 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <assert.h> /* assert */
|
||||
#include <errno.h> /* errno */
|
||||
#include <stdio.h> /* snprintf */
|
||||
#include <netdb.h> /* getservbyport */
|
||||
#include <sys/types.h> /* inet_ntop */
|
||||
#include <sys/socket.h> /* inet_ntop */
|
||||
#include <arpa/inet.h> /* inet_ntop */
|
||||
#include <net/ethernet.h> /* ETH_ALEN */
|
||||
|
||||
#include <libipset/debug.h> /* D() */
|
||||
#include <libipset/data.h> /* ipset_data_* */
|
||||
#include <libipset/icmp.h> /* icmp_to_name */
|
||||
#include <libipset/icmpv6.h> /* icmpv6_to_name */
|
||||
#include <libipset/parse.h> /* IPSET_*_SEPARATOR */
|
||||
#include <libipset/types.h> /* ipset set types */
|
||||
#include <libipset/session.h> /* IPSET_FLAG_ */
|
||||
#include <libipset/utils.h> /* UNUSED */
|
||||
#include <libipset/ui.h> /* IPSET_ENV_* */
|
||||
#include <libipset/print.h> /* prototypes */
|
||||
|
||||
/* Print data (to output buffer). All function must follow snprintf. */
|
||||
|
||||
#define SNPRINTF_FAILURE(size, len, offset) \
|
||||
do { \
|
||||
if (size < 0 || (unsigned int) size >= len) \
|
||||
return size; \
|
||||
offset += size; \
|
||||
len -= size; \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* ipset_print_ether - print ethernet address to string
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print Ethernet address to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_ether(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const unsigned char *ether;
|
||||
int i, size, offset = 0;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_ETHER);
|
||||
|
||||
if (len < ETH_ALEN*3)
|
||||
return -1;
|
||||
|
||||
ether = ipset_data_get(data, opt);
|
||||
assert(ether);
|
||||
|
||||
size = snprintf(buf, len, "%02X", ether[0]);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
for (i = 1; i < ETH_ALEN; i++) {
|
||||
size = snprintf(buf + offset, len, ":%02X", ether[i]);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_family - print INET family
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print INET family string to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_family(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
uint8_t family;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_FAMILY);
|
||||
|
||||
if (len < strlen("inet6") + 1)
|
||||
return -1;
|
||||
|
||||
family = ipset_data_family(data);
|
||||
|
||||
return snprintf(buf, len, "%s",
|
||||
family == AF_INET ? "inet" :
|
||||
family == AF_INET6 ? "inet6" : "any");
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_type - print ipset type string
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print ipset module string identifier to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_type(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const struct ipset_type *type;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_TYPE);
|
||||
|
||||
type = ipset_data_get(data, opt);
|
||||
assert(type);
|
||||
if (len < strlen(type->name) + 1)
|
||||
return -1;
|
||||
|
||||
return snprintf(buf, len, "%s", type->name);
|
||||
}
|
||||
|
||||
#define GETNAMEINFO(family, f, n) \
|
||||
static inline int \
|
||||
__getnameinfo##f(char *buf, unsigned int len, \
|
||||
int flags, const union nf_inet_addr *addr) \
|
||||
{ \
|
||||
struct sockaddr_in##n saddr; \
|
||||
int err; \
|
||||
\
|
||||
memset(&saddr, 0, sizeof(saddr)); \
|
||||
in##f##cpy(&saddr.sin##n##_addr, &addr->in##n); \
|
||||
saddr.sin##n##_family = family; \
|
||||
\
|
||||
err = getnameinfo((const struct sockaddr *)&saddr, \
|
||||
sizeof(saddr), \
|
||||
buf, len, NULL, 0, flags); \
|
||||
\
|
||||
if (err == EAI_AGAIN && !(flags & NI_NUMERICHOST)) \
|
||||
err = getnameinfo((const struct sockaddr *)&saddr, \
|
||||
sizeof(saddr), \
|
||||
buf, len, NULL, 0, \
|
||||
flags | NI_NUMERICHOST); \
|
||||
D("getnameinfo err: %i, errno %i", err, errno); \
|
||||
return (err == 0 ? (int)strlen(buf) : \
|
||||
(err == EAI_OVERFLOW || err == EAI_SYSTEM) ? (int)len : -1);\
|
||||
}
|
||||
|
||||
#define SNPRINTF_IP(mask, f) \
|
||||
static int \
|
||||
snprintf_ipv##f(char *buf, unsigned int len, int flags, \
|
||||
const union nf_inet_addr *ip, uint8_t cidr) \
|
||||
{ \
|
||||
int size, offset = 0; \
|
||||
\
|
||||
size = __getnameinfo##f(buf, len, flags, ip); \
|
||||
SNPRINTF_FAILURE(size, len, offset); \
|
||||
\
|
||||
D("cidr %u mask %u", cidr, mask); \
|
||||
if (cidr == mask) \
|
||||
return offset; \
|
||||
D("print cidr"); \
|
||||
size = snprintf(buf + offset, len, \
|
||||
"%s%u", IPSET_CIDR_SEPARATOR, cidr); \
|
||||
SNPRINTF_FAILURE(size, len, offset); \
|
||||
return offset; \
|
||||
}
|
||||
|
||||
GETNAMEINFO(AF_INET, 4, )
|
||||
SNPRINTF_IP(32, 4)
|
||||
|
||||
GETNAMEINFO(AF_INET6, 6, 6)
|
||||
SNPRINTF_IP(128, 6)
|
||||
|
||||
/**
|
||||
* ipset_print_ip - print IPv4|IPv6 address to string
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print IPv4|IPv6 address, address/cidr or address range to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_ip(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env)
|
||||
{
|
||||
const union nf_inet_addr *ip;
|
||||
uint8_t family, cidr;
|
||||
int flags, size, offset = 0;
|
||||
enum ipset_opt cidropt;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
|
||||
|
||||
D("len: %u", len);
|
||||
family = ipset_data_family(data);
|
||||
cidropt = opt == IPSET_OPT_IP ? IPSET_OPT_CIDR : IPSET_OPT_CIDR2;
|
||||
if (ipset_data_test(data, cidropt)) {
|
||||
cidr = *(const uint8_t *) ipset_data_get(data, cidropt);
|
||||
D("CIDR: %u", cidr);
|
||||
} else
|
||||
cidr = family == AF_INET6 ? 128 : 32;
|
||||
flags = env & (1 << IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;
|
||||
|
||||
ip = ipset_data_get(data, opt);
|
||||
assert(ip);
|
||||
if (family == AF_INET)
|
||||
size = snprintf_ipv4(buf, len, flags, ip, cidr);
|
||||
else if (family == AF_INET6)
|
||||
size = snprintf_ipv6(buf, len, flags, ip, cidr);
|
||||
else
|
||||
return -1;
|
||||
D("size %i, len %u", size, len);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
D("len: %u, offset %u", len, offset);
|
||||
if (!ipset_data_test(data, IPSET_OPT_IP_TO))
|
||||
return offset;
|
||||
|
||||
size = snprintf(buf + offset, len, "%s", IPSET_RANGE_SEPARATOR);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
ip = ipset_data_get(data, IPSET_OPT_IP_TO);
|
||||
if (family == AF_INET)
|
||||
size = snprintf_ipv4(buf + offset, len, flags, ip, cidr);
|
||||
else if (family == AF_INET6)
|
||||
size = snprintf_ipv6(buf + offset, len, flags, ip, cidr);
|
||||
else
|
||||
return -1;
|
||||
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_ipaddr - print IPv4|IPv6 address to string
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print IPv4|IPv6 address or address/cidr to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_ipaddr(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env)
|
||||
{
|
||||
const union nf_inet_addr *ip;
|
||||
uint8_t family, cidr;
|
||||
enum ipset_opt cidropt;
|
||||
int flags;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_IP
|
||||
|| opt == IPSET_OPT_IP_TO
|
||||
|| opt == IPSET_OPT_IP2);
|
||||
|
||||
family = ipset_data_family(data);
|
||||
cidropt = opt == IPSET_OPT_IP ? IPSET_OPT_CIDR : IPSET_OPT_CIDR2;
|
||||
if (ipset_data_test(data, cidropt))
|
||||
cidr = *(const uint8_t *) ipset_data_get(data, cidropt);
|
||||
else
|
||||
cidr = family == AF_INET6 ? 128 : 32;
|
||||
flags = env & (1 << IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;
|
||||
|
||||
ip = ipset_data_get(data, opt);
|
||||
assert(ip);
|
||||
if (family == AF_INET)
|
||||
return snprintf_ipv4(buf, len, flags, ip, cidr);
|
||||
else if (family == AF_INET6)
|
||||
return snprintf_ipv6(buf, len, flags, ip, cidr);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_number - print number to string
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print number to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_number(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
size_t maxsize;
|
||||
const void *number;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
|
||||
number = ipset_data_get(data, opt);
|
||||
maxsize = ipset_data_sizeof(opt, AF_INET);
|
||||
D("opt: %u, maxsize %zu", opt, maxsize);
|
||||
if (maxsize == sizeof(uint8_t))
|
||||
return snprintf(buf, len, "%u", *(const uint8_t *) number);
|
||||
else if (maxsize == sizeof(uint16_t))
|
||||
return snprintf(buf, len, "%u", *(const uint16_t *) number);
|
||||
else if (maxsize == sizeof(uint32_t))
|
||||
return snprintf(buf, len, "%lu",
|
||||
(long unsigned) *(const uint32_t *) number);
|
||||
else
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_name - print setname element string
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print setname element string to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_name(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const char *name;
|
||||
int size, offset = 0;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_NAME);
|
||||
|
||||
if (len < 2*IPSET_MAXNAMELEN + 2 + strlen("before"))
|
||||
return -1;
|
||||
|
||||
name = ipset_data_get(data, opt);
|
||||
assert(name);
|
||||
size = snprintf(buf, len, "%s", name);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
if (ipset_data_test(data, IPSET_OPT_NAMEREF)) {
|
||||
bool before = false;
|
||||
if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_FLAGS))) {
|
||||
const uint32_t *flags =
|
||||
ipset_data_get(data, IPSET_OPT_FLAGS);
|
||||
before = (*flags) & IPSET_FLAG_BEFORE;
|
||||
}
|
||||
size = snprintf(buf + offset, len,
|
||||
" %s %s", before ? "before" : "after",
|
||||
(const char *) ipset_data_get(data,
|
||||
IPSET_OPT_NAMEREF));
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_port - print port or port range
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print port or port range to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_port(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const uint16_t *port;
|
||||
int size, offset = 0;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_PORT);
|
||||
|
||||
if (len < 2*strlen("65535") + 2)
|
||||
return -1;
|
||||
|
||||
port = ipset_data_get(data, IPSET_OPT_PORT);
|
||||
assert(port);
|
||||
size = snprintf(buf, len, "%u", *port);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
if (ipset_data_test(data, IPSET_OPT_PORT_TO)) {
|
||||
port = ipset_data_get(data, IPSET_OPT_PORT_TO);
|
||||
size = snprintf(buf + offset, len,
|
||||
"%s%u",
|
||||
IPSET_RANGE_SEPARATOR, *port);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_proto - print protocol name
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print protocol name to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_proto(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const struct protoent *protoent;
|
||||
uint8_t proto;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_PROTO);
|
||||
|
||||
proto = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO);
|
||||
assert(proto);
|
||||
|
||||
protoent = getprotobynumber(proto);
|
||||
if (protoent)
|
||||
return snprintf(buf, len, "%s", protoent->p_name);
|
||||
|
||||
/* Should not happen */
|
||||
return snprintf(buf, len, "%u", proto);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_icmp - print ICMP code name or type/code
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print ICMP code name or type/code name to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_icmp(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const char *name;
|
||||
uint16_t typecode;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_PORT);
|
||||
|
||||
typecode = *(const uint16_t *) ipset_data_get(data, IPSET_OPT_PORT);
|
||||
name = icmp_to_name(typecode >> 8, typecode & 0xFF);
|
||||
if (name != NULL)
|
||||
return snprintf(buf, len, "%s", name);
|
||||
else
|
||||
return snprintf(buf, len, "%u/%u", typecode >> 8, typecode & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_icmpv6 - print ICMPv6 code name or type/code
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print ICMPv6 code name or type/code name to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_icmpv6(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
const char *name;
|
||||
uint16_t typecode;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_PORT);
|
||||
|
||||
typecode = *(const uint16_t *) ipset_data_get(data, IPSET_OPT_PORT);
|
||||
name = icmpv6_to_name(typecode >> 8, typecode & 0xFF);
|
||||
if (name != NULL)
|
||||
return snprintf(buf, len, "%s", name);
|
||||
else
|
||||
return snprintf(buf, len, "%u/%u", typecode >> 8, typecode & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_proto_port - print proto:port
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print protocol and port to output buffer.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_proto_port(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env UNUSED)
|
||||
{
|
||||
int size, offset = 0;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
assert(opt == IPSET_OPT_PORT);
|
||||
|
||||
if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_PROTO))) {
|
||||
uint8_t proto = *(const uint8_t *) ipset_data_get(data,
|
||||
IPSET_OPT_PROTO);
|
||||
size = ipset_print_proto(buf, len, data, IPSET_OPT_PROTO, env);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
if (len < 2)
|
||||
return -ENOSPC;
|
||||
size = snprintf(buf + offset, len, IPSET_PROTO_SEPARATOR);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
break;
|
||||
case IPPROTO_ICMP:
|
||||
return ipset_print_icmp(buf + offset, len, data,
|
||||
IPSET_OPT_PORT, env);
|
||||
case IPPROTO_ICMPV6:
|
||||
return ipset_print_icmpv6(buf + offset, len, data,
|
||||
IPSET_OPT_PORT, env);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
size = ipset_print_port(buf + offset, len, data, IPSET_OPT_PORT, env);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
#define print_second(data) \
|
||||
ipset_data_flags_test(data, \
|
||||
IPSET_FLAG(IPSET_OPT_PORT)|IPSET_FLAG(IPSET_OPT_ETHER))
|
||||
|
||||
#define print_third(data) \
|
||||
ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_IP2))
|
||||
|
||||
/**
|
||||
* ipset_print_elem - print ADT elem according to settype
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print (multipart) element according to settype
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_elem(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt UNUSED,
|
||||
uint8_t env)
|
||||
{
|
||||
const struct ipset_type *type;
|
||||
int size, offset = 0;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
|
||||
type = ipset_data_get(data, IPSET_OPT_TYPE);
|
||||
if (!type)
|
||||
return -1;
|
||||
|
||||
size = type->elem[IPSET_DIM_ONE].print(buf, len, data,
|
||||
type->elem[IPSET_DIM_ONE].opt, env);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
IF_D(ipset_data_test(data, type->elem[IPSET_DIM_TWO].opt),
|
||||
"print second elem");
|
||||
if (type->dimension == IPSET_DIM_ONE
|
||||
|| (type->last_elem_optional
|
||||
&& !ipset_data_test(data, type->elem[IPSET_DIM_TWO].opt)))
|
||||
return offset;
|
||||
|
||||
size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
size = type->elem[IPSET_DIM_TWO].print(buf + offset, len, data,
|
||||
type->elem[IPSET_DIM_TWO].opt, env);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
if (type->dimension == IPSET_DIM_TWO
|
||||
|| (type->last_elem_optional
|
||||
&& !ipset_data_test(data, type->elem[IPSET_DIM_THREE].opt)))
|
||||
return offset;
|
||||
|
||||
size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
size = type->elem[IPSET_DIM_THREE].print(buf + offset, len, data,
|
||||
type->elem[IPSET_DIM_THREE].opt, env);
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_flag - print a flag
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Print a flag, i.e. option without value
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_flag(char *buf UNUSED, unsigned int len UNUSED,
|
||||
const struct ipset_data *data UNUSED,
|
||||
enum ipset_opt opt UNUSED, uint8_t env UNUSED)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_print_data - print data, generic fuction
|
||||
* @buf: printing buffer
|
||||
* @len: length of available buffer space
|
||||
* @data: data blob
|
||||
* @opt: the option kind
|
||||
* @env: environment flags
|
||||
*
|
||||
* Generic wrapper of the printing functions.
|
||||
*
|
||||
* Return lenght of printed string or error size.
|
||||
*/
|
||||
int
|
||||
ipset_print_data(char *buf, unsigned int len,
|
||||
const struct ipset_data *data, enum ipset_opt opt,
|
||||
uint8_t env)
|
||||
{
|
||||
int size = 0, offset = 0;
|
||||
|
||||
assert(buf);
|
||||
assert(len > 0);
|
||||
assert(data);
|
||||
|
||||
switch (opt) {
|
||||
case IPSET_OPT_FAMILY:
|
||||
size = ipset_print_family(buf, len, data, opt, env);
|
||||
break;
|
||||
case IPSET_OPT_TYPE:
|
||||
size = ipset_print_type(buf, len, data, opt, env);
|
||||
break;
|
||||
case IPSET_SETNAME:
|
||||
size = snprintf(buf, len, "%s", ipset_data_setname(data));
|
||||
break;
|
||||
case IPSET_OPT_ELEM:
|
||||
size = ipset_print_elem(buf, len, data, opt, env);
|
||||
break;
|
||||
case IPSET_OPT_IP:
|
||||
size = ipset_print_ip(buf, len, data, opt, env);
|
||||
break;
|
||||
case IPSET_OPT_PORT:
|
||||
size = ipset_print_port(buf, len, data, opt, env);
|
||||
break;
|
||||
case IPSET_OPT_GC:
|
||||
case IPSET_OPT_HASHSIZE:
|
||||
case IPSET_OPT_MAXELEM:
|
||||
case IPSET_OPT_NETMASK:
|
||||
case IPSET_OPT_PROBES:
|
||||
case IPSET_OPT_RESIZE:
|
||||
case IPSET_OPT_TIMEOUT:
|
||||
case IPSET_OPT_REFERENCES:
|
||||
case IPSET_OPT_ELEMENTS:
|
||||
case IPSET_OPT_SIZE:
|
||||
size = ipset_print_number(buf, len, data, opt, env);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
SNPRINTF_FAILURE(size, len, offset);
|
||||
|
||||
return offset;
|
||||
}
|
||||
1915
extensions/ipset-5/libipset/session.c
Normal file
1915
extensions/ipset-5/libipset/session.c
Normal file
File diff suppressed because it is too large
Load Diff
538
extensions/ipset-5/libipset/types.c
Normal file
538
extensions/ipset-5/libipset/types.c
Normal file
@@ -0,0 +1,538 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <assert.h> /* assert */
|
||||
#include <errno.h> /* errno */
|
||||
#include <net/ethernet.h> /* ETH_ALEN */
|
||||
#include <netinet/in.h> /* struct in6_addr */
|
||||
#include <sys/socket.h> /* AF_ */
|
||||
#include <stdlib.h> /* malloc, free */
|
||||
#include <stdio.h> /* FIXME: debug */
|
||||
#include <libmnl/libmnl.h> /* MNL_ALIGN */
|
||||
|
||||
#include <libipset/debug.h> /* D() */
|
||||
#include <libipset/data.h> /* ipset_data_* */
|
||||
#include <libipset/session.h> /* ipset_cmd */
|
||||
#include <libipset/utils.h> /* STREQ */
|
||||
#include <libipset/types.h> /* prototypes */
|
||||
|
||||
/* Userspace cache of sets which exists in the kernel */
|
||||
|
||||
struct ipset {
|
||||
char name[IPSET_MAXNAMELEN]; /* set name */
|
||||
const struct ipset_type *type; /* set type */
|
||||
uint8_t family; /* family */
|
||||
struct ipset *next;
|
||||
};
|
||||
|
||||
static struct ipset_type *typelist = NULL; /* registered set types */
|
||||
static struct ipset *setlist = NULL; /* cached sets */
|
||||
|
||||
/**
|
||||
* ipset_cache_add - add a set to the cache
|
||||
* @name: set name
|
||||
* @type: set type structure
|
||||
*
|
||||
* Add the named set to the internal cache with the specified
|
||||
* set type. The set name must be unique.
|
||||
*
|
||||
* Returns 0 on success or a negative error code.
|
||||
*/
|
||||
int
|
||||
ipset_cache_add(const char *name, const struct ipset_type *type,
|
||||
uint8_t family)
|
||||
{
|
||||
struct ipset *s, *n;
|
||||
|
||||
assert(name);
|
||||
assert(type);
|
||||
|
||||
n = malloc(sizeof(*n));
|
||||
if (n == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ipset_strlcpy(n->name, name, IPSET_MAXNAMELEN);
|
||||
n->type = type;
|
||||
n->family = family;
|
||||
n->next = NULL;
|
||||
|
||||
if (setlist == NULL) {
|
||||
setlist = n;
|
||||
return 0;
|
||||
}
|
||||
for (s = setlist; s->next != NULL; s = s->next) {
|
||||
if (STREQ(name, s->name)) {
|
||||
free(n);
|
||||
return -EEXIST;
|
||||
}
|
||||
}
|
||||
s->next = n;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_cache_del - delete set from the cache
|
||||
* @name: set name
|
||||
*
|
||||
* Delete the named set from the internal cache. If NULL is
|
||||
* specified as setname, the whole cache is emptied.
|
||||
*
|
||||
* Returns 0 on success or a negative error code.
|
||||
*/
|
||||
int
|
||||
ipset_cache_del(const char *name)
|
||||
{
|
||||
struct ipset *s, *match = NULL, *prev = NULL;
|
||||
|
||||
if (!name) {
|
||||
for (s = setlist; s != NULL; ) {
|
||||
prev = s;
|
||||
s = s->next;
|
||||
free(prev);
|
||||
}
|
||||
setlist = NULL;
|
||||
return 0;
|
||||
}
|
||||
for (s = setlist; s != NULL && match == NULL; s = s->next) {
|
||||
if (STREQ(s->name, name)) {
|
||||
match = s;
|
||||
if (prev == NULL)
|
||||
setlist = match->next;
|
||||
else
|
||||
prev->next = match->next;
|
||||
}
|
||||
prev = s;
|
||||
}
|
||||
if (match == NULL)
|
||||
return -EEXIST;
|
||||
|
||||
free(match);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_cache_rename - rename a set in the cache
|
||||
* @from: the set to rename
|
||||
* @to: the new name of the set
|
||||
*
|
||||
* Rename the given set in the cache.
|
||||
*
|
||||
* Returns 0 on success or a negative error code.
|
||||
*/
|
||||
int
|
||||
ipset_cache_rename(const char *from, const char *to)
|
||||
{
|
||||
struct ipset *s;
|
||||
|
||||
assert(from);
|
||||
assert(to);
|
||||
|
||||
for (s = setlist; s != NULL; s = s->next) {
|
||||
if (STREQ(s->name, from)) {
|
||||
ipset_strlcpy(s->name, to, IPSET_MAXNAMELEN);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_cache_swap - swap two sets in the cache
|
||||
* @from: the first set
|
||||
* @to: the second set
|
||||
*
|
||||
* Swap two existing sets in the cache.
|
||||
*
|
||||
* Returns 0 on success or a negative error code.
|
||||
*/
|
||||
int
|
||||
ipset_cache_swap(const char *from, const char *to)
|
||||
{
|
||||
struct ipset *s, *a = NULL, *b = NULL;
|
||||
|
||||
assert(from);
|
||||
assert(to);
|
||||
|
||||
for (s = setlist; s != NULL && (a == NULL || b == NULL); s = s->next) {
|
||||
if (a == NULL && STREQ(s->name, from))
|
||||
a = s;
|
||||
if (b == NULL && STREQ(s->name, to))
|
||||
b = s;
|
||||
}
|
||||
if (a != NULL && b != NULL) {
|
||||
ipset_strlcpy(a->name, to, IPSET_MAXNAMELEN);
|
||||
ipset_strlcpy(b->name, from, IPSET_MAXNAMELEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
#define MATCH_FAMILY(type, f) \
|
||||
(f == AF_UNSPEC || type->family == f || type->family == AF_INET46)
|
||||
|
||||
bool
|
||||
ipset_match_typename(const char *name, const struct ipset_type *type)
|
||||
{
|
||||
const char * const * alias = type->alias;
|
||||
|
||||
if (STREQ(name, type->name))
|
||||
return true;
|
||||
|
||||
while (alias[0]) {
|
||||
if (STREQ(name, alias[0]))
|
||||
return true;
|
||||
alias++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline const struct ipset_type *
|
||||
create_type_get(struct ipset_session *session)
|
||||
{
|
||||
struct ipset_type *t, *match = NULL;
|
||||
struct ipset_data *data;
|
||||
const char *typename;
|
||||
uint8_t family, tmin = 0, tmax = 0;
|
||||
const uint8_t *kmin, *kmax;
|
||||
int ret;
|
||||
|
||||
data = ipset_session_data(session);
|
||||
assert(data);
|
||||
typename = ipset_data_get(data, IPSET_OPT_TYPENAME);
|
||||
assert(typename);
|
||||
family = ipset_data_family(data);
|
||||
|
||||
/* Check registered types in userspace */
|
||||
for (t = typelist; t != NULL; t = t->next) {
|
||||
/* Skip revisions which are unsupported by the kernel */
|
||||
if (t->kernel_check == IPSET_KERNEL_MISMATCH)
|
||||
continue;
|
||||
if (ipset_match_typename(typename, t)
|
||||
&& MATCH_FAMILY(t, family)) {
|
||||
if (match == NULL) {
|
||||
match = t;
|
||||
tmax = t->revision;
|
||||
} else if (t->family == match->family)
|
||||
tmin = t->revision;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
return ipset_errptr(session,
|
||||
"Syntax error: unknown settype %s",
|
||||
typename);
|
||||
|
||||
/* Family is unspecified yet: set from matching set type */
|
||||
if (family == AF_UNSPEC && match->family != AF_UNSPEC) {
|
||||
family = match->family == AF_INET46 ? AF_INET : match->family;
|
||||
ipset_data_set(data, IPSET_OPT_FAMILY, &family);
|
||||
}
|
||||
|
||||
if (match->kernel_check == IPSET_KERNEL_OK)
|
||||
goto found;
|
||||
|
||||
/* Check kernel */
|
||||
ret = ipset_cmd(session, IPSET_CMD_TYPE, 0);
|
||||
if (ret != 0)
|
||||
return NULL;
|
||||
|
||||
kmax = ipset_data_get(data, IPSET_OPT_REVISION);
|
||||
if (ipset_data_test(data, IPSET_OPT_REVISION_MIN))
|
||||
kmin = ipset_data_get(data, IPSET_OPT_REVISION_MIN);
|
||||
else
|
||||
kmin = kmax;
|
||||
if (MAX(tmin, *kmin) > MIN(tmax, *kmax)) {
|
||||
if (*kmin > tmax)
|
||||
return ipset_errptr(session,
|
||||
"Kernel supports %s type with family %s "
|
||||
"in minimal revision %u while ipset library "
|
||||
"in maximal revision %u. "
|
||||
"You need to upgrade your ipset library.",
|
||||
typename,
|
||||
family == AF_INET ? "INET" :
|
||||
family == AF_INET6 ? "INET6" : "UNSPEC",
|
||||
*kmin, tmax);
|
||||
else
|
||||
return ipset_errptr(session,
|
||||
"Kernel supports %s type with family %s "
|
||||
"in maximal revision %u while ipset library "
|
||||
"in minimal revision %u. "
|
||||
"You need to upgrade your kernel.",
|
||||
typename,
|
||||
family == AF_INET ? "INET" :
|
||||
family == AF_INET6 ? "INET6" : "UNSPEC",
|
||||
*kmax, tmin);
|
||||
}
|
||||
|
||||
match->kernel_check = IPSET_KERNEL_OK;
|
||||
found:
|
||||
ipset_data_set(data, IPSET_OPT_TYPE, match);
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
#define set_family_and_type(data, match, family) do { \
|
||||
if (family == AF_UNSPEC && match->family != AF_UNSPEC) \
|
||||
family = match->family == AF_INET46 ? AF_INET : match->family;\
|
||||
ipset_data_set(data, IPSET_OPT_FAMILY, &family); \
|
||||
ipset_data_set(data, IPSET_OPT_TYPE, match); \
|
||||
} while (0)
|
||||
|
||||
|
||||
static inline const struct ipset_type *
|
||||
adt_type_get(struct ipset_session *session)
|
||||
{
|
||||
struct ipset_data *data;
|
||||
struct ipset *s;
|
||||
struct ipset_type *t;
|
||||
const struct ipset_type *match;
|
||||
const char *setname, *typename;
|
||||
const uint8_t *revision;
|
||||
uint8_t family = AF_UNSPEC;
|
||||
int ret;
|
||||
|
||||
data = ipset_session_data(session);
|
||||
assert(data);
|
||||
setname = ipset_data_setname(data);
|
||||
assert(setname);
|
||||
|
||||
/* Check existing sets in cache */
|
||||
for (s = setlist; s != NULL; s = s->next) {
|
||||
if (STREQ(setname, s->name)) {
|
||||
ipset_data_set(data, IPSET_OPT_FAMILY, &s->family);
|
||||
ipset_data_set(data, IPSET_OPT_TYPE, s->type);
|
||||
return s->type;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check kernel */
|
||||
ret = ipset_cmd(session, IPSET_CMD_HEADER, 0);
|
||||
if (ret != 0)
|
||||
return NULL;
|
||||
|
||||
typename = ipset_data_get(data, IPSET_OPT_TYPENAME);
|
||||
revision = ipset_data_get(data, IPSET_OPT_REVISION);
|
||||
family = ipset_data_family(data);
|
||||
|
||||
/* Check registered types */
|
||||
for (t = typelist, match = NULL;
|
||||
t != NULL && match == NULL; t = t->next) {
|
||||
if (t->kernel_check == IPSET_KERNEL_MISMATCH)
|
||||
continue;
|
||||
if (STREQ(typename, t->name)
|
||||
&& MATCH_FAMILY(t, family)
|
||||
&& *revision == t->revision) {
|
||||
t->kernel_check = IPSET_KERNEL_OK;
|
||||
match = t;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
return ipset_errptr(session,
|
||||
"Kernel-library incompatibility: "
|
||||
"set %s in kernel has got settype %s "
|
||||
"with family %s and revision %u while "
|
||||
"ipset library does not support the "
|
||||
"settype with that family and revision.",
|
||||
setname, typename,
|
||||
family == AF_INET ? "inet" :
|
||||
family == AF_INET6 ? "inet6" : "unspec",
|
||||
*revision);
|
||||
|
||||
set_family_and_type(data, match, family);
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_type_get - get a set type from the kernel
|
||||
* @session: session structure
|
||||
* @cmd: the command which needs the set type
|
||||
*
|
||||
* Build up and send a private message to the kernel in order to
|
||||
* get the set type. When creating the set, we send the typename
|
||||
* and family and get the supported revisions of the given set type.
|
||||
* When adding/deleting/testing an entry, we send the setname and
|
||||
* receive the typename, family and revision.
|
||||
*
|
||||
* Returns the set type for success and NULL for failure.
|
||||
*/
|
||||
const struct ipset_type *
|
||||
ipset_type_get(struct ipset_session *session, enum ipset_cmd cmd)
|
||||
{
|
||||
assert(session);
|
||||
|
||||
switch (cmd) {
|
||||
case IPSET_CMD_CREATE:
|
||||
return create_type_get(session);
|
||||
case IPSET_CMD_ADD:
|
||||
case IPSET_CMD_DEL:
|
||||
case IPSET_CMD_TEST:
|
||||
return adt_type_get(session);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(cmd == IPSET_CMD_NONE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_type_check - check the set type received from kernel
|
||||
* @session: session structure
|
||||
*
|
||||
* Check the set type received from the kernel (typename, revision,
|
||||
* family) against the userspace types looking for a matching type.
|
||||
*
|
||||
* Returns the set type for success and NULL for failure.
|
||||
*/
|
||||
const struct ipset_type *
|
||||
ipset_type_check(struct ipset_session *session)
|
||||
{
|
||||
const struct ipset_type *t, *match = NULL;
|
||||
struct ipset_data *data;
|
||||
const char *typename;
|
||||
uint8_t family = AF_UNSPEC, revision;
|
||||
|
||||
assert(session);
|
||||
data = ipset_session_data(session);
|
||||
assert(data);
|
||||
|
||||
typename = ipset_data_get(data, IPSET_OPT_TYPENAME);
|
||||
family = ipset_data_family(data);
|
||||
revision = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_REVISION);
|
||||
|
||||
/* Check registered types */
|
||||
for (t = typelist; t != NULL && match == NULL; t = t->next) {
|
||||
if (t->kernel_check == IPSET_KERNEL_MISMATCH)
|
||||
continue;
|
||||
if (ipset_match_typename(typename, t)
|
||||
&& MATCH_FAMILY(t, family)
|
||||
&& t->revision == revision)
|
||||
match = t;
|
||||
}
|
||||
if (!match)
|
||||
return ipset_errptr(session,
|
||||
"Kernel and userspace incompatible: "
|
||||
"settype %s with revision %u not supported ",
|
||||
"by userspace.", typename, revision);
|
||||
|
||||
set_family_and_type(data, match, family);
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_type_add - add (register) a userspace set type
|
||||
* @type: pointer to the set type structure
|
||||
*
|
||||
* Add the given set type to the type list. The types
|
||||
* are added sorted, in descending revision number.
|
||||
*
|
||||
* Returns 0 on success or a negative error code.
|
||||
*/
|
||||
int
|
||||
ipset_type_add(struct ipset_type *type)
|
||||
{
|
||||
struct ipset_type *t, *prev;
|
||||
|
||||
assert(type);
|
||||
|
||||
/* Add to the list: higher revision numbers first */
|
||||
for (t = typelist, prev = NULL; t != NULL; t = t->next) {
|
||||
if (STREQ(t->name, type->name)) {
|
||||
if (t->revision == type->revision) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
} else if (t->revision < type->revision) {
|
||||
type->next = t;
|
||||
if (prev)
|
||||
prev->next = type;
|
||||
else
|
||||
typelist = type;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (t->next != NULL && STREQ(t->next->name, type->name)) {
|
||||
if (t->next->revision == type->revision) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
} else if (t->next->revision < type->revision) {
|
||||
type->next = t->next;
|
||||
t->next = type;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
prev = t;
|
||||
}
|
||||
type->next = typelist;
|
||||
typelist = type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_typename_resolve - resolve typename alias
|
||||
* @str: typename or alias
|
||||
*
|
||||
* Check the typenames (and aliases) and return the
|
||||
* preferred name of the set type.
|
||||
*
|
||||
* Returns the name of the matching set type or NULL.
|
||||
*/
|
||||
const char *
|
||||
ipset_typename_resolve(const char *str)
|
||||
{
|
||||
const struct ipset_type *t;
|
||||
|
||||
for (t = typelist; t != NULL; t = t->next)
|
||||
if (ipset_match_typename(str, t))
|
||||
return t->name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_types - return the list of the set types
|
||||
*
|
||||
* The types can be unchecked with respect of the running kernel.
|
||||
* Only useful for type specific help.
|
||||
*
|
||||
* Returns the list of the set types.
|
||||
*/
|
||||
const struct ipset_type *
|
||||
ipset_types(void)
|
||||
{
|
||||
return typelist;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_cache_init - initialize set cache
|
||||
*
|
||||
* Initialize the set cache in userspace.
|
||||
*
|
||||
* Returns 0 on success or a negative error code.
|
||||
*/
|
||||
int
|
||||
ipset_cache_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_cache_fini - release the set cache
|
||||
*
|
||||
* Release the set cache.
|
||||
*/
|
||||
void
|
||||
ipset_cache_fini(void)
|
||||
{
|
||||
struct ipset *set;
|
||||
|
||||
while (setlist) {
|
||||
set = setlist;
|
||||
setlist = setlist->next;
|
||||
free(set);
|
||||
}
|
||||
}
|
||||
89
extensions/ipset-5/slist.h
Normal file
89
extensions/ipset-5/slist.h
Normal file
@@ -0,0 +1,89 @@
|
||||
#ifndef _IP_SET_SLIST_H
|
||||
#define _IP_SET_SLIST_H
|
||||
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/prefetch.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
/*
|
||||
* Single linked lists with a single pointer.
|
||||
* Mostly useful for hash tables where the two pointer list head
|
||||
* and list node is too wasteful.
|
||||
*/
|
||||
|
||||
struct slist {
|
||||
struct slist *next;
|
||||
};
|
||||
|
||||
#define SLIST(name) struct slist name = { .next = NULL }
|
||||
#define INIT_SLIST(ptr) ((ptr)->next = NULL)
|
||||
|
||||
#define slist_entry(ptr, type, member) container_of(ptr, type, member)
|
||||
|
||||
#define slist_for_each(pos, head) \
|
||||
for (pos = (head)->next; pos && ({ prefetch(pos->next); 1; }); \
|
||||
pos = pos->next)
|
||||
|
||||
#define slist_for_each_prev(prev, pos, head) \
|
||||
for (prev = head, pos = (head)->next; \
|
||||
pos && ({ prefetch(pos->next); 1; }); \
|
||||
prev = pos, pos = pos->next)
|
||||
|
||||
#define slist_for_each_safe(pos, n, head) \
|
||||
for (pos = (head)->next; pos && ({ n = pos->next; 1; }); \
|
||||
pos = n)
|
||||
|
||||
/**
|
||||
* slist_for_each_entry - iterate over list of given type
|
||||
* @tpos: the type * to use as a loop cursor.
|
||||
* @pos: the &struct slist to use as a loop cursor.
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the slist within the struct.
|
||||
*/
|
||||
#define slist_for_each_entry(tpos, pos, head, member) \
|
||||
for (pos = (head)->next; \
|
||||
pos && ({ prefetch(pos->next); 1; }) && \
|
||||
({ tpos = slist_entry(pos, typeof(*tpos), member); 1; });\
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* slist_for_each_entry_continue - iterate over a hlist continuing
|
||||
* after current point
|
||||
* @tpos: the type * to use as a loop cursor.
|
||||
* @pos: the &struct slist to use as a loop cursor.
|
||||
* @member: the name of the slist within the struct.
|
||||
*/
|
||||
#define slist_for_each_entry_continue(tpos, pos, member) \
|
||||
for (pos = (pos)->next; \
|
||||
pos && ({ prefetch(pos->next); 1; }) && \
|
||||
({ tpos = slist_entry(pos, typeof(*tpos), member); 1; });\
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* slist_for_each_entry_from - iterate over a hlist continuing
|
||||
* from current point
|
||||
* @tpos: the type * to use as a loop cursor.
|
||||
* @pos: the &struct slist to use as a loop cursor.
|
||||
* @member: the name of the slist within the struct.
|
||||
*/
|
||||
#define slist_for_each_entry_from(tpos, pos, member) \
|
||||
for (; pos && ({ prefetch(pos->next); 1; }) && \
|
||||
({ tpos = slist_entry(pos, typeof(*tpos), member); 1; });\
|
||||
pos = pos->next)
|
||||
|
||||
/**
|
||||
* slist_for_each_entry_safe - iterate over list of given type safe against
|
||||
* removal of list entry
|
||||
* @tpos: the type * to use as a loop cursor.
|
||||
* @pos: the &struct slist to use as a loop cursor.
|
||||
* @n: another &struct slist to use as temporary storage
|
||||
* @head: the head for your list.
|
||||
* @member: the name of the slist within the struct.
|
||||
*/
|
||||
#define slist_for_each_entry_safe(tpos, pos, n, head, member) \
|
||||
for (pos = (head)->next; \
|
||||
pos && ({ n = pos->next; 1; }) && \
|
||||
({ tpos = slist_entry(pos, typeof(*tpos), member); 1; });\
|
||||
pos = n)
|
||||
|
||||
#endif /* _IP_SET_SLIST_H */
|
||||
194
extensions/ipset-5/src/errcode.c
Normal file
194
extensions/ipset-5/src/errcode.c
Normal file
@@ -0,0 +1,194 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <assert.h> /* assert */
|
||||
#include <errno.h> /* errno */
|
||||
#include <string.h> /* strerror */
|
||||
|
||||
#include <libipset/debug.h> /* D() */
|
||||
#include <libipset/data.h> /* ipset_data_get */
|
||||
#include <libipset/session.h> /* ipset_err */
|
||||
#include <libipset/types.h> /* struct ipset_type */
|
||||
#include <libipset/utils.h> /* STRNEQ */
|
||||
#include <libipset/errcode.h> /* prototypes */
|
||||
#include <libipset/linux_ip_set_bitmap.h> /* bitmap specific errcodes */
|
||||
#include <libipset/linux_ip_set_hash.h> /* hash specific errcodes */
|
||||
#include <libipset/linux_ip_set_list.h> /* list specific errcodes */
|
||||
|
||||
/* Core kernel error codes */
|
||||
static const struct ipset_errcode_table core_errcode_table[] = {
|
||||
/* Generic error codes */
|
||||
{ EEXIST, 0,
|
||||
"The set with the given name does not exist" },
|
||||
{ IPSET_ERR_PROTOCOL, 0,
|
||||
"Kernel error received: ipset protocol error" },
|
||||
|
||||
/* CREATE specific error codes */
|
||||
{ EEXIST, IPSET_CMD_CREATE,
|
||||
"Set cannot be created: set with the same name already exists" },
|
||||
{ IPSET_ERR_FIND_TYPE, 0,
|
||||
"Kernel error received: set type does not supported" },
|
||||
{ IPSET_ERR_MAX_SETS, 0,
|
||||
"Kernel error received: maximal number of sets reached, "
|
||||
"cannot create more." },
|
||||
{ IPSET_ERR_INVALID_NETMASK, 0,
|
||||
"The value of the netmask parameter is invalid" },
|
||||
{ IPSET_ERR_INVALID_FAMILY, 0,
|
||||
"The protocol family not supported by the set type" },
|
||||
|
||||
/* DESTROY specific error codes */
|
||||
{ IPSET_ERR_BUSY, IPSET_CMD_DESTROY,
|
||||
"Set cannot be destroyed: it is in use by a kernel component" },
|
||||
|
||||
/* FLUSH specific error codes */
|
||||
|
||||
/* RENAME specific error codes */
|
||||
{ IPSET_ERR_EXIST_SETNAME2, IPSET_CMD_RENAME,
|
||||
"Set cannot be renamed: a set with the new name already exists" },
|
||||
{ IPSET_ERR_REFERENCED, IPSET_CMD_RENAME,
|
||||
"Set cannot be renamed: it is in use by another system" },
|
||||
|
||||
/* SWAP specific error codes */
|
||||
{ IPSET_ERR_EXIST_SETNAME2, IPSET_CMD_SWAP,
|
||||
"Sets cannot be swapped: the second set does not exist" },
|
||||
{ IPSET_ERR_TYPE_MISMATCH, IPSET_CMD_SWAP,
|
||||
"The sets cannot be swapped: they type does not match" },
|
||||
|
||||
/* LIST/SAVE specific error codes */
|
||||
|
||||
/* Generic (CADT) error codes */
|
||||
{ IPSET_ERR_INVALID_CIDR, 0,
|
||||
"The value of the CIDR parameter of the IP address is invalid" },
|
||||
{ IPSET_ERR_TIMEOUT, 0,
|
||||
"Timeout cannot be used: set was created without timeout support" },
|
||||
{ IPSET_ERR_IPADDR_IPV4, 0,
|
||||
"An IPv4 address is expected, but not received" },
|
||||
{ IPSET_ERR_IPADDR_IPV6, 0,
|
||||
"An IPv6 address is expected, but not received" },
|
||||
|
||||
/* ADD specific error codes */
|
||||
{ IPSET_ERR_EXIST, IPSET_CMD_ADD,
|
||||
"Element cannot be added to the set: it's already added" },
|
||||
|
||||
/* DEL specific error codes */
|
||||
{ IPSET_ERR_EXIST, IPSET_CMD_DEL,
|
||||
"Element cannot be deleted from the set: it's not added" },
|
||||
|
||||
/* TEST specific error codes */
|
||||
|
||||
/* HEADER specific error codes */
|
||||
|
||||
/* TYPE specific error codes */
|
||||
{ EEXIST, IPSET_CMD_TYPE,
|
||||
"Kernel error received: set type does not supported" },
|
||||
|
||||
/* PROTOCOL specific error codes */
|
||||
|
||||
{ },
|
||||
};
|
||||
|
||||
/* Bitmap type-specific error codes */
|
||||
static const struct ipset_errcode_table bitmap_errcode_table[] = {
|
||||
/* Generic (CADT) error codes */
|
||||
{ IPSET_ERR_BITMAP_RANGE, 0,
|
||||
"Element is out of the range of the set" },
|
||||
{ IPSET_ERR_BITMAP_RANGE_SIZE, IPSET_CMD_CREATE,
|
||||
"The range you specified exceeds the size limit of the set type" },
|
||||
{ },
|
||||
};
|
||||
|
||||
/* Hash type-specific error codes */
|
||||
static const struct ipset_errcode_table hash_errcode_table[] = {
|
||||
/* Generic (CADT) error codes */
|
||||
{ IPSET_ERR_HASH_FULL, 0,
|
||||
"Hash is full, cannot add more elements" },
|
||||
{ IPSET_ERR_HASH_ELEM, 0,
|
||||
"Null-valued element, cannot be stored in a hash type of set" },
|
||||
{ IPSET_ERR_INVALID_PROTO, 0,
|
||||
"Invalid protocol specified" },
|
||||
{ IPSET_ERR_MISSING_PROTO, 0,
|
||||
"Protocol missing, but must be specified" },
|
||||
{ },
|
||||
};
|
||||
|
||||
/* List type-specific error codes */
|
||||
static const struct ipset_errcode_table list_errcode_table[] = {
|
||||
/* Generic (CADT) error codes */
|
||||
{ IPSET_ERR_NAME, 0,
|
||||
"Set to be added/deleted/tested as element does not exist." },
|
||||
{ IPSET_ERR_LOOP, 0,
|
||||
"Sets with list:set type cannot be added to the set." },
|
||||
{ IPSET_ERR_BEFORE, 0,
|
||||
"No reference set specified." },
|
||||
{ IPSET_ERR_NAMEREF, 0,
|
||||
"The set to which you referred with 'before' or 'after' "
|
||||
"does not exist." },
|
||||
{ IPSET_ERR_LIST_FULL, 0,
|
||||
"The set is full, more elements cannot be added." },
|
||||
{ IPSET_ERR_REF_EXIST, 0,
|
||||
"The set to which you referred with 'before' or 'after' "
|
||||
"is not added to the set." },
|
||||
{ },
|
||||
};
|
||||
|
||||
#define MATCH_TYPENAME(a, b) STRNEQ(a, b, strlen(b))
|
||||
|
||||
/**
|
||||
* ipset_errcode - interpret a kernel error code
|
||||
* @session: session structure
|
||||
* @errcode: errcode
|
||||
*
|
||||
* Find the error code and print the appropriate
|
||||
* error message into the error buffer.
|
||||
*
|
||||
* Returns -1.
|
||||
*/
|
||||
int
|
||||
ipset_errcode(struct ipset_session *session, enum ipset_cmd cmd, int errcode)
|
||||
{
|
||||
const struct ipset_errcode_table *table = core_errcode_table;
|
||||
int i, generic;
|
||||
|
||||
if (errcode >= IPSET_ERR_TYPE_SPECIFIC) {
|
||||
const struct ipset_type *type;
|
||||
|
||||
type = ipset_saved_type(session);
|
||||
if (type) {
|
||||
if (MATCH_TYPENAME(type->name, "bitmap:"))
|
||||
table = bitmap_errcode_table;
|
||||
else if (MATCH_TYPENAME(type->name, "hash:"))
|
||||
table = hash_errcode_table;
|
||||
else if (MATCH_TYPENAME(type->name, "list:"))
|
||||
table = list_errcode_table;
|
||||
}
|
||||
}
|
||||
|
||||
retry:
|
||||
for (i = 0, generic = -1; table[i].errcode; i++) {
|
||||
if (table[i].errcode == errcode
|
||||
&& (table[i].cmd == cmd || table[i].cmd == 0)) {
|
||||
if (table[i].cmd == 0) {
|
||||
generic = i;
|
||||
continue;
|
||||
}
|
||||
return ipset_err(session, table[i].message);
|
||||
}
|
||||
}
|
||||
if (generic != -1)
|
||||
return ipset_err(session, table[generic].message);
|
||||
/* Fall back to the core table */
|
||||
if (table != core_errcode_table) {
|
||||
table = core_errcode_table;
|
||||
goto retry;
|
||||
}
|
||||
if (errcode < IPSET_ERR_PRIVATE)
|
||||
return ipset_err(session, "Kernel error received: %s",
|
||||
strerror(errcode));
|
||||
else
|
||||
return ipset_err(session,
|
||||
"Undecoded error %u received from kernel",
|
||||
errcode);
|
||||
}
|
||||
747
extensions/ipset-5/src/ipset.c
Normal file
747
extensions/ipset-5/src/ipset.c
Normal file
@@ -0,0 +1,747 @@
|
||||
/* Copyright 2000-2002 Joakim Axelsson (gozem@linux.nu)
|
||||
* Patrick Schaaf (bof@bof.de)
|
||||
* Copyright 2003-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <ctype.h> /* isspace */
|
||||
#include <stdarg.h> /* va_* */
|
||||
#include <stdbool.h> /* bool */
|
||||
#include <stdio.h> /* fprintf, fgets */
|
||||
#include <stdlib.h> /* exit */
|
||||
#include <string.h> /* str* */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <libipset/debug.h> /* D() */
|
||||
#include <libipset/data.h> /* enum ipset_data */
|
||||
#include <libipset/parse.h> /* ipset_parse_* */
|
||||
#include <libipset/session.h> /* ipset_session_* */
|
||||
#include <libipset/types.h> /* struct ipset_type */
|
||||
#include <libipset/ui.h> /* core options, commands */
|
||||
#include <libipset/utils.h> /* STREQ */
|
||||
|
||||
static char program_name[] = PACKAGE;
|
||||
static char program_version[] = PACKAGE_VERSION;
|
||||
|
||||
static struct ipset_session *session = NULL;
|
||||
static uint32_t restore_line = 0;
|
||||
static bool interactive = false;
|
||||
static char cmdline[1024];
|
||||
static char *newargv[255];
|
||||
static int newargc = 0;
|
||||
|
||||
/* The known set types: (typename, revision, family) is unique */
|
||||
extern struct ipset_type ipset_bitmap_ip0;
|
||||
extern struct ipset_type ipset_bitmap_ipmac0;
|
||||
extern struct ipset_type ipset_bitmap_port0;
|
||||
extern struct ipset_type ipset_hash_ip0;
|
||||
extern struct ipset_type ipset_hash_net0;
|
||||
extern struct ipset_type ipset_hash_netport0;
|
||||
extern struct ipset_type ipset_hash_ipport0;
|
||||
extern struct ipset_type ipset_hash_ipportip0;
|
||||
extern struct ipset_type ipset_hash_ipportnet0;
|
||||
extern struct ipset_type ipset_list_set0;
|
||||
|
||||
enum exittype {
|
||||
NO_PROBLEM = 0,
|
||||
OTHER_PROBLEM,
|
||||
PARAMETER_PROBLEM,
|
||||
VERSION_PROBLEM,
|
||||
SESSION_PROBLEM,
|
||||
};
|
||||
|
||||
static int __attribute__((format(printf,2,3)))
|
||||
exit_error(int status, const char *msg, ...)
|
||||
{
|
||||
bool quiet = !interactive
|
||||
&& session
|
||||
&& ipset_envopt_test(session, IPSET_ENV_QUIET);
|
||||
|
||||
if (status && msg && !quiet) {
|
||||
va_list args;
|
||||
|
||||
fprintf(stderr, "%s v%s: ", program_name, program_version);
|
||||
va_start(args, msg);
|
||||
vfprintf(stderr, msg, args);
|
||||
va_end(args);
|
||||
if (status != SESSION_PROBLEM)
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
if (status == PARAMETER_PROBLEM)
|
||||
fprintf(stderr,
|
||||
"Try `%s help' for more information.\n",
|
||||
program_name);
|
||||
}
|
||||
/* Ignore errors in interactive mode */
|
||||
if (status && interactive) {
|
||||
if (session)
|
||||
ipset_session_report_reset(session);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (session)
|
||||
ipset_session_fini(session);
|
||||
|
||||
D("status: %u", status);
|
||||
exit(status > VERSION_PROBLEM ? OTHER_PROBLEM : status);
|
||||
/* Unreached */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
handle_error(void)
|
||||
{
|
||||
if (ipset_session_warning(session)
|
||||
&& !ipset_envopt_test(session, IPSET_ENV_QUIET))
|
||||
fprintf(stderr, "Warning: %s\n",
|
||||
ipset_session_warning(session));
|
||||
if (ipset_session_error(session))
|
||||
return exit_error(SESSION_PROBLEM, "%s",
|
||||
ipset_session_error(session));
|
||||
|
||||
if (!interactive) {
|
||||
ipset_session_fini(session);
|
||||
exit(OTHER_PROBLEM);
|
||||
}
|
||||
|
||||
ipset_session_report_reset(session);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
help(void)
|
||||
{
|
||||
const struct ipset_commands *c;
|
||||
const struct ipset_envopts *opt = ipset_envopts;
|
||||
|
||||
printf("%s v%s\n\n"
|
||||
"Usage: %s [options] COMMAND\n\nCommands:\n",
|
||||
program_name, program_version, program_name);
|
||||
|
||||
for (c = ipset_commands; c->cmd; c++) {
|
||||
printf("%s %s\n", c->name[0], c->help);
|
||||
}
|
||||
printf("\nOptions:\n");
|
||||
|
||||
while (opt->flag) {
|
||||
if (opt->help)
|
||||
printf("%s %s\n", opt->name[0], opt->help);
|
||||
opt++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Build faked argv from parsed line */
|
||||
static void
|
||||
build_argv(char *buffer)
|
||||
{
|
||||
char *ptr;
|
||||
int i;
|
||||
|
||||
/* Reset */
|
||||
for (i = 1; i < newargc; i++)
|
||||
newargv[i] = NULL;
|
||||
newargc = 1;
|
||||
|
||||
ptr = strtok(buffer, " \t\n");
|
||||
newargv[newargc++] = ptr;
|
||||
while ((ptr = strtok(NULL, " \t\n")) != NULL) {
|
||||
if ((newargc + 1) < (int)(sizeof(newargv)/sizeof(char *)))
|
||||
newargv[newargc++] = ptr;
|
||||
else {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Line is too long to parse.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Main parser function, workhorse */
|
||||
int parse_commandline(int argc, char *argv[]);
|
||||
|
||||
/*
|
||||
* Performs a restore from stdin
|
||||
*/
|
||||
static int
|
||||
restore(char *argv0)
|
||||
{
|
||||
int ret = 0;
|
||||
char *c;
|
||||
|
||||
/* Initialize newargv/newargc */
|
||||
newargc = 0;
|
||||
newargv[newargc++] = argv0;
|
||||
|
||||
while (fgets(cmdline, sizeof(cmdline), stdin)) {
|
||||
restore_line++;
|
||||
c = cmdline;
|
||||
while (isspace(c[0]))
|
||||
c++;
|
||||
if (c[0] == '\0' || c[0] == '#')
|
||||
continue;
|
||||
else if (strcmp(c, "COMMIT\n") == 0) {
|
||||
ret = ipset_commit(session);
|
||||
if (ret < 0)
|
||||
handle_error();
|
||||
continue;
|
||||
}
|
||||
/* Build faked argv, argc */
|
||||
build_argv(c);
|
||||
|
||||
/* Execute line */
|
||||
ret = parse_commandline(newargc, newargv);
|
||||
if (ret < 0)
|
||||
handle_error();
|
||||
}
|
||||
/* implicit "COMMIT" at EOF */
|
||||
ret = ipset_commit(session);
|
||||
if (ret < 0)
|
||||
handle_error();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
call_parser(int *argc, char *argv[], const struct ipset_arg *args)
|
||||
{
|
||||
int i = 1, ret = 0;
|
||||
const struct ipset_arg *arg;
|
||||
const char *optstr;
|
||||
|
||||
/* Currently CREATE and ADT may have got additional arguments */
|
||||
if (!args)
|
||||
goto done;
|
||||
for (arg = args; arg->opt; arg++) {
|
||||
for (i = 1; i < *argc; ) {
|
||||
D("argc: %u, i: %u: %s vs %s",
|
||||
*argc, i, argv[i], arg->name[0]);
|
||||
if (!(ipset_match_option(argv[i], arg->name))) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
optstr = argv[i];
|
||||
/* Shift off matched option */
|
||||
D("match %s", arg->name[0]);
|
||||
ipset_shift_argv(argc, argv, i);
|
||||
D("argc: %u, i: %u", *argc, i);
|
||||
switch (arg->has_arg) {
|
||||
case IPSET_MANDATORY_ARG:
|
||||
if (i + 1 > *argc)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Missing mandatory argument "
|
||||
"of option `%s'",
|
||||
arg->name[0]);
|
||||
/* Fall through */
|
||||
case IPSET_OPTIONAL_ARG:
|
||||
if (i + 1 <= *argc) {
|
||||
ret = ipset_call_parser(session,
|
||||
arg->parse,
|
||||
optstr, arg->opt,
|
||||
argv[i]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ipset_shift_argv(argc, argv, i);
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
default:
|
||||
ret = ipset_call_parser(session,
|
||||
arg->parse,
|
||||
optstr, arg->opt,
|
||||
optstr);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
if (i < *argc)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Unknown argument: `%s'",
|
||||
argv[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static enum ipset_adt
|
||||
cmd2cmd(int cmd)
|
||||
{
|
||||
switch(cmd) {
|
||||
case IPSET_CMD_ADD:
|
||||
return IPSET_ADD;
|
||||
case IPSET_CMD_DEL:
|
||||
return IPSET_DEL;
|
||||
case IPSET_CMD_TEST:
|
||||
return IPSET_TEST;
|
||||
case IPSET_CMD_CREATE:
|
||||
return IPSET_CREATE;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_mandatory(const struct ipset_type *type, enum ipset_cmd command)
|
||||
{
|
||||
enum ipset_adt cmd = cmd2cmd(command);
|
||||
uint64_t flags = ipset_data_flags(ipset_session_data(session));
|
||||
uint64_t mandatory = type->mandatory[cmd];
|
||||
const struct ipset_arg *arg = type->args[cmd];
|
||||
|
||||
/* Range can be expressed by ip/cidr */
|
||||
if (flags & IPSET_FLAG(IPSET_OPT_CIDR))
|
||||
flags |= IPSET_FLAG(IPSET_OPT_IP_TO);
|
||||
|
||||
mandatory &= ~flags;
|
||||
if (!mandatory)
|
||||
return;
|
||||
if (!arg) {
|
||||
exit_error(OTHER_PROBLEM,
|
||||
"There are missing mandatory flags "
|
||||
"but can't check them. "
|
||||
"It's a bug, please report the problem.");
|
||||
return;
|
||||
}
|
||||
|
||||
for (; arg->opt; arg++)
|
||||
if (mandatory & IPSET_FLAG(arg->opt)) {
|
||||
exit_error(PARAMETER_PROBLEM,
|
||||
"Mandatory option `%s' is missing",
|
||||
arg->name[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
cmd2name(enum ipset_cmd cmd)
|
||||
{
|
||||
const struct ipset_commands *c;
|
||||
|
||||
for (c = ipset_commands; c->cmd; c++)
|
||||
if (cmd == c->cmd)
|
||||
return c->name[0];
|
||||
return "unknown command";
|
||||
}
|
||||
|
||||
static const char *
|
||||
session_family(void)
|
||||
{
|
||||
switch (ipset_data_family(ipset_session_data(session))) {
|
||||
case AF_INET:
|
||||
return "inet";
|
||||
case AF_INET6:
|
||||
return "inet6";
|
||||
default:
|
||||
return "unspec";
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_allowed(const struct ipset_type *type, enum ipset_cmd command)
|
||||
{
|
||||
uint64_t flags = ipset_data_flags(ipset_session_data(session));
|
||||
enum ipset_adt cmd = cmd2cmd(command);
|
||||
uint64_t allowed = type->full[cmd];
|
||||
uint64_t cmdflags = command == IPSET_CMD_CREATE
|
||||
? IPSET_CREATE_FLAGS : IPSET_ADT_FLAGS;
|
||||
const struct ipset_arg *arg = type->args[cmd];
|
||||
enum ipset_opt i;
|
||||
|
||||
/* Range can be expressed by ip/cidr or from-to */
|
||||
if (allowed & IPSET_FLAG(IPSET_OPT_IP_TO))
|
||||
allowed |= IPSET_FLAG(IPSET_OPT_CIDR);
|
||||
|
||||
for (i = IPSET_OPT_IP; i < IPSET_OPT_FLAGS; i++) {
|
||||
if (!(cmdflags & IPSET_FLAG(i))
|
||||
|| (allowed & IPSET_FLAG(i))
|
||||
|| !(flags & IPSET_FLAG(i)))
|
||||
continue;
|
||||
/* Not allowed element-expressions */
|
||||
switch (i) {
|
||||
case IPSET_OPT_CIDR:
|
||||
exit_error(OTHER_PROBLEM,
|
||||
"IP/CIDR range is not allowed in command %s "
|
||||
"with set type %s and family %s",
|
||||
cmd2name(command), type->name, session_family());
|
||||
return;
|
||||
case IPSET_OPT_IP_TO:
|
||||
exit_error(OTHER_PROBLEM,
|
||||
"FROM-TO IP range is not allowed in command %s "
|
||||
"with set type %s and family %s",
|
||||
cmd2name(command), type->name, session_family());
|
||||
return;
|
||||
case IPSET_OPT_PORT_TO:
|
||||
exit_error(OTHER_PROBLEM,
|
||||
"FROM-TO port range is not allowed in command %s "
|
||||
"with set type %s and family %s",
|
||||
cmd2name(command), type->name, session_family());
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Other options */
|
||||
if (!arg) {
|
||||
exit_error(OTHER_PROBLEM,
|
||||
"There are not allowed options (%u) "
|
||||
"but option list is NULL. "
|
||||
"It's a bug, please report the problem.", i);
|
||||
return;
|
||||
}
|
||||
for (; arg->opt; arg++) {
|
||||
if (arg->opt != i)
|
||||
continue;
|
||||
exit_error(OTHER_PROBLEM,
|
||||
"%s parameter is not allowed in command %s "
|
||||
"with set type %s and family %s",
|
||||
arg->name[0],
|
||||
cmd2name(command), type->name, session_family());
|
||||
return;
|
||||
}
|
||||
exit_error(OTHER_PROBLEM,
|
||||
"There are not allowed options (%u) "
|
||||
"but can't resolve them. "
|
||||
"It's a bug, please report the problem.", i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct ipset_type *
|
||||
type_find(const char *name)
|
||||
{
|
||||
const struct ipset_type *t = ipset_types();
|
||||
|
||||
while (t) {
|
||||
if (ipset_match_typename(name, t))
|
||||
return t;
|
||||
t = t->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Workhorse */
|
||||
int
|
||||
parse_commandline(int argc, char *argv[])
|
||||
{
|
||||
int ret = 0;
|
||||
enum ipset_cmd cmd = IPSET_CMD_NONE;
|
||||
int i;
|
||||
char *arg0 = NULL, *arg1 = NULL, *c;
|
||||
const struct ipset_envopts *opt;
|
||||
const struct ipset_commands *command;
|
||||
const struct ipset_type *type;
|
||||
|
||||
/* Initialize session */
|
||||
if (session == NULL) {
|
||||
session = ipset_session_init(printf);
|
||||
if (session == NULL)
|
||||
return exit_error(OTHER_PROBLEM,
|
||||
"Cannot initialize ipset session, aborting.");
|
||||
}
|
||||
|
||||
/* Commandline parsing, somewhat similar to that of 'ip' */
|
||||
|
||||
/* First: parse core options */
|
||||
for (opt = ipset_envopts; opt->flag; opt++) {
|
||||
for (i = 1; i < argc; ) {
|
||||
if (!ipset_match_envopt(argv[i], opt->name)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
/* Shift off matched option */
|
||||
ipset_shift_argv(&argc, argv, i);
|
||||
switch (opt->has_arg) {
|
||||
case IPSET_MANDATORY_ARG:
|
||||
if (i + 1 > argc)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Missing mandatory argument "
|
||||
"to option %s",
|
||||
opt->name[0]);
|
||||
/* Fall through */
|
||||
case IPSET_OPTIONAL_ARG:
|
||||
if (i + 1 <= argc) {
|
||||
ret = opt->parse(session, opt->flag,
|
||||
argv[i]);
|
||||
if (ret < 0)
|
||||
return handle_error();
|
||||
ipset_shift_argv(&argc, argv, i);
|
||||
}
|
||||
break;
|
||||
case IPSET_NO_ARG:
|
||||
ret = opt->parse(session, opt->flag,
|
||||
opt->name[0]);
|
||||
if (ret < 0)
|
||||
return handle_error();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Second: parse command */
|
||||
for (command = ipset_commands;
|
||||
command->cmd && cmd == IPSET_CMD_NONE;
|
||||
command++) {
|
||||
for (i = 1; i < argc; ) {
|
||||
if (!ipset_match_cmd(argv[1], command->name)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if (restore_line != 0
|
||||
&& (command->cmd == IPSET_CMD_RESTORE
|
||||
|| command->cmd == IPSET_CMD_VERSION
|
||||
|| command->cmd == IPSET_CMD_HELP))
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Command `%s' is invalid "
|
||||
"in restore mode.",
|
||||
command->name[0]);
|
||||
if (interactive
|
||||
&& command->cmd == IPSET_CMD_RESTORE) {
|
||||
printf("Restore command ignored "
|
||||
"in interactive mode\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Shift off matched command arg */
|
||||
ipset_shift_argv(&argc, argv, i);
|
||||
cmd = command->cmd;
|
||||
switch (command->has_arg) {
|
||||
case IPSET_MANDATORY_ARG:
|
||||
case IPSET_MANDATORY_ARG2:
|
||||
if (i + 1 > argc)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Missing mandatory argument "
|
||||
"to command %s",
|
||||
command->name[0]);
|
||||
/* Fall through */
|
||||
case IPSET_OPTIONAL_ARG:
|
||||
arg0 = argv[i];
|
||||
if (i + 1 <= argc)
|
||||
/* Shift off first arg */
|
||||
ipset_shift_argv(&argc, argv, i);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (command->has_arg == IPSET_MANDATORY_ARG2) {
|
||||
if (i + 1 > argc)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Missing second mandatory "
|
||||
"argument to command %s",
|
||||
command->name[0]);
|
||||
arg1 = argv[i];
|
||||
/* Shift off second arg */
|
||||
ipset_shift_argv(&argc, argv, i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Third: catch interactive mode, handle help, version */
|
||||
switch (cmd) {
|
||||
case IPSET_CMD_NONE:
|
||||
if (interactive) {
|
||||
printf("No command specified\n");
|
||||
return 0;
|
||||
}
|
||||
if (argc > 1 && STREQ(argv[1], "-")) {
|
||||
interactive = true;
|
||||
printf("%s> ", program_name);
|
||||
/* Initialize newargv/newargc */
|
||||
newargv[newargc++] = program_name;
|
||||
while (fgets(cmdline, sizeof(cmdline), stdin)) {
|
||||
c = cmdline;
|
||||
while (isspace(c[0]))
|
||||
c++;
|
||||
if (c[0] == '\0' || c[0] == '#')
|
||||
continue;
|
||||
/* Build fake argv, argc */
|
||||
build_argv(c);
|
||||
/* Execute line: ignore errors */
|
||||
parse_commandline(newargc, newargv);
|
||||
printf("%s> ", program_name);
|
||||
}
|
||||
return exit_error(NO_PROBLEM, NULL);
|
||||
}
|
||||
if (argc > 1)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"No command specified: unknown argument %s",
|
||||
argv[1]);
|
||||
return exit_error(PARAMETER_PROBLEM, "No command specified.");
|
||||
case IPSET_CMD_VERSION:
|
||||
printf("%s v%s.\n", program_name, program_version);
|
||||
if (interactive)
|
||||
return 0;
|
||||
return exit_error(NO_PROBLEM, NULL);
|
||||
case IPSET_CMD_HELP:
|
||||
help();
|
||||
|
||||
if (interactive
|
||||
|| !ipset_envopt_test(session, IPSET_ENV_QUIET)) {
|
||||
if (arg0) {
|
||||
/* Type-specific help, without kernel checking */
|
||||
type = type_find(arg0);
|
||||
if (!type)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Unknown settype: `%s'", arg0);
|
||||
printf("\n%s type specific options:\n\n%s",
|
||||
type->name, type->usage);
|
||||
if (type->usagefn)
|
||||
type->usagefn();
|
||||
if (type->family == AF_UNSPEC)
|
||||
printf("\nType %s is family neutral.\n",
|
||||
type->name);
|
||||
else if (type->family == AF_INET46)
|
||||
printf("\nType %s supports INET "
|
||||
"and INET6.\n",
|
||||
type->name);
|
||||
else
|
||||
printf("\nType %s supports family "
|
||||
"%s only.\n",
|
||||
type->name,
|
||||
type->family == AF_INET
|
||||
? "INET" : "INET6");
|
||||
} else {
|
||||
printf("\nSupported set types:\n");
|
||||
type = ipset_types();
|
||||
while (type) {
|
||||
printf(" %s\n", type->name);
|
||||
type = type->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (interactive)
|
||||
return 0;
|
||||
return exit_error(NO_PROBLEM, NULL);
|
||||
case IPSET_CMD_QUIT:
|
||||
return exit_error(NO_PROBLEM, NULL);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Forth: parse command args and issue the command */
|
||||
switch (cmd) {
|
||||
case IPSET_CMD_CREATE:
|
||||
/* Args: setname typename [type specific options] */
|
||||
ret = ipset_parse_setname(session, IPSET_SETNAME, arg0);
|
||||
if (ret < 0)
|
||||
return handle_error();
|
||||
|
||||
ret = ipset_parse_typename(session, IPSET_OPT_TYPENAME, arg1);
|
||||
if (ret < 0)
|
||||
return handle_error();
|
||||
|
||||
type = ipset_type_get(session, cmd);
|
||||
if (type == NULL)
|
||||
return handle_error();
|
||||
|
||||
/* Parse create options */
|
||||
ret = call_parser(&argc, argv, type->args[IPSET_CREATE]);
|
||||
if (ret < 0)
|
||||
return handle_error();
|
||||
else if (ret)
|
||||
return ret;
|
||||
|
||||
/* Check mandatory, then allowed options */
|
||||
check_mandatory(type, cmd);
|
||||
check_allowed(type, cmd);
|
||||
|
||||
break;
|
||||
case IPSET_CMD_DESTROY:
|
||||
case IPSET_CMD_FLUSH:
|
||||
case IPSET_CMD_LIST:
|
||||
case IPSET_CMD_SAVE:
|
||||
/* Args: [setname] */
|
||||
if (arg0) {
|
||||
ret = ipset_parse_setname(session,
|
||||
IPSET_SETNAME, arg0);
|
||||
if (ret < 0)
|
||||
return handle_error();
|
||||
}
|
||||
break;
|
||||
|
||||
case IPSET_CMD_RENAME:
|
||||
case IPSET_CMD_SWAP:
|
||||
/* Args: from-setname to-setname */
|
||||
ret = ipset_parse_setname(session, IPSET_SETNAME, arg0);
|
||||
if (ret < 0)
|
||||
return handle_error();
|
||||
ret = ipset_parse_setname(session, IPSET_OPT_SETNAME2, arg1);
|
||||
if (ret < 0)
|
||||
return handle_error();
|
||||
break;
|
||||
|
||||
case IPSET_CMD_RESTORE:
|
||||
/* Restore mode */
|
||||
if (argc > 1)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Unknown argument %s", argv[1]);
|
||||
return restore(argv[0]);
|
||||
case IPSET_CMD_ADD:
|
||||
case IPSET_CMD_DEL:
|
||||
case IPSET_CMD_TEST:
|
||||
D("ADT: setname %s", arg0);
|
||||
/* Args: setname ip [options] */
|
||||
ret = ipset_parse_setname(session, IPSET_SETNAME, arg0);
|
||||
if (ret < 0)
|
||||
return handle_error();
|
||||
|
||||
type = ipset_type_get(session, cmd);
|
||||
if (type == NULL)
|
||||
return handle_error();
|
||||
|
||||
ret = ipset_parse_elem(session, type->last_elem_optional, arg1);
|
||||
if (ret < 0)
|
||||
return handle_error();
|
||||
|
||||
/* Parse additional ADT options */
|
||||
ret = call_parser(&argc, argv, type->args[cmd2cmd(cmd)]);
|
||||
if (ret < 0)
|
||||
return handle_error();
|
||||
else if (ret)
|
||||
return ret;
|
||||
|
||||
/* Check mandatory, then allowed options */
|
||||
check_mandatory(type, cmd);
|
||||
check_allowed(type, cmd);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (argc > 1)
|
||||
return exit_error(PARAMETER_PROBLEM,
|
||||
"Unknown argument %s", argv[1]);
|
||||
ret = ipset_cmd(session, cmd, restore_line);
|
||||
D("ret %d", ret);
|
||||
/* Special case for TEST and non-quiet mode */
|
||||
if (cmd == IPSET_CMD_TEST && ipset_session_warning(session)) {
|
||||
if (!ipset_envopt_test(session, IPSET_ENV_QUIET))
|
||||
fprintf(stderr, "%s", ipset_session_warning(session));
|
||||
ipset_session_report_reset(session);
|
||||
}
|
||||
if (ret < 0)
|
||||
handle_error();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
/* Register types */
|
||||
ipset_type_add(&ipset_bitmap_ip0);
|
||||
ipset_type_add(&ipset_bitmap_ipmac0);
|
||||
ipset_type_add(&ipset_bitmap_port0);
|
||||
ipset_type_add(&ipset_hash_ip0);
|
||||
ipset_type_add(&ipset_hash_net0);
|
||||
ipset_type_add(&ipset_hash_netport0);
|
||||
ipset_type_add(&ipset_hash_ipport0);
|
||||
ipset_type_add(&ipset_hash_ipportip0);
|
||||
ipset_type_add(&ipset_hash_ipportnet0);
|
||||
ipset_type_add(&ipset_list_set0);
|
||||
|
||||
return parse_commandline(argc, argv);
|
||||
}
|
||||
97
extensions/ipset-5/src/ipset_bitmap_ip.c
Normal file
97
extensions/ipset-5/src/ipset_bitmap_ip.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/data.h> /* IPSET_OPT_* */
|
||||
#include <libipset/parse.h> /* parser functions */
|
||||
#include <libipset/print.h> /* printing functions */
|
||||
#include <libipset/types.h> /* prototypes */
|
||||
|
||||
/* Parse commandline arguments */
|
||||
static const struct ipset_arg bitmap_ip_create_args[] = {
|
||||
{ .name = { "range", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
|
||||
.parse = ipset_parse_netrange, .print = ipset_print_ip,
|
||||
},
|
||||
{ .name = { "netmask", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_NETMASK,
|
||||
.parse = ipset_parse_netmask, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
/* Backward compatibility */
|
||||
{ .name = { "from", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
|
||||
.parse = ipset_parse_single_ip,
|
||||
},
|
||||
{ .name = { "to", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO,
|
||||
.parse = ipset_parse_single_ip,
|
||||
},
|
||||
{ .name = { "network", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
|
||||
.parse = ipset_parse_net,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct ipset_arg bitmap_ip_add_args[] = {
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const char bitmap_ip_usage[] =
|
||||
"create SETNAME bitmap:ip range IP/CIDR|FROM-TO\n"
|
||||
" [netmask CIDR] [timeout VALUE]\n"
|
||||
"add SETNAME IP|IP/CIDR|FROM-TO [timeout VALUE]\n"
|
||||
"del SETNAME IP|IP/CIDR|FROM-TO\n"
|
||||
"test SETNAME IP\n\n"
|
||||
"where IP, FROM and TO are IPv4 addresses (or hostnames),\n"
|
||||
" CIDR is a valid IPv4 CIDR prefix.\n";
|
||||
|
||||
struct ipset_type ipset_bitmap_ip0 = {
|
||||
.name = "bitmap:ip",
|
||||
.alias = { "ipmap", NULL },
|
||||
.revision = 0,
|
||||
.family = AF_INET,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.elem = {
|
||||
[IPSET_DIM_ONE] = {
|
||||
.parse = ipset_parse_ip,
|
||||
.print = ipset_print_ip,
|
||||
.opt = IPSET_OPT_IP
|
||||
},
|
||||
},
|
||||
.args = {
|
||||
[IPSET_CREATE] = bitmap_ip_create_args,
|
||||
[IPSET_ADD] = bitmap_ip_add_args,
|
||||
},
|
||||
.mandatory = {
|
||||
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO),
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
},
|
||||
.full = {
|
||||
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_NETMASK)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
},
|
||||
|
||||
.usage = bitmap_ip_usage,
|
||||
};
|
||||
100
extensions/ipset-5/src/ipset_bitmap_ipmac.c
Normal file
100
extensions/ipset-5/src/ipset_bitmap_ipmac.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/data.h> /* IPSET_OPT_* */
|
||||
#include <libipset/parse.h> /* parser functions */
|
||||
#include <libipset/print.h> /* printing functions */
|
||||
#include <libipset/types.h> /* prototypes */
|
||||
|
||||
/* Parse commandline arguments */
|
||||
static const struct ipset_arg bitmap_ipmac_create_args[] = {
|
||||
{ .name = { "range", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
|
||||
.parse = ipset_parse_netrange, .print = ipset_print_ip,
|
||||
},
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
/* Backward compatibility */
|
||||
{ .name = { "from", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
|
||||
.parse = ipset_parse_single_ip,
|
||||
},
|
||||
{ .name = { "to", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO,
|
||||
.parse = ipset_parse_single_ip,
|
||||
},
|
||||
{ .name = { "network", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
|
||||
.parse = ipset_parse_net,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct ipset_arg bitmap_ipmac_add_args[] = {
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const char bitmap_ipmac_usage[] =
|
||||
"create SETNAME bitmap:ip,mac range IP/CIDR|FROM-TO\n"
|
||||
" [matchunset] [timeout VALUE]\n"
|
||||
"add SETNAME IP[,MAC] [timeout VALUE]\n"
|
||||
"del SETNAME IP[,MAC]\n"
|
||||
"test SETNAME IP[,MAC]\n\n"
|
||||
"where IP, FROM and TO are IPv4 addresses (or hostnames),\n"
|
||||
" CIDR is a valid IPv4 CIDR prefix,\n"
|
||||
" MAC is a valid MAC address.\n";
|
||||
|
||||
struct ipset_type ipset_bitmap_ipmac0 = {
|
||||
.name = "bitmap:ip,mac",
|
||||
.alias = { "macipmap", NULL },
|
||||
.revision = 0,
|
||||
.family = AF_INET,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.last_elem_optional = true,
|
||||
.elem = {
|
||||
[IPSET_DIM_ONE] = {
|
||||
.parse = ipset_parse_single_ip,
|
||||
.print = ipset_print_ip,
|
||||
.opt = IPSET_OPT_IP
|
||||
},
|
||||
[IPSET_DIM_TWO] = {
|
||||
.parse = ipset_parse_ether,
|
||||
.print = ipset_print_ether,
|
||||
.opt = IPSET_OPT_ETHER
|
||||
},
|
||||
},
|
||||
.args = {
|
||||
[IPSET_CREATE] = bitmap_ipmac_create_args,
|
||||
[IPSET_ADD] = bitmap_ipmac_add_args,
|
||||
},
|
||||
.mandatory = {
|
||||
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO),
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
},
|
||||
.full = {
|
||||
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_ETHER)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_ETHER),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_ETHER),
|
||||
},
|
||||
|
||||
.usage = bitmap_ipmac_usage,
|
||||
};
|
||||
87
extensions/ipset-5/src/ipset_bitmap_port.c
Normal file
87
extensions/ipset-5/src/ipset_bitmap_port.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/data.h> /* IPSET_OPT_* */
|
||||
#include <libipset/parse.h> /* parser functions */
|
||||
#include <libipset/print.h> /* printing functions */
|
||||
#include <libipset/types.h> /* prototypes */
|
||||
|
||||
/* Parse commandline arguments */
|
||||
static const struct ipset_arg bitmap_port_create_args[] = {
|
||||
{ .name = { "range", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PORT,
|
||||
.parse = ipset_parse_tcp_port, .print = ipset_print_port,
|
||||
},
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
/* Backward compatibility */
|
||||
{ .name = { "from", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PORT,
|
||||
.parse = ipset_parse_single_tcp_port,
|
||||
},
|
||||
{ .name = { "to", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PORT_TO,
|
||||
.parse = ipset_parse_single_tcp_port,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct ipset_arg bitmap_port_add_args[] = {
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const char bitmap_port_usage[] =
|
||||
"create SETNAME bitmap:port range FROM-TO\n"
|
||||
" [timeout VALUE]\n"
|
||||
"add SETNAME PORT|FROM-TO [timeout VALUE]\n"
|
||||
"del SETNAME PORT|FROM-TO\n"
|
||||
"test SETNAME PORT\n\n"
|
||||
"where PORT, FROM and TO are port numbers or port names from /etc/services.\n";
|
||||
|
||||
struct ipset_type ipset_bitmap_port0 = {
|
||||
.name = "bitmap:port",
|
||||
.alias = { "portmap", NULL },
|
||||
.revision = 0,
|
||||
.family = AF_UNSPEC,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.elem = {
|
||||
[IPSET_DIM_ONE] = {
|
||||
.parse = ipset_parse_tcp_port,
|
||||
.print = ipset_print_port,
|
||||
.opt = IPSET_OPT_PORT
|
||||
},
|
||||
},
|
||||
.args = {
|
||||
[IPSET_CREATE] = bitmap_port_create_args,
|
||||
[IPSET_ADD] = bitmap_port_add_args,
|
||||
},
|
||||
.mandatory = {
|
||||
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO),
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_PORT),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_PORT),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_PORT),
|
||||
},
|
||||
.full = {
|
||||
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_PORT),
|
||||
},
|
||||
|
||||
.usage = bitmap_port_usage,
|
||||
};
|
||||
120
extensions/ipset-5/src/ipset_hash_ip.c
Normal file
120
extensions/ipset-5/src/ipset_hash_ip.c
Normal file
@@ -0,0 +1,120 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/data.h> /* IPSET_OPT_* */
|
||||
#include <libipset/parse.h> /* parser functions */
|
||||
#include <libipset/print.h> /* printing functions */
|
||||
#include <libipset/types.h> /* prototypes */
|
||||
|
||||
/* Parse commandline arguments */
|
||||
static const struct ipset_arg hash_ip_create_args[] = {
|
||||
{ .name = { "family", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family, .print = ipset_print_family,
|
||||
},
|
||||
/* Alias: family inet */
|
||||
{ .name = { "-4", NULL },
|
||||
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family,
|
||||
},
|
||||
/* Alias: family inet6 */
|
||||
{ .name = { "-6", NULL },
|
||||
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family,
|
||||
},
|
||||
{ .name = { "hashsize", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "maxelem", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "netmask", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_NETMASK,
|
||||
.parse = ipset_parse_netmask, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
/* Ignored options: backward compatibilty */
|
||||
{ .name = { "probes", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES,
|
||||
.parse = ipset_parse_ignored, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "resize", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE,
|
||||
.parse = ipset_parse_ignored, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "gc", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_GC,
|
||||
.parse = ipset_parse_ignored, .print = ipset_print_number,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct ipset_arg hash_ip_add_args[] = {
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const char hash_ip_usage[] =
|
||||
"create SETNAME hash:ip\n"
|
||||
" [family inet|inet6]\n"
|
||||
" [hashsize VALUE] [maxelem VALUE]\n"
|
||||
" [netmask CIDR] [timeout VALUE]\n"
|
||||
"add SETNAME IP [timeout VALUE]\n"
|
||||
"del SETNAME IP\n"
|
||||
"test SETNAME IP\n\n"
|
||||
"where depending on the INET family\n"
|
||||
" IP is a valid IPv4 or IPv6 address (or hostname),\n"
|
||||
" CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
|
||||
" Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
|
||||
" is supported for IPv4.\n";
|
||||
|
||||
struct ipset_type ipset_hash_ip0 = {
|
||||
.name = "hash:ip",
|
||||
.alias = { "iphash", "iptree", "iptreemap", NULL },
|
||||
.revision = 0,
|
||||
.family = AF_INET46,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.elem = {
|
||||
[IPSET_DIM_ONE] = {
|
||||
.parse = ipset_parse_ip4_single6,
|
||||
.print = ipset_print_ip,
|
||||
.opt = IPSET_OPT_IP
|
||||
},
|
||||
},
|
||||
.compat_parse_elem = ipset_parse_iptimeout,
|
||||
.args = {
|
||||
[IPSET_CREATE] = hash_ip_create_args,
|
||||
[IPSET_ADD] = hash_ip_add_args,
|
||||
},
|
||||
.mandatory = {
|
||||
[IPSET_CREATE] = 0,
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
},
|
||||
.full = {
|
||||
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
|
||||
| IPSET_FLAG(IPSET_OPT_MAXELEM)
|
||||
| IPSET_FLAG(IPSET_OPT_NETMASK)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
},
|
||||
|
||||
.usage = hash_ip_usage,
|
||||
};
|
||||
144
extensions/ipset-5/src/ipset_hash_ipport.c
Normal file
144
extensions/ipset-5/src/ipset_hash_ipport.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/data.h> /* IPSET_OPT_* */
|
||||
#include <libipset/parse.h> /* parser functions */
|
||||
#include <libipset/print.h> /* printing functions */
|
||||
#include <libipset/ui.h> /* ipset_port_usage */
|
||||
#include <libipset/types.h> /* prototypes */
|
||||
|
||||
/* Parse commandline arguments */
|
||||
static const struct ipset_arg hash_ipport_create_args[] = {
|
||||
{ .name = { "family", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family, .print = ipset_print_family,
|
||||
},
|
||||
/* Alias: family inet */
|
||||
{ .name = { "-4", NULL },
|
||||
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family,
|
||||
},
|
||||
/* Alias: family inet6 */
|
||||
{ .name = { "-6", NULL },
|
||||
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family,
|
||||
},
|
||||
{ .name = { "hashsize", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "maxelem", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
/* Backward compatibility */
|
||||
{ .name = { "probes", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES,
|
||||
.parse = ipset_parse_ignored, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "resize", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE,
|
||||
.parse = ipset_parse_ignored, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "from", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
|
||||
.parse = ipset_parse_ignored,
|
||||
},
|
||||
{ .name = { "to", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO,
|
||||
.parse = ipset_parse_ignored,
|
||||
},
|
||||
{ .name = { "network", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
|
||||
.parse = ipset_parse_ignored,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct ipset_arg hash_ipport_add_args[] = {
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const char hash_ipport_usage[] =
|
||||
"create SETNAME hash:ip,port\n"
|
||||
" [family inet|inet6]\n"
|
||||
" [hashsize VALUE] [maxelem VALUE]\n"
|
||||
" [timeout VALUE]\n"
|
||||
"add SETNAME IP,PROTO:PORT [timeout VALUE]\n"
|
||||
"del SETNAME IP,PROTO:PORT\n"
|
||||
"test SETNAME IP,PROTO:PORT\n\n"
|
||||
"where depending on the INET family\n"
|
||||
" IP is a valid IPv4 or IPv6 address (or hostname).\n"
|
||||
" Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
|
||||
" is supported for IPv4.\n"
|
||||
" Adding/deleting multiple elements with TCP/UDP port range\n"
|
||||
" is supported both for IPv4 and IPv6.\n";
|
||||
|
||||
struct ipset_type ipset_hash_ipport0 = {
|
||||
.name = "hash:ip,port",
|
||||
.alias = { "ipporthash", NULL },
|
||||
.revision = 0,
|
||||
.family = AF_INET46,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.elem = {
|
||||
[IPSET_DIM_ONE] = {
|
||||
.parse = ipset_parse_ip4_single6,
|
||||
.print = ipset_print_ip,
|
||||
.opt = IPSET_OPT_IP
|
||||
},
|
||||
[IPSET_DIM_TWO] = {
|
||||
.parse = ipset_parse_proto_port,
|
||||
.print = ipset_print_proto_port,
|
||||
.opt = IPSET_OPT_PORT
|
||||
},
|
||||
},
|
||||
.args = {
|
||||
[IPSET_CREATE] = hash_ipport_create_args,
|
||||
[IPSET_ADD] = hash_ipport_add_args,
|
||||
},
|
||||
.mandatory = {
|
||||
[IPSET_CREATE] = 0,
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT),
|
||||
},
|
||||
.full = {
|
||||
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
|
||||
| IPSET_FLAG(IPSET_OPT_MAXELEM)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO),
|
||||
},
|
||||
|
||||
.usage = hash_ipport_usage,
|
||||
.usagefn = ipset_port_usage,
|
||||
};
|
||||
155
extensions/ipset-5/src/ipset_hash_ipportip.c
Normal file
155
extensions/ipset-5/src/ipset_hash_ipportip.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/data.h> /* IPSET_OPT_* */
|
||||
#include <libipset/parse.h> /* parser functions */
|
||||
#include <libipset/print.h> /* printing functions */
|
||||
#include <libipset/ui.h> /* ipset_port_usage */
|
||||
#include <libipset/types.h> /* prototypes */
|
||||
|
||||
/* Parse commandline arguments */
|
||||
static const struct ipset_arg hash_ipportip_create_args[] = {
|
||||
{ .name = { "family", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family, .print = ipset_print_family,
|
||||
},
|
||||
/* Alias: family inet */
|
||||
{ .name = { "-4", NULL },
|
||||
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family,
|
||||
},
|
||||
/* Alias: family inet6 */
|
||||
{ .name = { "-6", NULL },
|
||||
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family,
|
||||
},
|
||||
{ .name = { "hashsize", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "maxelem", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
/* Backward compatibility */
|
||||
{ .name = { "probes", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES,
|
||||
.parse = ipset_parse_ignored, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "resize", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE,
|
||||
.parse = ipset_parse_ignored, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "from", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
|
||||
.parse = ipset_parse_ignored,
|
||||
},
|
||||
{ .name = { "to", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO,
|
||||
.parse = ipset_parse_ignored,
|
||||
},
|
||||
{ .name = { "network", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
|
||||
.parse = ipset_parse_ignored,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct ipset_arg hash_ipportip_add_args[] = {
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const char hash_ipportip_usage[] =
|
||||
"create SETNAME hash:ip,port,ip\n"
|
||||
" [family inet|inet6]\n"
|
||||
" [hashsize VALUE] [maxelem VALUE]\n"
|
||||
" [timeout VALUE]\n"
|
||||
"add SETNAME IP,PROTO:PORT,IP [timeout VALUE]\n"
|
||||
"del SETNAME IP,PROTO:PORT,IP\n"
|
||||
"test SETNAME IP,PROTO:PORT,IP\n\n"
|
||||
"where depending on the INET family\n"
|
||||
" IP is a valid IPv4 or IPv6 address (or hostname).\n"
|
||||
" Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
|
||||
" in the first IP component is supported for IPv4.\n"
|
||||
" Adding/deleting multiple elements with TCP/UDP port range\n"
|
||||
" is supported both for IPv4 and IPv6.\n";
|
||||
|
||||
struct ipset_type ipset_hash_ipportip0 = {
|
||||
.name = "hash:ip,port,ip",
|
||||
.alias = { "ipportiphash", NULL },
|
||||
.revision = 0,
|
||||
.family = AF_INET46,
|
||||
.dimension = IPSET_DIM_THREE,
|
||||
.elem = {
|
||||
[IPSET_DIM_ONE] = {
|
||||
.parse = ipset_parse_ip4_single6,
|
||||
.print = ipset_print_ip,
|
||||
.opt = IPSET_OPT_IP
|
||||
},
|
||||
[IPSET_DIM_TWO] = {
|
||||
.parse = ipset_parse_proto_port,
|
||||
.print = ipset_print_proto_port,
|
||||
.opt = IPSET_OPT_PORT
|
||||
},
|
||||
[IPSET_DIM_THREE] = {
|
||||
.parse = ipset_parse_single_ip,
|
||||
.print = ipset_print_ip,
|
||||
.opt = IPSET_OPT_IP2
|
||||
},
|
||||
},
|
||||
.args = {
|
||||
[IPSET_CREATE] = hash_ipportip_create_args,
|
||||
[IPSET_ADD] = hash_ipportip_add_args,
|
||||
},
|
||||
.mandatory = {
|
||||
[IPSET_CREATE] = 0,
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_IP2),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_IP2),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_IP2),
|
||||
},
|
||||
.full = {
|
||||
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
|
||||
| IPSET_FLAG(IPSET_OPT_MAXELEM)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_IP2)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_IP2),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_IP2),
|
||||
},
|
||||
|
||||
.usage = hash_ipportip_usage,
|
||||
.usagefn = ipset_port_usage,
|
||||
};
|
||||
159
extensions/ipset-5/src/ipset_hash_ipportnet.c
Normal file
159
extensions/ipset-5/src/ipset_hash_ipportnet.c
Normal file
@@ -0,0 +1,159 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/data.h> /* IPSET_OPT_* */
|
||||
#include <libipset/parse.h> /* parser functions */
|
||||
#include <libipset/print.h> /* printing functions */
|
||||
#include <libipset/ui.h> /* ipset_port_usage */
|
||||
#include <libipset/types.h> /* prototypes */
|
||||
|
||||
/* Parse commandline arguments */
|
||||
static const struct ipset_arg hash_ipportnet_create_args[] = {
|
||||
{ .name = { "family", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family, .print = ipset_print_family,
|
||||
},
|
||||
/* Alias: family inet */
|
||||
{ .name = { "-4", NULL },
|
||||
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family,
|
||||
},
|
||||
/* Alias: family inet6 */
|
||||
{ .name = { "-6", NULL },
|
||||
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family,
|
||||
},
|
||||
{ .name = { "hashsize", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "maxelem", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
/* Backward compatibility */
|
||||
{ .name = { "probes", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES,
|
||||
.parse = ipset_parse_ignored, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "resize", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE,
|
||||
.parse = ipset_parse_ignored, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "from", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
|
||||
.parse = ipset_parse_ignored,
|
||||
},
|
||||
{ .name = { "to", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO,
|
||||
.parse = ipset_parse_ignored,
|
||||
},
|
||||
{ .name = { "network", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
|
||||
.parse = ipset_parse_ignored,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct ipset_arg hash_ipportnet_add_args[] = {
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const char hash_ipportnet_usage[] =
|
||||
"create SETNAME hash:ip,port,net\n"
|
||||
" [family inet|inet6]\n"
|
||||
" [hashsize VALUE] [maxelem VALUE]\n"
|
||||
" [timeout VALUE]\n"
|
||||
"add SETNAME IP,PROTO:PORT,IP[/CIDR] [timeout VALUE]\n"
|
||||
"del SETNAME IP,PROTO:PORT,IP[/CIDR]\n"
|
||||
"test SETNAME IP,PROTO:PORT,IP[/CIDR]\n\n"
|
||||
"where depending on the INET family\n"
|
||||
" IP are valid IPv4 or IPv6 addresses (or hostnames),\n"
|
||||
" CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
|
||||
" Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
|
||||
" in the first IP component is supported for IPv4.\n"
|
||||
" Adding/deleting multiple elements with TCP/UDP port range\n"
|
||||
" is supported both for IPv4 and IPv6.\n";
|
||||
|
||||
struct ipset_type ipset_hash_ipportnet0 = {
|
||||
.name = "hash:ip,port,net",
|
||||
.alias = { "ipportnethash", NULL },
|
||||
.revision = 0,
|
||||
.family = AF_INET46,
|
||||
.dimension = IPSET_DIM_THREE,
|
||||
.elem = {
|
||||
[IPSET_DIM_ONE] = {
|
||||
.parse = ipset_parse_ip4_single6,
|
||||
.print = ipset_print_ip,
|
||||
.opt = IPSET_OPT_IP
|
||||
},
|
||||
[IPSET_DIM_TWO] = {
|
||||
.parse = ipset_parse_proto_port,
|
||||
.print = ipset_print_proto_port,
|
||||
.opt = IPSET_OPT_PORT
|
||||
},
|
||||
[IPSET_DIM_THREE] = {
|
||||
.parse = ipset_parse_ipnet,
|
||||
.print = ipset_print_ip,
|
||||
.opt = IPSET_OPT_IP2
|
||||
},
|
||||
},
|
||||
.args = {
|
||||
[IPSET_CREATE] = hash_ipportnet_create_args,
|
||||
[IPSET_ADD] = hash_ipportnet_add_args,
|
||||
},
|
||||
.mandatory = {
|
||||
[IPSET_CREATE] = 0,
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_IP2),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_IP2),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_IP2),
|
||||
},
|
||||
.full = {
|
||||
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
|
||||
| IPSET_FLAG(IPSET_OPT_MAXELEM)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_IP2)
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR2)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_IP_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_IP2)
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR2),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_IP2)
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR2),
|
||||
},
|
||||
|
||||
.usage = hash_ipportnet_usage,
|
||||
.usagefn = ipset_port_usage,
|
||||
};
|
||||
109
extensions/ipset-5/src/ipset_hash_net.c
Normal file
109
extensions/ipset-5/src/ipset_hash_net.c
Normal file
@@ -0,0 +1,109 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/data.h> /* IPSET_OPT_* */
|
||||
#include <libipset/parse.h> /* parser functions */
|
||||
#include <libipset/print.h> /* printing functions */
|
||||
#include <libipset/types.h> /* prototypes */
|
||||
|
||||
/* Parse commandline arguments */
|
||||
static const struct ipset_arg hash_net_create_args[] = {
|
||||
{ .name = { "family", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family, .print = ipset_print_family,
|
||||
},
|
||||
/* Alias: family inet */
|
||||
{ .name = { "-4", NULL },
|
||||
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family,
|
||||
},
|
||||
/* Alias: family inet6 */
|
||||
{ .name = { "-6", NULL },
|
||||
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family,
|
||||
},
|
||||
{ .name = { "hashsize", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "maxelem", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
/* Ignored options: backward compatibilty */
|
||||
{ .name = { "probes", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES,
|
||||
.parse = ipset_parse_ignored, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "resize", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE,
|
||||
.parse = ipset_parse_ignored, .print = ipset_print_number,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct ipset_arg hash_net_add_args[] = {
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const char hash_net_usage[] =
|
||||
"create SETNAME hash:net\n"
|
||||
" [family inet|inet6]\n"
|
||||
" [hashsize VALUE] [maxelem VALUE]\n"
|
||||
" [timeout VALUE]\n"
|
||||
"add SETNAME IP[/CIDR] [timeout VALUE]\n"
|
||||
"del SETNAME IP[/CIDR]\n"
|
||||
"test SETNAME IP[/CIDR]\n\n"
|
||||
"where depending on the INET family\n"
|
||||
" IP is an IPv4 or IPv6 address (or hostname),\n"
|
||||
" CIDR is a valid IPv4 or IPv6 CIDR prefix.\n";
|
||||
|
||||
struct ipset_type ipset_hash_net0 = {
|
||||
.name = "hash:net",
|
||||
.alias = { "nethash", NULL },
|
||||
.revision = 0,
|
||||
.family = AF_INET46,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.elem = {
|
||||
[IPSET_DIM_ONE] = {
|
||||
.parse = ipset_parse_ipnet,
|
||||
.print = ipset_print_ip,
|
||||
.opt = IPSET_OPT_IP
|
||||
},
|
||||
},
|
||||
.args = {
|
||||
[IPSET_CREATE] = hash_net_create_args,
|
||||
[IPSET_ADD] = hash_net_add_args,
|
||||
},
|
||||
.mandatory = {
|
||||
[IPSET_CREATE] = 0,
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
|
||||
},
|
||||
.full = {
|
||||
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
|
||||
| IPSET_FLAG(IPSET_OPT_MAXELEM)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR),
|
||||
},
|
||||
|
||||
.usage = hash_net_usage,
|
||||
};
|
||||
122
extensions/ipset-5/src/ipset_hash_netport.c
Normal file
122
extensions/ipset-5/src/ipset_hash_netport.c
Normal file
@@ -0,0 +1,122 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/data.h> /* IPSET_OPT_* */
|
||||
#include <libipset/parse.h> /* parser functions */
|
||||
#include <libipset/print.h> /* printing functions */
|
||||
#include <libipset/ui.h> /* ipset_port_usage */
|
||||
#include <libipset/types.h> /* prototypes */
|
||||
|
||||
/* Parse commandline arguments */
|
||||
static const struct ipset_arg hash_netport_create_args[] = {
|
||||
{ .name = { "family", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family, .print = ipset_print_family,
|
||||
},
|
||||
/* Alias: family inet */
|
||||
{ .name = { "-4", NULL },
|
||||
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family,
|
||||
},
|
||||
/* Alias: family inet6 */
|
||||
{ .name = { "-6", NULL },
|
||||
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
|
||||
.parse = ipset_parse_family,
|
||||
},
|
||||
{ .name = { "hashsize", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "maxelem", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct ipset_arg hash_netport_add_args[] = {
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const char hash_netport_usage[] =
|
||||
"create SETNAME hash:net,port\n"
|
||||
" [family inet|inet6]\n"
|
||||
" [hashsize VALUE] [maxelem VALUE]\n"
|
||||
" [timeout VALUE]\n"
|
||||
"add SETNAME IP[/CIDR],PROTO:PORT [timeout VALUE]\n"
|
||||
"del SETNAME IP[/CIDR],PROTO:PORT\n"
|
||||
"test SETNAME IP[/CIDR],PROTO:PORT\n\n"
|
||||
"where depending on the INET family\n"
|
||||
" IP is a valid IPv4 or IPv6 address (or hostname),\n"
|
||||
" CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
|
||||
" Adding/deleting multiple elements with TCP/UDP port range supported.\n";
|
||||
|
||||
struct ipset_type ipset_hash_netport0 = {
|
||||
.name = "hash:net,port",
|
||||
.alias = { "netporthash", NULL },
|
||||
.revision = 0,
|
||||
.family = AF_INET46,
|
||||
.dimension = IPSET_DIM_TWO,
|
||||
.elem = {
|
||||
[IPSET_DIM_ONE] = {
|
||||
.parse = ipset_parse_ipnet,
|
||||
.print = ipset_print_ip,
|
||||
.opt = IPSET_OPT_IP
|
||||
},
|
||||
[IPSET_DIM_TWO] = {
|
||||
.parse = ipset_parse_proto_port,
|
||||
.print = ipset_print_proto_port,
|
||||
.opt = IPSET_OPT_PORT
|
||||
},
|
||||
},
|
||||
.args = {
|
||||
[IPSET_CREATE] = hash_netport_create_args,
|
||||
[IPSET_ADD] = hash_netport_add_args,
|
||||
},
|
||||
.mandatory = {
|
||||
[IPSET_CREATE] = 0,
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT),
|
||||
},
|
||||
.full = {
|
||||
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
|
||||
| IPSET_FLAG(IPSET_OPT_MAXELEM)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT)
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT_TO)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
|
||||
| IPSET_FLAG(IPSET_OPT_PORT)
|
||||
| IPSET_FLAG(IPSET_OPT_PROTO)
|
||||
| IPSET_FLAG(IPSET_OPT_CIDR),
|
||||
},
|
||||
|
||||
.usage = hash_netport_usage,
|
||||
.usagefn = ipset_port_usage,
|
||||
};
|
||||
91
extensions/ipset-5/src/ipset_list_set.c
Normal file
91
extensions/ipset-5/src/ipset_list_set.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <libipset/data.h> /* IPSET_OPT_* */
|
||||
#include <libipset/parse.h> /* parser functions */
|
||||
#include <libipset/print.h> /* printing functions */
|
||||
#include <libipset/types.h> /* prototypes */
|
||||
|
||||
/* Parse commandline arguments */
|
||||
static const struct ipset_arg list_set_create_args[] = {
|
||||
{ .name = { "size", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_SIZE,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct ipset_arg list_set_adt_args[] = {
|
||||
{ .name = { "timeout", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
|
||||
.parse = ipset_parse_uint32, .print = ipset_print_number,
|
||||
},
|
||||
{ .name = { "before", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_NAMEREF,
|
||||
.parse = ipset_parse_before,
|
||||
},
|
||||
{ .name = { "after", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_NAMEREF,
|
||||
.parse = ipset_parse_after,
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const char list_set_usage[] =
|
||||
"create SETNAME list:set\n"
|
||||
" [size VALUE] [timeout VALUE]\n"
|
||||
"add SETNAME NAME [before|after NAME] [timeout VALUE]\n"
|
||||
"del SETNAME NAME [before|after NAME]\n"
|
||||
"test SETNAME NAME [before|after NAME]\n\n"
|
||||
"where NAME are existing set names.\n";
|
||||
|
||||
struct ipset_type ipset_list_set0 = {
|
||||
.name = "list:set",
|
||||
.alias = { "setlist", NULL },
|
||||
.revision = 0,
|
||||
.family = AF_UNSPEC,
|
||||
.dimension = IPSET_DIM_ONE,
|
||||
.elem = {
|
||||
[IPSET_DIM_ONE] = {
|
||||
.parse = ipset_parse_setname,
|
||||
.print = ipset_print_name,
|
||||
.opt = IPSET_OPT_NAME
|
||||
},
|
||||
},
|
||||
.compat_parse_elem = ipset_parse_name_compat,
|
||||
.args = {
|
||||
[IPSET_CREATE] = list_set_create_args,
|
||||
[IPSET_ADD] = list_set_adt_args,
|
||||
[IPSET_DEL] = list_set_adt_args,
|
||||
[IPSET_TEST] = list_set_adt_args,
|
||||
},
|
||||
.mandatory = {
|
||||
[IPSET_CREATE] = 0,
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_NAME),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_NAME),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_NAME),
|
||||
},
|
||||
.full = {
|
||||
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_SIZE)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_NAME)
|
||||
| IPSET_FLAG(IPSET_OPT_BEFORE)
|
||||
| IPSET_FLAG(IPSET_OPT_NAMEREF)
|
||||
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
|
||||
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_NAME)
|
||||
| IPSET_FLAG(IPSET_OPT_BEFORE)
|
||||
| IPSET_FLAG(IPSET_OPT_NAMEREF),
|
||||
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_NAME)
|
||||
| IPSET_FLAG(IPSET_OPT_BEFORE)
|
||||
| IPSET_FLAG(IPSET_OPT_NAMEREF),
|
||||
},
|
||||
|
||||
.usage = list_set_usage,
|
||||
};
|
||||
276
extensions/ipset-5/src/ui.c
Normal file
276
extensions/ipset-5/src/ui.c
Normal file
@@ -0,0 +1,276 @@
|
||||
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <assert.h> /* assert */
|
||||
#include <ctype.h> /* tolower */
|
||||
#include <string.h> /* memcmp, str* */
|
||||
|
||||
#include <libipset/linux_ip_set.h> /* IPSET_CMD_* */
|
||||
#include <libipset/icmp.h> /* id_to_icmp */
|
||||
#include <libipset/icmpv6.h> /* id_to_icmpv6 */
|
||||
#include <libipset/types.h> /* IPSET_*_ARG */
|
||||
#include <libipset/session.h> /* ipset_envopt_parse */
|
||||
#include <libipset/parse.h> /* ipset_parse_family */
|
||||
#include <libipset/print.h> /* ipset_print_family */
|
||||
#include <libipset/utils.h> /* STREQ */
|
||||
#include <libipset/ui.h> /* prototypes */
|
||||
|
||||
/* Commands and environment options */
|
||||
|
||||
const struct ipset_commands ipset_commands[] = {
|
||||
/* Order is important */
|
||||
|
||||
{ /* c[reate], --create, n, -N */
|
||||
.cmd = IPSET_CMD_CREATE,
|
||||
.name = { "create", "n" },
|
||||
.has_arg = IPSET_MANDATORY_ARG2,
|
||||
.help = "SETNAME TYPENAME [type-specific-options]\n"
|
||||
" Create a new set",
|
||||
},
|
||||
{ /* a[dd], --add, -A */
|
||||
.cmd = IPSET_CMD_ADD,
|
||||
.name = { "add", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG2,
|
||||
.help = "SETNAME ENTRY\n"
|
||||
" Add entry to the named set",
|
||||
},
|
||||
{ /* d[el], --del, -D */
|
||||
.cmd = IPSET_CMD_DEL,
|
||||
.name = { "del", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG2,
|
||||
.help = "SETNAME ENTRY\n"
|
||||
" Delete entry from the named set",
|
||||
},
|
||||
{ /* t[est], --test, -T */
|
||||
.cmd = IPSET_CMD_TEST,
|
||||
.name = { "test", NULL },
|
||||
.has_arg = IPSET_MANDATORY_ARG2,
|
||||
.help = "SETNAME ENTRY\n"
|
||||
" Test entry in the named set",
|
||||
},
|
||||
{ /* des[troy], --destroy, x, -X */
|
||||
.cmd = IPSET_CMD_DESTROY,
|
||||
.name = { "destroy", "x" },
|
||||
.has_arg = IPSET_OPTIONAL_ARG,
|
||||
.help = "[SETNAME]\n"
|
||||
" Destroy a named set or all sets",
|
||||
},
|
||||
{ /* l[ist], --list, -L */
|
||||
.cmd = IPSET_CMD_LIST,
|
||||
.name = { "list", NULL },
|
||||
.has_arg = IPSET_OPTIONAL_ARG,
|
||||
.help = "[SETNAME]\n"
|
||||
" List the entries of a named set or all sets",
|
||||
},
|
||||
{ /* s[save], --save, -S */
|
||||
.cmd = IPSET_CMD_SAVE,
|
||||
.name = { "save", NULL },
|
||||
.has_arg = IPSET_OPTIONAL_ARG,
|
||||
.help = "[SETNAME]\n"
|
||||
" Save the named set or all sets to stdout",
|
||||
},
|
||||
{ /* r[estore], --restore, -R */
|
||||
.cmd = IPSET_CMD_RESTORE,
|
||||
.name = { "restore", NULL },
|
||||
.has_arg = IPSET_NO_ARG,
|
||||
.help = "\n"
|
||||
" Restore a saved state",
|
||||
},
|
||||
{ /* f[lush], --flush, -F */
|
||||
.cmd = IPSET_CMD_FLUSH,
|
||||
.name = { "flush", NULL },
|
||||
.has_arg = IPSET_OPTIONAL_ARG,
|
||||
.help = "[SETNAME]\n"
|
||||
" Flush a named set or all sets",
|
||||
},
|
||||
{ /* ren[ame], --rename, e, -E */
|
||||
.cmd = IPSET_CMD_RENAME,
|
||||
.name = { "rename", "e" },
|
||||
.has_arg = IPSET_MANDATORY_ARG2,
|
||||
.help = "FROM-SETNAME TO-SETNAME\n"
|
||||
" Rename two sets",
|
||||
},
|
||||
{ /* sw[ap], --swap, w, -W */
|
||||
.cmd = IPSET_CMD_SWAP,
|
||||
.name = { "swap", "w" },
|
||||
.has_arg = IPSET_MANDATORY_ARG2,
|
||||
.help = "FROM-SETNAME TO-SETNAME\n"
|
||||
" Swap the contect of two existing sets",
|
||||
},
|
||||
{ /* h[elp, --help, -H */
|
||||
.cmd = IPSET_CMD_HELP,
|
||||
.name = { "help", NULL },
|
||||
.has_arg = IPSET_OPTIONAL_ARG,
|
||||
.help = "[TYPENAME]\n"
|
||||
" Print help, and settype specific help",
|
||||
},
|
||||
{ /* v[ersion], --version, -V */
|
||||
.cmd = IPSET_CMD_VERSION,
|
||||
.name = { "version", NULL },
|
||||
.has_arg = IPSET_NO_ARG,
|
||||
.help = "\n"
|
||||
" Print version information",
|
||||
},
|
||||
{ /* q[uit] */
|
||||
.cmd = IPSET_CMD_QUIT,
|
||||
.name = { "quit", NULL },
|
||||
.has_arg = IPSET_NO_ARG,
|
||||
.help = "\n"
|
||||
" Quit interactive mode",
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
/* Match a command: try to match as a prefix or letter-command */
|
||||
bool
|
||||
ipset_match_cmd(const char *arg, const char * const name[])
|
||||
{
|
||||
size_t len;
|
||||
|
||||
assert(arg);
|
||||
assert(name && name[0]);
|
||||
|
||||
/* Ignore (two) leading dashes */
|
||||
if (arg[0] == '-')
|
||||
arg++;
|
||||
if (arg[0] == '-')
|
||||
arg++;
|
||||
|
||||
len = strlen(arg);
|
||||
|
||||
if (len > strlen(name[0]) || !len)
|
||||
return false;
|
||||
else if (strncmp(arg, name[0], len) == 0)
|
||||
return true;
|
||||
else if (len != 1)
|
||||
return false;
|
||||
else if (name[1] == NULL)
|
||||
return tolower(arg[0]) == name[0][0];
|
||||
else
|
||||
return tolower(arg[0]) == name[1][0];
|
||||
}
|
||||
|
||||
const struct ipset_envopts ipset_envopts[] = {
|
||||
{ .name = { "-o", "-output" },
|
||||
.has_arg = IPSET_MANDATORY_ARG, .flag = IPSET_OPT_MAX,
|
||||
.parse = ipset_parse_output,
|
||||
.help = "plain|save|xml\n"
|
||||
" Specify output mode for listing sets.\n"
|
||||
" Default value for \"list\" command is mode \"plain\"\n"
|
||||
" and for \"save\" command is mode \"save\".",
|
||||
},
|
||||
{ .name = { "-s", "-sorted" },
|
||||
.parse = ipset_envopt_parse,
|
||||
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_SORTED,
|
||||
.help = "\n"
|
||||
" Print elements sorted (if supported by the set type).",
|
||||
},
|
||||
{ .name = { "-q", "-quiet" },
|
||||
.parse = ipset_envopt_parse,
|
||||
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_QUIET,
|
||||
.help = "\n"
|
||||
" Suppress any notice or warning message.",
|
||||
},
|
||||
{ .name = { "-r", "-resolve" },
|
||||
.parse = ipset_envopt_parse,
|
||||
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_RESOLVE,
|
||||
.help = "\n"
|
||||
" Try to resolve IP addresses in the output (slow!)",
|
||||
},
|
||||
{ .name = { "-!", "-exist" },
|
||||
.parse = ipset_envopt_parse,
|
||||
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_EXIST,
|
||||
.help = "\n"
|
||||
" Ignore errors when creating already created sets,\n"
|
||||
" when adding already existing elements\n"
|
||||
" or when deleting non-existing elements.",
|
||||
},
|
||||
{ },
|
||||
};
|
||||
|
||||
/* Strict option matching */
|
||||
bool
|
||||
ipset_match_option(const char *arg, const char * const name[])
|
||||
{
|
||||
assert(arg);
|
||||
assert(name && name[0]);
|
||||
|
||||
/* Skip two leading dashes */
|
||||
if (arg[0] == '-' && arg[1] == '-')
|
||||
arg++, arg++;
|
||||
|
||||
return STREQ(arg, name[0])
|
||||
|| (name[1] != NULL && STREQ(arg, name[1]));
|
||||
}
|
||||
|
||||
/* Strict envopt matching */
|
||||
bool
|
||||
ipset_match_envopt(const char *arg, const char * const name[])
|
||||
{
|
||||
assert(arg);
|
||||
assert(name && name[0]);
|
||||
|
||||
/* Skip one leading dash */
|
||||
if (arg[0] == '-' && arg[1] == '-')
|
||||
arg++;
|
||||
|
||||
return STREQ(arg, name[0])
|
||||
|| (name[1] != NULL && STREQ(arg, name[1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_shift_argv - shift off an argument
|
||||
* @arc: argument count
|
||||
* @argv: array of argument strings
|
||||
* @from: from where shift off an argument
|
||||
*
|
||||
* Shift off the argument at "from" from the array of
|
||||
* arguments argv of size argc.
|
||||
*/
|
||||
void
|
||||
ipset_shift_argv(int *argc, char *argv[], int from)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert(*argc >= from + 1);
|
||||
|
||||
for (i = from + 1; i <= *argc; i++) {
|
||||
argv[i-1] = argv[i];
|
||||
}
|
||||
(*argc)--;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_port_usage - prints the usage for the port parameter
|
||||
*
|
||||
* Print the usage for the port parameter to stdout.
|
||||
*/
|
||||
void
|
||||
ipset_port_usage(void)
|
||||
{
|
||||
int i;
|
||||
const char *name;
|
||||
|
||||
printf(" [PROTO:]PORT is a valid pattern of the following:\n"
|
||||
" PORTNAME port name from /etc/services\n"
|
||||
" PORTNUMBER port number identifier\n"
|
||||
" tcp|udp:PORTNAME|PORTNUMBER\n"
|
||||
" icmp:CODENAME supported ICMP codename\n"
|
||||
" icmp:TYPE/CODE ICMP type/code value\n"
|
||||
" icmpv6:CODENAME supported ICMPv6 codename\n"
|
||||
" icmpv6:TYPE/CODE ICMPv6 type/code value\n"
|
||||
" PROTO:0 all other protocols\n\n");
|
||||
|
||||
printf(" Supported ICMP codenames:\n");
|
||||
i = 0;
|
||||
while ((name = id_to_icmp(i++)) != NULL)
|
||||
printf(" %s\n", name);
|
||||
printf(" Supported ICMPv6 codenames:\n");
|
||||
i = 0;
|
||||
while ((name = id_to_icmpv6(i++)) != NULL)
|
||||
printf(" %s\n", name);
|
||||
}
|
||||
419
extensions/ipset-5/xt_set.c
Normal file
419
extensions/ipset-5/xt_set.c
Normal file
@@ -0,0 +1,419 @@
|
||||
/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
|
||||
* Patrick Schaaf <bof@bof.de>
|
||||
* Martin Josefsson <gandalf@wlug.westbo.se>
|
||||
* Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Kernel module which implements the set match and SET target
|
||||
* for netfilter/iptables. */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include "xt_set.h"
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
|
||||
MODULE_DESCRIPTION("Xtables: IP set match and target module");
|
||||
MODULE_ALIAS("xt_SET");
|
||||
MODULE_ALIAS("ipt_set");
|
||||
MODULE_ALIAS("ip6t_set");
|
||||
MODULE_ALIAS("ipt_SET");
|
||||
MODULE_ALIAS("ip6t_SET");
|
||||
|
||||
static inline int
|
||||
match_set(ip_set_id_t index, const struct sk_buff *skb,
|
||||
u8 pf, u8 dim, u8 flags, int inv)
|
||||
{
|
||||
if (ip_set_test(index, skb, pf, dim, flags))
|
||||
inv = !inv;
|
||||
return inv;
|
||||
}
|
||||
|
||||
/* Revision 0 interface: backward compatible with netfilter/iptables */
|
||||
|
||||
/* Backward compatibility constrains (incomplete):
|
||||
* 2.6.24: [NETLINK]: Introduce nested and byteorder flag to netlink attribute
|
||||
* 2.6.25: is_vmalloc_addr(): Check if an address is within the vmalloc
|
||||
* boundaries
|
||||
* 2.6.27: rcu: split list.h and move rcu-protected lists into rculist.h
|
||||
* 2.6.28: netfilter: ctnetlink: remove bogus module dependency between
|
||||
* ctnetlink and nf_nat (nfnl_lock/nfnl_unlock)
|
||||
* 2.6.29: generic swap(): introduce global macro swap(a, b)
|
||||
* 2.6.31: netfilter: passive OS fingerprint xtables match
|
||||
* 2.6.34: rcu: Add lockdep-enabled variants of rcu_dereference()
|
||||
*/
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
|
||||
#error "Linux kernel version too old: must be >= 2.6.34"
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
#define CHECK_OK 1
|
||||
#define CHECK_FAIL 0
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */
|
||||
#define CHECK_OK 0
|
||||
#define CHECK_FAIL (-EINVAL)
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
static bool
|
||||
set_match_v0(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */
|
||||
static bool
|
||||
set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
#endif
|
||||
{
|
||||
const struct xt_set_info_match_v0 *info = par->matchinfo;
|
||||
|
||||
return match_set(info->match_set.index, skb, par->family,
|
||||
info->match_set.u.compat.dim,
|
||||
info->match_set.u.compat.flags,
|
||||
info->match_set.u.compat.flags & IPSET_INV_MATCH);
|
||||
}
|
||||
|
||||
static void
|
||||
compat_flags(struct xt_set_info_v0 *info)
|
||||
{
|
||||
u_int8_t i;
|
||||
|
||||
/* Fill out compatibility data according to enum ip_set_kopt */
|
||||
info->u.compat.dim = IPSET_DIM_ZERO;
|
||||
if (info->u.flags[0] & IPSET_MATCH_INV)
|
||||
info->u.compat.flags |= IPSET_INV_MATCH;
|
||||
for (i = 0; i < IPSET_DIM_MAX-1 && info->u.flags[i]; i++) {
|
||||
info->u.compat.dim++;
|
||||
if (info->u.flags[i] & IPSET_SRC)
|
||||
info->u.compat.flags |= (1<<info->u.compat.dim);
|
||||
}
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
static bool
|
||||
set_match_v0_checkentry(const struct xt_mtchk_param *par)
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */
|
||||
static int
|
||||
set_match_v0_checkentry(const struct xt_mtchk_param *par)
|
||||
#endif
|
||||
{
|
||||
struct xt_set_info_match_v0 *info = par->matchinfo;
|
||||
ip_set_id_t index;
|
||||
|
||||
index = ip_set_nfnl_get_byindex(info->match_set.index);
|
||||
|
||||
if (index == IPSET_INVALID_ID) {
|
||||
pr_warning("Cannot find set indentified by id %u to match",
|
||||
info->match_set.index);
|
||||
return CHECK_FAIL; /* error */
|
||||
}
|
||||
if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) {
|
||||
pr_warning("That's nasty!");
|
||||
return CHECK_FAIL; /* error */
|
||||
}
|
||||
|
||||
/* Fill out compatibility data */
|
||||
compat_flags(&info->match_set);
|
||||
|
||||
return CHECK_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
set_match_v0_destroy(const struct xt_mtdtor_param *par)
|
||||
{
|
||||
struct xt_set_info_match_v0 *info = par->matchinfo;
|
||||
|
||||
ip_set_nfnl_put(info->match_set.index);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
static unsigned int
|
||||
set_target_v0(struct sk_buff *skb, const struct xt_target_param *par)
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */
|
||||
static unsigned int
|
||||
set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
#endif
|
||||
{
|
||||
const struct xt_set_info_target_v0 *info = par->targinfo;
|
||||
|
||||
if (info->add_set.index != IPSET_INVALID_ID)
|
||||
ip_set_add(info->add_set.index, skb, par->family,
|
||||
info->add_set.u.compat.dim,
|
||||
info->add_set.u.compat.flags);
|
||||
if (info->del_set.index != IPSET_INVALID_ID)
|
||||
ip_set_del(info->del_set.index, skb, par->family,
|
||||
info->del_set.u.compat.dim,
|
||||
info->del_set.u.compat.flags);
|
||||
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
static bool
|
||||
set_target_v0_checkentry(const struct xt_tgchk_param *par)
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */
|
||||
static int
|
||||
set_target_v0_checkentry(const struct xt_tgchk_param *par)
|
||||
#endif
|
||||
{
|
||||
struct xt_set_info_target_v0 *info = par->targinfo;
|
||||
ip_set_id_t index;
|
||||
|
||||
if (info->add_set.index != IPSET_INVALID_ID) {
|
||||
index = ip_set_nfnl_get_byindex(info->add_set.index);
|
||||
if (index == IPSET_INVALID_ID) {
|
||||
pr_warning("cannot find add_set index %u as target",
|
||||
info->add_set.index);
|
||||
return CHECK_FAIL; /* error */
|
||||
}
|
||||
}
|
||||
|
||||
if (info->del_set.index != IPSET_INVALID_ID) {
|
||||
index = ip_set_nfnl_get_byindex(info->del_set.index);
|
||||
if (index == IPSET_INVALID_ID) {
|
||||
pr_warning("cannot find del_set index %u as target",
|
||||
info->del_set.index);
|
||||
return CHECK_FAIL; /* error */
|
||||
}
|
||||
}
|
||||
if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0
|
||||
|| info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) {
|
||||
pr_warning("That's nasty!");
|
||||
return CHECK_FAIL; /* error */
|
||||
}
|
||||
|
||||
/* Fill out compatibility data */
|
||||
compat_flags(&info->add_set);
|
||||
compat_flags(&info->del_set);
|
||||
|
||||
return CHECK_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
set_target_v0_destroy(const struct xt_tgdtor_param *par)
|
||||
{
|
||||
const struct xt_set_info_target_v0 *info = par->targinfo;
|
||||
|
||||
if (info->add_set.index != IPSET_INVALID_ID)
|
||||
ip_set_nfnl_put(info->add_set.index);
|
||||
if (info->del_set.index != IPSET_INVALID_ID)
|
||||
ip_set_nfnl_put(info->del_set.index);
|
||||
}
|
||||
|
||||
/* Revision 1: current interface to netfilter/iptables */
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
static bool
|
||||
set_match(const struct sk_buff *skb, const struct xt_match_param *par)
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */
|
||||
static bool
|
||||
set_match(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
#endif
|
||||
{
|
||||
const struct xt_set_info_match *info = par->matchinfo;
|
||||
|
||||
return match_set(info->match_set.index, skb, par->family,
|
||||
info->match_set.dim,
|
||||
info->match_set.flags,
|
||||
info->match_set.flags & IPSET_INV_MATCH);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
static bool
|
||||
set_match_checkentry(const struct xt_mtchk_param *par)
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */
|
||||
static int
|
||||
set_match_checkentry(const struct xt_mtchk_param *par)
|
||||
#endif
|
||||
{
|
||||
struct xt_set_info_match *info = par->matchinfo;
|
||||
ip_set_id_t index;
|
||||
|
||||
index = ip_set_nfnl_get_byindex(info->match_set.index);
|
||||
|
||||
if (index == IPSET_INVALID_ID) {
|
||||
pr_warning("Cannot find set indentified by id %u to match",
|
||||
info->match_set.index);
|
||||
return CHECK_FAIL; /* error */
|
||||
}
|
||||
if (info->match_set.dim > IPSET_DIM_MAX) {
|
||||
pr_warning("That's nasty!");
|
||||
return CHECK_FAIL; /* error */
|
||||
}
|
||||
|
||||
return CHECK_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
set_match_destroy(const struct xt_mtdtor_param *par)
|
||||
{
|
||||
struct xt_set_info_match *info = par->matchinfo;
|
||||
|
||||
ip_set_nfnl_put(info->match_set.index);
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
static unsigned int
|
||||
set_target(struct sk_buff *skb, const struct xt_target_param *par)
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */
|
||||
static unsigned int
|
||||
set_target(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
#endif
|
||||
{
|
||||
const struct xt_set_info_target *info = par->targinfo;
|
||||
|
||||
if (info->add_set.index != IPSET_INVALID_ID)
|
||||
ip_set_add(info->add_set.index,
|
||||
skb, par->family,
|
||||
info->add_set.dim,
|
||||
info->add_set.flags);
|
||||
if (info->del_set.index != IPSET_INVALID_ID)
|
||||
ip_set_del(info->del_set.index,
|
||||
skb, par->family,
|
||||
info->add_set.dim,
|
||||
info->del_set.flags);
|
||||
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
static bool
|
||||
set_target_checkentry(const struct xt_tgchk_param *par)
|
||||
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */
|
||||
static int
|
||||
set_target_checkentry(const struct xt_tgchk_param *par)
|
||||
#endif
|
||||
{
|
||||
const struct xt_set_info_target *info = par->targinfo;
|
||||
ip_set_id_t index;
|
||||
|
||||
if (info->add_set.index != IPSET_INVALID_ID) {
|
||||
index = ip_set_nfnl_get_byindex(info->add_set.index);
|
||||
if (index == IPSET_INVALID_ID) {
|
||||
pr_warning("cannot find add_set index %u as target",
|
||||
info->add_set.index);
|
||||
return CHECK_FAIL; /* error */
|
||||
}
|
||||
}
|
||||
|
||||
if (info->del_set.index != IPSET_INVALID_ID) {
|
||||
index = ip_set_nfnl_get_byindex(info->del_set.index);
|
||||
if (index == IPSET_INVALID_ID) {
|
||||
pr_warning("cannot find del_set index %u as target",
|
||||
info->del_set.index);
|
||||
return CHECK_FAIL; /* error */
|
||||
}
|
||||
}
|
||||
if (info->add_set.dim > IPSET_DIM_MAX
|
||||
|| info->del_set.flags > IPSET_DIM_MAX) {
|
||||
pr_warning("That's nasty!");
|
||||
return CHECK_FAIL; /* error */
|
||||
}
|
||||
|
||||
return CHECK_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
set_target_destroy(const struct xt_tgdtor_param *par)
|
||||
{
|
||||
const struct xt_set_info_target *info = par->targinfo;
|
||||
|
||||
if (info->add_set.index != IPSET_INVALID_ID)
|
||||
ip_set_nfnl_put(info->add_set.index);
|
||||
if (info->del_set.index != IPSET_INVALID_ID)
|
||||
ip_set_nfnl_put(info->del_set.index);
|
||||
}
|
||||
|
||||
static struct xt_match set_matches[] __read_mostly = {
|
||||
{
|
||||
.name = "set",
|
||||
.family = NFPROTO_IPV4,
|
||||
.revision = 0,
|
||||
.match = set_match_v0,
|
||||
.matchsize = sizeof(struct xt_set_info_match_v0),
|
||||
.checkentry = set_match_v0_checkentry,
|
||||
.destroy = set_match_v0_destroy,
|
||||
.me = THIS_MODULE
|
||||
},
|
||||
{
|
||||
.name = "set",
|
||||
.family = NFPROTO_IPV4,
|
||||
.revision = 1,
|
||||
.match = set_match,
|
||||
.matchsize = sizeof(struct xt_set_info_match),
|
||||
.checkentry = set_match_checkentry,
|
||||
.destroy = set_match_destroy,
|
||||
.me = THIS_MODULE
|
||||
},
|
||||
{
|
||||
.name = "set",
|
||||
.family = NFPROTO_IPV6,
|
||||
.revision = 1,
|
||||
.match = set_match,
|
||||
.matchsize = sizeof(struct xt_set_info_match),
|
||||
.checkentry = set_match_checkentry,
|
||||
.destroy = set_match_destroy,
|
||||
.me = THIS_MODULE
|
||||
},
|
||||
};
|
||||
|
||||
static struct xt_target set_targets[] __read_mostly = {
|
||||
{
|
||||
.name = "SET",
|
||||
.revision = 0,
|
||||
.family = NFPROTO_IPV4,
|
||||
.target = set_target_v0,
|
||||
.targetsize = sizeof(struct xt_set_info_target_v0),
|
||||
.checkentry = set_target_v0_checkentry,
|
||||
.destroy = set_target_v0_destroy,
|
||||
.me = THIS_MODULE
|
||||
},
|
||||
{
|
||||
.name = "SET",
|
||||
.revision = 1,
|
||||
.family = NFPROTO_IPV4,
|
||||
.target = set_target,
|
||||
.targetsize = sizeof(struct xt_set_info_target),
|
||||
.checkentry = set_target_checkentry,
|
||||
.destroy = set_target_destroy,
|
||||
.me = THIS_MODULE
|
||||
},
|
||||
{
|
||||
.name = "SET",
|
||||
.revision = 1,
|
||||
.family = NFPROTO_IPV6,
|
||||
.target = set_target,
|
||||
.targetsize = sizeof(struct xt_set_info_target),
|
||||
.checkentry = set_target_checkentry,
|
||||
.destroy = set_target_destroy,
|
||||
.me = THIS_MODULE
|
||||
},
|
||||
};
|
||||
|
||||
static int __init xt_set_init(void)
|
||||
{
|
||||
int ret = xt_register_matches(set_matches, ARRAY_SIZE(set_matches));
|
||||
|
||||
if (!ret) {
|
||||
ret = xt_register_targets(set_targets,
|
||||
ARRAY_SIZE(set_targets));
|
||||
if (ret)
|
||||
xt_unregister_matches(set_matches,
|
||||
ARRAY_SIZE(set_matches));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit xt_set_fini(void)
|
||||
{
|
||||
xt_unregister_matches(set_matches, ARRAY_SIZE(set_matches));
|
||||
xt_unregister_targets(set_targets, ARRAY_SIZE(set_targets));
|
||||
}
|
||||
|
||||
module_init(xt_set_init);
|
||||
module_exit(xt_set_fini);
|
||||
55
extensions/ipset-5/xt_set.h
Normal file
55
extensions/ipset-5/xt_set.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef _XT_SET_H
|
||||
#define _XT_SET_H
|
||||
|
||||
#include "ip_set.h"
|
||||
|
||||
/* Revision 0 interface: backward compatible with netfilter/iptables */
|
||||
|
||||
/*
|
||||
* Option flags for kernel operations (xt_set_info_v0)
|
||||
*/
|
||||
#define IPSET_SRC 0x01 /* Source match/add */
|
||||
#define IPSET_DST 0x02 /* Destination match/add */
|
||||
#define IPSET_MATCH_INV 0x04 /* Inverse matching */
|
||||
|
||||
struct xt_set_info_v0 {
|
||||
ip_set_id_t index;
|
||||
union {
|
||||
__u32 flags[IPSET_DIM_MAX + 1];
|
||||
struct {
|
||||
__u32 __flags[IPSET_DIM_MAX];
|
||||
__u8 dim;
|
||||
__u8 flags;
|
||||
} compat;
|
||||
} u;
|
||||
};
|
||||
|
||||
/* match and target infos */
|
||||
struct xt_set_info_match_v0 {
|
||||
struct xt_set_info_v0 match_set;
|
||||
};
|
||||
|
||||
struct xt_set_info_target_v0 {
|
||||
struct xt_set_info_v0 add_set;
|
||||
struct xt_set_info_v0 del_set;
|
||||
};
|
||||
|
||||
/* Revision 1: current interface to netfilter/iptables */
|
||||
|
||||
struct xt_set_info {
|
||||
ip_set_id_t index;
|
||||
__u8 dim;
|
||||
__u8 flags;
|
||||
};
|
||||
|
||||
/* match and target infos */
|
||||
struct xt_set_info_match {
|
||||
struct xt_set_info match_set;
|
||||
};
|
||||
|
||||
struct xt_set_info_target {
|
||||
struct xt_set_info add_set;
|
||||
struct xt_set_info del_set;
|
||||
};
|
||||
|
||||
#endif /*_XT_SET_H*/
|
||||
Reference in New Issue
Block a user