Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6

+10210 -34
+4
include/linux/netfilter/Kbuild
··· 1 + header-y += ipset/ 2 + 1 3 header-y += nf_conntrack_common.h 2 4 header-y += nf_conntrack_ftp.h 3 5 header-y += nf_conntrack_sctp.h ··· 37 35 header-y += xt_conntrack.h 38 36 header-y += xt_cpu.h 39 37 header-y += xt_dccp.h 38 + header-y += xt_devgroup.h 40 39 header-y += xt_dscp.h 41 40 header-y += xt_esp.h 42 41 header-y += xt_hashlimit.h ··· 58 55 header-y += xt_rateest.h 59 56 header-y += xt_realm.h 60 57 header-y += xt_recent.h 58 + header-y += xt_set.h 61 59 header-y += xt_sctp.h 62 60 header-y += xt_socket.h 63 61 header-y += xt_state.h
+4
include/linux/netfilter/ipset/Kbuild
··· 1 + header-y += ip_set.h 2 + header-y += ip_set_bitmap.h 3 + header-y += ip_set_hash.h 4 + header-y += ip_set_list.h
+452
include/linux/netfilter/ipset/ip_set.h
··· 1 + #ifndef _IP_SET_H 2 + #define _IP_SET_H 3 + 4 + /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> 5 + * Patrick Schaaf <bof@bof.de> 6 + * Martin Josefsson <gandalf@wlug.westbo.se> 7 + * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 8 + * 9 + * This program is free software; you can redistribute it and/or modify 10 + * it under the terms of the GNU General Public License version 2 as 11 + * published by the Free Software Foundation. 12 + */ 13 + 14 + /* The protocol version */ 15 + #define IPSET_PROTOCOL 6 16 + 17 + /* The max length of strings including NUL: set and type identifiers */ 18 + #define IPSET_MAXNAMELEN 32 19 + 20 + /* Message types and commands */ 21 + enum ipset_cmd { 22 + IPSET_CMD_NONE, 23 + IPSET_CMD_PROTOCOL, /* 1: Return protocol version */ 24 + IPSET_CMD_CREATE, /* 2: Create a new (empty) set */ 25 + IPSET_CMD_DESTROY, /* 3: Destroy a (empty) set */ 26 + IPSET_CMD_FLUSH, /* 4: Remove all elements from a set */ 27 + IPSET_CMD_RENAME, /* 5: Rename a set */ 28 + IPSET_CMD_SWAP, /* 6: Swap two sets */ 29 + IPSET_CMD_LIST, /* 7: List sets */ 30 + IPSET_CMD_SAVE, /* 8: Save sets */ 31 + IPSET_CMD_ADD, /* 9: Add an element to a set */ 32 + IPSET_CMD_DEL, /* 10: Delete an element from a set */ 33 + IPSET_CMD_TEST, /* 11: Test an element in a set */ 34 + IPSET_CMD_HEADER, /* 12: Get set header data only */ 35 + IPSET_CMD_TYPE, /* 13: Get set type */ 36 + IPSET_MSG_MAX, /* Netlink message commands */ 37 + 38 + /* Commands in userspace: */ 39 + IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */ 40 + IPSET_CMD_HELP, /* 15: Get help */ 41 + IPSET_CMD_VERSION, /* 16: Get program version */ 42 + IPSET_CMD_QUIT, /* 17: Quit from interactive mode */ 43 + 44 + IPSET_CMD_MAX, 45 + 46 + IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */ 47 + }; 48 + 49 + /* Attributes at command level */ 50 + enum { 51 + IPSET_ATTR_UNSPEC, 52 + IPSET_ATTR_PROTOCOL, /* 1: Protocol version */ 53 + IPSET_ATTR_SETNAME, /* 2: Name of the set */ 54 + IPSET_ATTR_TYPENAME, /* 3: Typename */ 55 + IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */ 56 + IPSET_ATTR_REVISION, /* 4: Settype revision */ 57 + IPSET_ATTR_FAMILY, /* 5: Settype family */ 58 + IPSET_ATTR_FLAGS, /* 6: Flags at command level */ 59 + IPSET_ATTR_DATA, /* 7: Nested attributes */ 60 + IPSET_ATTR_ADT, /* 8: Multiple data containers */ 61 + IPSET_ATTR_LINENO, /* 9: Restore lineno */ 62 + IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */ 63 + IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */ 64 + __IPSET_ATTR_CMD_MAX, 65 + }; 66 + #define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1) 67 + 68 + /* CADT specific attributes */ 69 + enum { 70 + IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1, 71 + IPSET_ATTR_IP_FROM = IPSET_ATTR_IP, 72 + IPSET_ATTR_IP_TO, /* 2 */ 73 + IPSET_ATTR_CIDR, /* 3 */ 74 + IPSET_ATTR_PORT, /* 4 */ 75 + IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT, 76 + IPSET_ATTR_PORT_TO, /* 5 */ 77 + IPSET_ATTR_TIMEOUT, /* 6 */ 78 + IPSET_ATTR_PROTO, /* 7 */ 79 + IPSET_ATTR_CADT_FLAGS, /* 8 */ 80 + IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */ 81 + /* Reserve empty slots */ 82 + IPSET_ATTR_CADT_MAX = 16, 83 + /* Create-only specific attributes */ 84 + IPSET_ATTR_GC, 85 + IPSET_ATTR_HASHSIZE, 86 + IPSET_ATTR_MAXELEM, 87 + IPSET_ATTR_NETMASK, 88 + IPSET_ATTR_PROBES, 89 + IPSET_ATTR_RESIZE, 90 + IPSET_ATTR_SIZE, 91 + /* Kernel-only */ 92 + IPSET_ATTR_ELEMENTS, 93 + IPSET_ATTR_REFERENCES, 94 + IPSET_ATTR_MEMSIZE, 95 + 96 + __IPSET_ATTR_CREATE_MAX, 97 + }; 98 + #define IPSET_ATTR_CREATE_MAX (__IPSET_ATTR_CREATE_MAX - 1) 99 + 100 + /* ADT specific attributes */ 101 + enum { 102 + IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1, 103 + IPSET_ATTR_NAME, 104 + IPSET_ATTR_NAMEREF, 105 + IPSET_ATTR_IP2, 106 + IPSET_ATTR_CIDR2, 107 + __IPSET_ATTR_ADT_MAX, 108 + }; 109 + #define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1) 110 + 111 + /* IP specific attributes */ 112 + enum { 113 + IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1, 114 + IPSET_ATTR_IPADDR_IPV6, 115 + __IPSET_ATTR_IPADDR_MAX, 116 + }; 117 + #define IPSET_ATTR_IPADDR_MAX (__IPSET_ATTR_IPADDR_MAX - 1) 118 + 119 + /* Error codes */ 120 + enum ipset_errno { 121 + IPSET_ERR_PRIVATE = 4096, 122 + IPSET_ERR_PROTOCOL, 123 + IPSET_ERR_FIND_TYPE, 124 + IPSET_ERR_MAX_SETS, 125 + IPSET_ERR_BUSY, 126 + IPSET_ERR_EXIST_SETNAME2, 127 + IPSET_ERR_TYPE_MISMATCH, 128 + IPSET_ERR_EXIST, 129 + IPSET_ERR_INVALID_CIDR, 130 + IPSET_ERR_INVALID_NETMASK, 131 + IPSET_ERR_INVALID_FAMILY, 132 + IPSET_ERR_TIMEOUT, 133 + IPSET_ERR_REFERENCED, 134 + IPSET_ERR_IPADDR_IPV4, 135 + IPSET_ERR_IPADDR_IPV6, 136 + 137 + /* Type specific error codes */ 138 + IPSET_ERR_TYPE_SPECIFIC = 4352, 139 + }; 140 + 141 + /* Flags at command level */ 142 + enum ipset_cmd_flags { 143 + IPSET_FLAG_BIT_EXIST = 0, 144 + IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST), 145 + }; 146 + 147 + /* Flags at CADT attribute level */ 148 + enum ipset_cadt_flags { 149 + IPSET_FLAG_BIT_BEFORE = 0, 150 + IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE), 151 + }; 152 + 153 + /* Commands with settype-specific attributes */ 154 + enum ipset_adt { 155 + IPSET_ADD, 156 + IPSET_DEL, 157 + IPSET_TEST, 158 + IPSET_ADT_MAX, 159 + IPSET_CREATE = IPSET_ADT_MAX, 160 + IPSET_CADT_MAX, 161 + }; 162 + 163 + #ifdef __KERNEL__ 164 + #include <linux/ip.h> 165 + #include <linux/ipv6.h> 166 + #include <linux/netlink.h> 167 + #include <linux/netfilter.h> 168 + #include <linux/vmalloc.h> 169 + #include <net/netlink.h> 170 + 171 + /* Sets are identified by an index in kernel space. Tweak with ip_set_id_t 172 + * and IPSET_INVALID_ID if you want to increase the max number of sets. 173 + */ 174 + typedef u16 ip_set_id_t; 175 + 176 + #define IPSET_INVALID_ID 65535 177 + 178 + enum ip_set_dim { 179 + IPSET_DIM_ZERO = 0, 180 + IPSET_DIM_ONE, 181 + IPSET_DIM_TWO, 182 + IPSET_DIM_THREE, 183 + /* Max dimension in elements. 184 + * If changed, new revision of iptables match/target is required. 185 + */ 186 + IPSET_DIM_MAX = 6, 187 + }; 188 + 189 + /* Option flags for kernel operations */ 190 + enum ip_set_kopt { 191 + IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO), 192 + IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE), 193 + IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO), 194 + IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE), 195 + }; 196 + 197 + /* Set features */ 198 + enum ip_set_feature { 199 + IPSET_TYPE_IP_FLAG = 0, 200 + IPSET_TYPE_IP = (1 << IPSET_TYPE_IP_FLAG), 201 + IPSET_TYPE_PORT_FLAG = 1, 202 + IPSET_TYPE_PORT = (1 << IPSET_TYPE_PORT_FLAG), 203 + IPSET_TYPE_MAC_FLAG = 2, 204 + IPSET_TYPE_MAC = (1 << IPSET_TYPE_MAC_FLAG), 205 + IPSET_TYPE_IP2_FLAG = 3, 206 + IPSET_TYPE_IP2 = (1 << IPSET_TYPE_IP2_FLAG), 207 + IPSET_TYPE_NAME_FLAG = 4, 208 + IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG), 209 + /* Strictly speaking not a feature, but a flag for dumping: 210 + * this settype must be dumped last */ 211 + IPSET_DUMP_LAST_FLAG = 7, 212 + IPSET_DUMP_LAST = (1 << IPSET_DUMP_LAST_FLAG), 213 + }; 214 + 215 + struct ip_set; 216 + 217 + typedef int (*ipset_adtfn)(struct ip_set *set, void *value, u32 timeout); 218 + 219 + /* Set type, variant-specific part */ 220 + struct ip_set_type_variant { 221 + /* Kernelspace: test/add/del entries 222 + * returns negative error code, 223 + * zero for no match/success to add/delete 224 + * positive for matching element */ 225 + int (*kadt)(struct ip_set *set, const struct sk_buff * skb, 226 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags); 227 + 228 + /* Userspace: test/add/del entries 229 + * returns negative error code, 230 + * zero for no match/success to add/delete 231 + * positive for matching element */ 232 + int (*uadt)(struct ip_set *set, struct nlattr *tb[], 233 + enum ipset_adt adt, u32 *lineno, u32 flags); 234 + 235 + /* Low level add/del/test functions */ 236 + ipset_adtfn adt[IPSET_ADT_MAX]; 237 + 238 + /* When adding entries and set is full, try to resize the set */ 239 + int (*resize)(struct ip_set *set, bool retried); 240 + /* Destroy the set */ 241 + void (*destroy)(struct ip_set *set); 242 + /* Flush the elements */ 243 + void (*flush)(struct ip_set *set); 244 + /* Expire entries before listing */ 245 + void (*expire)(struct ip_set *set); 246 + /* List set header data */ 247 + int (*head)(struct ip_set *set, struct sk_buff *skb); 248 + /* List elements */ 249 + int (*list)(const struct ip_set *set, struct sk_buff *skb, 250 + struct netlink_callback *cb); 251 + 252 + /* Return true if "b" set is the same as "a" 253 + * according to the create set parameters */ 254 + bool (*same_set)(const struct ip_set *a, const struct ip_set *b); 255 + }; 256 + 257 + /* The core set type structure */ 258 + struct ip_set_type { 259 + struct list_head list; 260 + 261 + /* Typename */ 262 + char name[IPSET_MAXNAMELEN]; 263 + /* Protocol version */ 264 + u8 protocol; 265 + /* Set features to control swapping */ 266 + u8 features; 267 + /* Set type dimension */ 268 + u8 dimension; 269 + /* Supported family: may be AF_UNSPEC for both AF_INET/AF_INET6 */ 270 + u8 family; 271 + /* Type revision */ 272 + u8 revision; 273 + 274 + /* Create set */ 275 + int (*create)(struct ip_set *set, struct nlattr *tb[], u32 flags); 276 + 277 + /* Attribute policies */ 278 + const struct nla_policy create_policy[IPSET_ATTR_CREATE_MAX + 1]; 279 + const struct nla_policy adt_policy[IPSET_ATTR_ADT_MAX + 1]; 280 + 281 + /* Set this to THIS_MODULE if you are a module, otherwise NULL */ 282 + struct module *me; 283 + }; 284 + 285 + /* register and unregister set type */ 286 + extern int ip_set_type_register(struct ip_set_type *set_type); 287 + extern void ip_set_type_unregister(struct ip_set_type *set_type); 288 + 289 + /* A generic IP set */ 290 + struct ip_set { 291 + /* The name of the set */ 292 + char name[IPSET_MAXNAMELEN]; 293 + /* Lock protecting the set data */ 294 + rwlock_t lock; 295 + /* References to the set */ 296 + atomic_t ref; 297 + /* The core set type */ 298 + struct ip_set_type *type; 299 + /* The type variant doing the real job */ 300 + const struct ip_set_type_variant *variant; 301 + /* The actual INET family of the set */ 302 + u8 family; 303 + /* The type specific data */ 304 + void *data; 305 + }; 306 + 307 + /* register and unregister set references */ 308 + extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set); 309 + extern void ip_set_put_byindex(ip_set_id_t index); 310 + extern const char * ip_set_name_byindex(ip_set_id_t index); 311 + extern ip_set_id_t ip_set_nfnl_get(const char *name); 312 + extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index); 313 + extern void ip_set_nfnl_put(ip_set_id_t index); 314 + 315 + /* API for iptables set match, and SET target */ 316 + extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb, 317 + u8 family, u8 dim, u8 flags); 318 + extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb, 319 + u8 family, u8 dim, u8 flags); 320 + extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb, 321 + u8 family, u8 dim, u8 flags); 322 + 323 + /* Utility functions */ 324 + extern void * ip_set_alloc(size_t size); 325 + extern void ip_set_free(void *members); 326 + extern int ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr); 327 + extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr); 328 + 329 + static inline int 330 + ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr) 331 + { 332 + __be32 ip; 333 + int ret = ip_set_get_ipaddr4(nla, &ip); 334 + 335 + if (ret) 336 + return ret; 337 + *ipaddr = ntohl(ip); 338 + return 0; 339 + } 340 + 341 + /* Ignore IPSET_ERR_EXIST errors if asked to do so? */ 342 + static inline bool 343 + ip_set_eexist(int ret, u32 flags) 344 + { 345 + return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST); 346 + } 347 + 348 + /* Check the NLA_F_NET_BYTEORDER flag */ 349 + static inline bool 350 + ip_set_attr_netorder(struct nlattr *tb[], int type) 351 + { 352 + return tb[type] && (tb[type]->nla_type & NLA_F_NET_BYTEORDER); 353 + } 354 + 355 + static inline bool 356 + ip_set_optattr_netorder(struct nlattr *tb[], int type) 357 + { 358 + return !tb[type] || (tb[type]->nla_type & NLA_F_NET_BYTEORDER); 359 + } 360 + 361 + /* Useful converters */ 362 + static inline u32 363 + ip_set_get_h32(const struct nlattr *attr) 364 + { 365 + return ntohl(nla_get_be32(attr)); 366 + } 367 + 368 + static inline u16 369 + ip_set_get_h16(const struct nlattr *attr) 370 + { 371 + return ntohs(nla_get_be16(attr)); 372 + } 373 + 374 + #define ipset_nest_start(skb, attr) nla_nest_start(skb, attr | NLA_F_NESTED) 375 + #define ipset_nest_end(skb, start) nla_nest_end(skb, start) 376 + 377 + #define NLA_PUT_IPADDR4(skb, type, ipaddr) \ 378 + do { \ 379 + struct nlattr *__nested = ipset_nest_start(skb, type); \ 380 + \ 381 + if (!__nested) \ 382 + goto nla_put_failure; \ 383 + NLA_PUT_NET32(skb, IPSET_ATTR_IPADDR_IPV4, ipaddr); \ 384 + ipset_nest_end(skb, __nested); \ 385 + } while (0) 386 + 387 + #define NLA_PUT_IPADDR6(skb, type, ipaddrptr) \ 388 + do { \ 389 + struct nlattr *__nested = ipset_nest_start(skb, type); \ 390 + \ 391 + if (!__nested) \ 392 + goto nla_put_failure; \ 393 + NLA_PUT(skb, IPSET_ATTR_IPADDR_IPV6, \ 394 + sizeof(struct in6_addr), ipaddrptr); \ 395 + ipset_nest_end(skb, __nested); \ 396 + } while (0) 397 + 398 + /* Get address from skbuff */ 399 + static inline __be32 400 + ip4addr(const struct sk_buff *skb, bool src) 401 + { 402 + return src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr; 403 + } 404 + 405 + static inline void 406 + ip4addrptr(const struct sk_buff *skb, bool src, __be32 *addr) 407 + { 408 + *addr = src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr; 409 + } 410 + 411 + static inline void 412 + ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr) 413 + { 414 + memcpy(addr, src ? &ipv6_hdr(skb)->saddr : &ipv6_hdr(skb)->daddr, 415 + sizeof(*addr)); 416 + } 417 + 418 + /* Calculate the bytes required to store the inclusive range of a-b */ 419 + static inline int 420 + bitmap_bytes(u32 a, u32 b) 421 + { 422 + return 4 * ((((b - a + 8) / 8) + 3) / 4); 423 + } 424 + 425 + /* Interface to iptables/ip6tables */ 426 + 427 + #define SO_IP_SET 83 428 + 429 + union ip_set_name_index { 430 + char name[IPSET_MAXNAMELEN]; 431 + ip_set_id_t index; 432 + }; 433 + 434 + #define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */ 435 + struct ip_set_req_get_set { 436 + unsigned op; 437 + unsigned version; 438 + union ip_set_name_index set; 439 + }; 440 + 441 + #define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */ 442 + /* Uses ip_set_req_get_set */ 443 + 444 + #define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */ 445 + struct ip_set_req_version { 446 + unsigned op; 447 + unsigned version; 448 + }; 449 + 450 + #endif /* __KERNEL__ */ 451 + 452 + #endif /*_IP_SET_H */
+1074
include/linux/netfilter/ipset/ip_set_ahash.h
··· 1 + #ifndef _IP_SET_AHASH_H 2 + #define _IP_SET_AHASH_H 3 + 4 + #include <linux/rcupdate.h> 5 + #include <linux/jhash.h> 6 + #include <linux/netfilter/ipset/ip_set_timeout.h> 7 + 8 + /* Hashing which uses arrays to resolve clashing. The hash table is resized 9 + * (doubled) when searching becomes too long. 10 + * Internally jhash is used with the assumption that the size of the 11 + * stored data is a multiple of sizeof(u32). If storage supports timeout, 12 + * the timeout field must be the last one in the data structure - that field 13 + * is ignored when computing the hash key. 14 + * 15 + * Readers and resizing 16 + * 17 + * Resizing can be triggered by userspace command only, and those 18 + * are serialized by the nfnl mutex. During resizing the set is 19 + * read-locked, so the only possible concurrent operations are 20 + * the kernel side readers. Those must be protected by proper RCU locking. 21 + */ 22 + 23 + /* Number of elements to store in an initial array block */ 24 + #define AHASH_INIT_SIZE 4 25 + /* Max number of elements to store in an array block */ 26 + #define AHASH_MAX_SIZE (3*4) 27 + 28 + /* A hash bucket */ 29 + struct hbucket { 30 + void *value; /* the array of the values */ 31 + u8 size; /* size of the array */ 32 + u8 pos; /* position of the first free entry */ 33 + }; 34 + 35 + /* The hash table: the table size stored here in order to make resizing easy */ 36 + struct htable { 37 + u8 htable_bits; /* size of hash table == 2^htable_bits */ 38 + struct hbucket bucket[0]; /* hashtable buckets */ 39 + }; 40 + 41 + #define hbucket(h, i) &((h)->bucket[i]) 42 + 43 + /* Book-keeping of the prefixes added to the set */ 44 + struct ip_set_hash_nets { 45 + u8 cidr; /* the different cidr values in the set */ 46 + u32 nets; /* number of elements per cidr */ 47 + }; 48 + 49 + /* The generic ip_set hash structure */ 50 + struct ip_set_hash { 51 + struct htable *table; /* the hash table */ 52 + u32 maxelem; /* max elements in the hash */ 53 + u32 elements; /* current element (vs timeout) */ 54 + u32 initval; /* random jhash init value */ 55 + u32 timeout; /* timeout value, if enabled */ 56 + struct timer_list gc; /* garbage collection when timeout enabled */ 57 + #ifdef IP_SET_HASH_WITH_NETMASK 58 + u8 netmask; /* netmask value for subnets to store */ 59 + #endif 60 + #ifdef IP_SET_HASH_WITH_NETS 61 + struct ip_set_hash_nets nets[0]; /* book-keeping of prefixes */ 62 + #endif 63 + }; 64 + 65 + /* Compute htable_bits from the user input parameter hashsize */ 66 + static u8 67 + htable_bits(u32 hashsize) 68 + { 69 + /* Assume that hashsize == 2^htable_bits */ 70 + u8 bits = fls(hashsize - 1); 71 + if (jhash_size(bits) != hashsize) 72 + /* Round up to the first 2^n value */ 73 + bits = fls(hashsize); 74 + 75 + return bits; 76 + } 77 + 78 + #ifdef IP_SET_HASH_WITH_NETS 79 + 80 + #define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128) 81 + 82 + /* Network cidr size book keeping when the hash stores different 83 + * sized networks */ 84 + static void 85 + add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask) 86 + { 87 + u8 i; 88 + 89 + ++h->nets[cidr-1].nets; 90 + 91 + pr_debug("add_cidr added %u: %u\n", cidr, h->nets[cidr-1].nets); 92 + 93 + if (h->nets[cidr-1].nets > 1) 94 + return; 95 + 96 + /* New cidr size */ 97 + for (i = 0; i < host_mask && h->nets[i].cidr; i++) { 98 + /* Add in increasing prefix order, so larger cidr first */ 99 + if (h->nets[i].cidr < cidr) 100 + swap(h->nets[i].cidr, cidr); 101 + } 102 + if (i < host_mask) 103 + h->nets[i].cidr = cidr; 104 + } 105 + 106 + static void 107 + del_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask) 108 + { 109 + u8 i; 110 + 111 + --h->nets[cidr-1].nets; 112 + 113 + pr_debug("del_cidr deleted %u: %u\n", cidr, h->nets[cidr-1].nets); 114 + 115 + if (h->nets[cidr-1].nets != 0) 116 + return; 117 + 118 + /* All entries with this cidr size deleted, so cleanup h->cidr[] */ 119 + for (i = 0; i < host_mask - 1 && h->nets[i].cidr; i++) { 120 + if (h->nets[i].cidr == cidr) 121 + h->nets[i].cidr = cidr = h->nets[i+1].cidr; 122 + } 123 + h->nets[i - 1].cidr = 0; 124 + } 125 + #endif 126 + 127 + /* Destroy the hashtable part of the set */ 128 + static void 129 + ahash_destroy(struct htable *t) 130 + { 131 + struct hbucket *n; 132 + u32 i; 133 + 134 + for (i = 0; i < jhash_size(t->htable_bits); i++) { 135 + n = hbucket(t, i); 136 + if (n->size) 137 + /* FIXME: use slab cache */ 138 + kfree(n->value); 139 + } 140 + 141 + ip_set_free(t); 142 + } 143 + 144 + /* Calculate the actual memory size of the set data */ 145 + static size_t 146 + ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 host_mask) 147 + { 148 + u32 i; 149 + struct htable *t = h->table; 150 + size_t memsize = sizeof(*h) 151 + + sizeof(*t) 152 + #ifdef IP_SET_HASH_WITH_NETS 153 + + sizeof(struct ip_set_hash_nets) * host_mask 154 + #endif 155 + + jhash_size(t->htable_bits) * sizeof(struct hbucket); 156 + 157 + for (i = 0; i < jhash_size(t->htable_bits); i++) 158 + memsize += t->bucket[i].size * dsize; 159 + 160 + return memsize; 161 + } 162 + 163 + /* Flush a hash type of set: destroy all elements */ 164 + static void 165 + ip_set_hash_flush(struct ip_set *set) 166 + { 167 + struct ip_set_hash *h = set->data; 168 + struct htable *t = h->table; 169 + struct hbucket *n; 170 + u32 i; 171 + 172 + for (i = 0; i < jhash_size(t->htable_bits); i++) { 173 + n = hbucket(t, i); 174 + if (n->size) { 175 + n->size = n->pos = 0; 176 + /* FIXME: use slab cache */ 177 + kfree(n->value); 178 + } 179 + } 180 + #ifdef IP_SET_HASH_WITH_NETS 181 + memset(h->nets, 0, sizeof(struct ip_set_hash_nets) 182 + * SET_HOST_MASK(set->family)); 183 + #endif 184 + h->elements = 0; 185 + } 186 + 187 + /* Destroy a hash type of set */ 188 + static void 189 + ip_set_hash_destroy(struct ip_set *set) 190 + { 191 + struct ip_set_hash *h = set->data; 192 + 193 + if (with_timeout(h->timeout)) 194 + del_timer_sync(&h->gc); 195 + 196 + ahash_destroy(h->table); 197 + kfree(h); 198 + 199 + set->data = NULL; 200 + } 201 + 202 + #define HKEY(data, initval, htable_bits) \ 203 + (jhash2((u32 *)(data), sizeof(struct type_pf_elem)/sizeof(u32), initval) \ 204 + & jhash_mask(htable_bits)) 205 + 206 + #endif /* _IP_SET_AHASH_H */ 207 + 208 + #define CONCAT(a, b, c) a##b##c 209 + #define TOKEN(a, b, c) CONCAT(a, b, c) 210 + 211 + /* Type/family dependent function prototypes */ 212 + 213 + #define type_pf_data_equal TOKEN(TYPE, PF, _data_equal) 214 + #define type_pf_data_isnull TOKEN(TYPE, PF, _data_isnull) 215 + #define type_pf_data_copy TOKEN(TYPE, PF, _data_copy) 216 + #define type_pf_data_zero_out TOKEN(TYPE, PF, _data_zero_out) 217 + #define type_pf_data_netmask TOKEN(TYPE, PF, _data_netmask) 218 + #define type_pf_data_list TOKEN(TYPE, PF, _data_list) 219 + #define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist) 220 + 221 + #define type_pf_elem TOKEN(TYPE, PF, _elem) 222 + #define type_pf_telem TOKEN(TYPE, PF, _telem) 223 + #define type_pf_data_timeout TOKEN(TYPE, PF, _data_timeout) 224 + #define type_pf_data_expired TOKEN(TYPE, PF, _data_expired) 225 + #define type_pf_data_timeout_set TOKEN(TYPE, PF, _data_timeout_set) 226 + 227 + #define type_pf_elem_add TOKEN(TYPE, PF, _elem_add) 228 + #define type_pf_add TOKEN(TYPE, PF, _add) 229 + #define type_pf_del TOKEN(TYPE, PF, _del) 230 + #define type_pf_test_cidrs TOKEN(TYPE, PF, _test_cidrs) 231 + #define type_pf_test TOKEN(TYPE, PF, _test) 232 + 233 + #define type_pf_elem_tadd TOKEN(TYPE, PF, _elem_tadd) 234 + #define type_pf_del_telem TOKEN(TYPE, PF, _ahash_del_telem) 235 + #define type_pf_expire TOKEN(TYPE, PF, _expire) 236 + #define type_pf_tadd TOKEN(TYPE, PF, _tadd) 237 + #define type_pf_tdel TOKEN(TYPE, PF, _tdel) 238 + #define type_pf_ttest_cidrs TOKEN(TYPE, PF, _ahash_ttest_cidrs) 239 + #define type_pf_ttest TOKEN(TYPE, PF, _ahash_ttest) 240 + 241 + #define type_pf_resize TOKEN(TYPE, PF, _resize) 242 + #define type_pf_tresize TOKEN(TYPE, PF, _tresize) 243 + #define type_pf_flush ip_set_hash_flush 244 + #define type_pf_destroy ip_set_hash_destroy 245 + #define type_pf_head TOKEN(TYPE, PF, _head) 246 + #define type_pf_list TOKEN(TYPE, PF, _list) 247 + #define type_pf_tlist TOKEN(TYPE, PF, _tlist) 248 + #define type_pf_same_set TOKEN(TYPE, PF, _same_set) 249 + #define type_pf_kadt TOKEN(TYPE, PF, _kadt) 250 + #define type_pf_uadt TOKEN(TYPE, PF, _uadt) 251 + #define type_pf_gc TOKEN(TYPE, PF, _gc) 252 + #define type_pf_gc_init TOKEN(TYPE, PF, _gc_init) 253 + #define type_pf_variant TOKEN(TYPE, PF, _variant) 254 + #define type_pf_tvariant TOKEN(TYPE, PF, _tvariant) 255 + 256 + /* Flavour without timeout */ 257 + 258 + /* Get the ith element from the array block n */ 259 + #define ahash_data(n, i) \ 260 + ((struct type_pf_elem *)((n)->value) + (i)) 261 + 262 + /* Add an element to the hash table when resizing the set: 263 + * we spare the maintenance of the internal counters. */ 264 + static int 265 + type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value) 266 + { 267 + if (n->pos >= n->size) { 268 + void *tmp; 269 + 270 + if (n->size >= AHASH_MAX_SIZE) 271 + /* Trigger rehashing */ 272 + return -EAGAIN; 273 + 274 + tmp = kzalloc((n->size + AHASH_INIT_SIZE) 275 + * sizeof(struct type_pf_elem), 276 + GFP_ATOMIC); 277 + if (!tmp) 278 + return -ENOMEM; 279 + if (n->size) { 280 + memcpy(tmp, n->value, 281 + sizeof(struct type_pf_elem) * n->size); 282 + kfree(n->value); 283 + } 284 + n->value = tmp; 285 + n->size += AHASH_INIT_SIZE; 286 + } 287 + type_pf_data_copy(ahash_data(n, n->pos++), value); 288 + return 0; 289 + } 290 + 291 + /* Resize a hash: create a new hash table with doubling the hashsize 292 + * and inserting the elements to it. Repeat until we succeed or 293 + * fail due to memory pressures. */ 294 + static int 295 + type_pf_resize(struct ip_set *set, bool retried) 296 + { 297 + struct ip_set_hash *h = set->data; 298 + struct htable *t, *orig = h->table; 299 + u8 htable_bits = orig->htable_bits; 300 + const struct type_pf_elem *data; 301 + struct hbucket *n, *m; 302 + u32 i, j; 303 + int ret; 304 + 305 + retry: 306 + ret = 0; 307 + htable_bits++; 308 + pr_debug("attempt to resize set %s from %u to %u, t %p\n", 309 + set->name, orig->htable_bits, htable_bits, orig); 310 + if (!htable_bits) 311 + /* In case we have plenty of memory :-) */ 312 + return -IPSET_ERR_HASH_FULL; 313 + t = ip_set_alloc(sizeof(*t) 314 + + jhash_size(htable_bits) * sizeof(struct hbucket)); 315 + if (!t) 316 + return -ENOMEM; 317 + t->htable_bits = htable_bits; 318 + 319 + read_lock_bh(&set->lock); 320 + for (i = 0; i < jhash_size(orig->htable_bits); i++) { 321 + n = hbucket(orig, i); 322 + for (j = 0; j < n->pos; j++) { 323 + data = ahash_data(n, j); 324 + m = hbucket(t, HKEY(data, h->initval, htable_bits)); 325 + ret = type_pf_elem_add(m, data); 326 + if (ret < 0) { 327 + read_unlock_bh(&set->lock); 328 + ahash_destroy(t); 329 + if (ret == -EAGAIN) 330 + goto retry; 331 + return ret; 332 + } 333 + } 334 + } 335 + 336 + rcu_assign_pointer(h->table, t); 337 + read_unlock_bh(&set->lock); 338 + 339 + /* Give time to other readers of the set */ 340 + synchronize_rcu_bh(); 341 + 342 + pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name, 343 + orig->htable_bits, orig, t->htable_bits, t); 344 + ahash_destroy(orig); 345 + 346 + return 0; 347 + } 348 + 349 + /* Add an element to a hash and update the internal counters when succeeded, 350 + * otherwise report the proper error code. */ 351 + static int 352 + type_pf_add(struct ip_set *set, void *value, u32 timeout) 353 + { 354 + struct ip_set_hash *h = set->data; 355 + struct htable *t; 356 + const struct type_pf_elem *d = value; 357 + struct hbucket *n; 358 + int i, ret = 0; 359 + u32 key; 360 + 361 + if (h->elements >= h->maxelem) 362 + return -IPSET_ERR_HASH_FULL; 363 + 364 + rcu_read_lock_bh(); 365 + t = rcu_dereference_bh(h->table); 366 + key = HKEY(value, h->initval, t->htable_bits); 367 + n = hbucket(t, key); 368 + for (i = 0; i < n->pos; i++) 369 + if (type_pf_data_equal(ahash_data(n, i), d)) { 370 + ret = -IPSET_ERR_EXIST; 371 + goto out; 372 + } 373 + 374 + ret = type_pf_elem_add(n, value); 375 + if (ret != 0) 376 + goto out; 377 + 378 + #ifdef IP_SET_HASH_WITH_NETS 379 + add_cidr(h, d->cidr, HOST_MASK); 380 + #endif 381 + h->elements++; 382 + out: 383 + rcu_read_unlock_bh(); 384 + return ret; 385 + } 386 + 387 + /* Delete an element from the hash: swap it with the last element 388 + * and free up space if possible. 389 + */ 390 + static int 391 + type_pf_del(struct ip_set *set, void *value, u32 timeout) 392 + { 393 + struct ip_set_hash *h = set->data; 394 + struct htable *t = h->table; 395 + const struct type_pf_elem *d = value; 396 + struct hbucket *n; 397 + int i; 398 + struct type_pf_elem *data; 399 + u32 key; 400 + 401 + key = HKEY(value, h->initval, t->htable_bits); 402 + n = hbucket(t, key); 403 + for (i = 0; i < n->pos; i++) { 404 + data = ahash_data(n, i); 405 + if (!type_pf_data_equal(data, d)) 406 + continue; 407 + if (i != n->pos - 1) 408 + /* Not last one */ 409 + type_pf_data_copy(data, ahash_data(n, n->pos - 1)); 410 + 411 + n->pos--; 412 + h->elements--; 413 + #ifdef IP_SET_HASH_WITH_NETS 414 + del_cidr(h, d->cidr, HOST_MASK); 415 + #endif 416 + if (n->pos + AHASH_INIT_SIZE < n->size) { 417 + void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) 418 + * sizeof(struct type_pf_elem), 419 + GFP_ATOMIC); 420 + if (!tmp) 421 + return 0; 422 + n->size -= AHASH_INIT_SIZE; 423 + memcpy(tmp, n->value, 424 + n->size * sizeof(struct type_pf_elem)); 425 + kfree(n->value); 426 + n->value = tmp; 427 + } 428 + return 0; 429 + } 430 + 431 + return -IPSET_ERR_EXIST; 432 + } 433 + 434 + #ifdef IP_SET_HASH_WITH_NETS 435 + 436 + /* Special test function which takes into account the different network 437 + * sizes added to the set */ 438 + static int 439 + type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout) 440 + { 441 + struct ip_set_hash *h = set->data; 442 + struct htable *t = h->table; 443 + struct hbucket *n; 444 + const struct type_pf_elem *data; 445 + int i, j = 0; 446 + u32 key; 447 + u8 host_mask = SET_HOST_MASK(set->family); 448 + 449 + pr_debug("test by nets\n"); 450 + for (; j < host_mask && h->nets[j].cidr; j++) { 451 + type_pf_data_netmask(d, h->nets[j].cidr); 452 + key = HKEY(d, h->initval, t->htable_bits); 453 + n = hbucket(t, key); 454 + for (i = 0; i < n->pos; i++) { 455 + data = ahash_data(n, i); 456 + if (type_pf_data_equal(data, d)) 457 + return 1; 458 + } 459 + } 460 + return 0; 461 + } 462 + #endif 463 + 464 + /* Test whether the element is added to the set */ 465 + static int 466 + type_pf_test(struct ip_set *set, void *value, u32 timeout) 467 + { 468 + struct ip_set_hash *h = set->data; 469 + struct htable *t = h->table; 470 + struct type_pf_elem *d = value; 471 + struct hbucket *n; 472 + const struct type_pf_elem *data; 473 + int i; 474 + u32 key; 475 + 476 + #ifdef IP_SET_HASH_WITH_NETS 477 + /* If we test an IP address and not a network address, 478 + * try all possible network sizes */ 479 + if (d->cidr == SET_HOST_MASK(set->family)) 480 + return type_pf_test_cidrs(set, d, timeout); 481 + #endif 482 + 483 + key = HKEY(d, h->initval, t->htable_bits); 484 + n = hbucket(t, key); 485 + for (i = 0; i < n->pos; i++) { 486 + data = ahash_data(n, i); 487 + if (type_pf_data_equal(data, d)) 488 + return 1; 489 + } 490 + return 0; 491 + } 492 + 493 + /* Reply a HEADER request: fill out the header part of the set */ 494 + static int 495 + type_pf_head(struct ip_set *set, struct sk_buff *skb) 496 + { 497 + const struct ip_set_hash *h = set->data; 498 + struct nlattr *nested; 499 + size_t memsize; 500 + 501 + read_lock_bh(&set->lock); 502 + memsize = ahash_memsize(h, with_timeout(h->timeout) 503 + ? sizeof(struct type_pf_telem) 504 + : sizeof(struct type_pf_elem), 505 + set->family == AF_INET ? 32 : 128); 506 + read_unlock_bh(&set->lock); 507 + 508 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 509 + if (!nested) 510 + goto nla_put_failure; 511 + NLA_PUT_NET32(skb, IPSET_ATTR_HASHSIZE, 512 + htonl(jhash_size(h->table->htable_bits))); 513 + NLA_PUT_NET32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem)); 514 + #ifdef IP_SET_HASH_WITH_NETMASK 515 + if (h->netmask != HOST_MASK) 516 + NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, h->netmask); 517 + #endif 518 + NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, 519 + htonl(atomic_read(&set->ref) - 1)); 520 + NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)); 521 + if (with_timeout(h->timeout)) 522 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(h->timeout)); 523 + ipset_nest_end(skb, nested); 524 + 525 + return 0; 526 + nla_put_failure: 527 + return -EMSGSIZE; 528 + } 529 + 530 + /* Reply a LIST/SAVE request: dump the elements of the specified set */ 531 + static int 532 + type_pf_list(const struct ip_set *set, 533 + struct sk_buff *skb, struct netlink_callback *cb) 534 + { 535 + const struct ip_set_hash *h = set->data; 536 + const struct htable *t = h->table; 537 + struct nlattr *atd, *nested; 538 + const struct hbucket *n; 539 + const struct type_pf_elem *data; 540 + u32 first = cb->args[2]; 541 + /* We assume that one hash bucket fills into one page */ 542 + void *incomplete; 543 + int i; 544 + 545 + atd = ipset_nest_start(skb, IPSET_ATTR_ADT); 546 + if (!atd) 547 + return -EMSGSIZE; 548 + pr_debug("list hash set %s\n", set->name); 549 + for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) { 550 + incomplete = skb_tail_pointer(skb); 551 + n = hbucket(t, cb->args[2]); 552 + pr_debug("cb->args[2]: %lu, t %p n %p\n", cb->args[2], t, n); 553 + for (i = 0; i < n->pos; i++) { 554 + data = ahash_data(n, i); 555 + pr_debug("list hash %lu hbucket %p i %u, data %p\n", 556 + cb->args[2], n, i, data); 557 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 558 + if (!nested) { 559 + if (cb->args[2] == first) { 560 + nla_nest_cancel(skb, atd); 561 + return -EMSGSIZE; 562 + } else 563 + goto nla_put_failure; 564 + } 565 + if (type_pf_data_list(skb, data)) 566 + goto nla_put_failure; 567 + ipset_nest_end(skb, nested); 568 + } 569 + } 570 + ipset_nest_end(skb, atd); 571 + /* Set listing finished */ 572 + cb->args[2] = 0; 573 + 574 + return 0; 575 + 576 + nla_put_failure: 577 + nlmsg_trim(skb, incomplete); 578 + ipset_nest_end(skb, atd); 579 + if (unlikely(first == cb->args[2])) { 580 + pr_warning("Can't list set %s: one bucket does not fit into " 581 + "a message. Please report it!\n", set->name); 582 + cb->args[2] = 0; 583 + return -EMSGSIZE; 584 + } 585 + return 0; 586 + } 587 + 588 + static int 589 + type_pf_kadt(struct ip_set *set, const struct sk_buff * skb, 590 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags); 591 + static int 592 + type_pf_uadt(struct ip_set *set, struct nlattr *tb[], 593 + enum ipset_adt adt, u32 *lineno, u32 flags); 594 + 595 + static const struct ip_set_type_variant type_pf_variant = { 596 + .kadt = type_pf_kadt, 597 + .uadt = type_pf_uadt, 598 + .adt = { 599 + [IPSET_ADD] = type_pf_add, 600 + [IPSET_DEL] = type_pf_del, 601 + [IPSET_TEST] = type_pf_test, 602 + }, 603 + .destroy = type_pf_destroy, 604 + .flush = type_pf_flush, 605 + .head = type_pf_head, 606 + .list = type_pf_list, 607 + .resize = type_pf_resize, 608 + .same_set = type_pf_same_set, 609 + }; 610 + 611 + /* Flavour with timeout support */ 612 + 613 + #define ahash_tdata(n, i) \ 614 + (struct type_pf_elem *)((struct type_pf_telem *)((n)->value) + (i)) 615 + 616 + static inline u32 617 + type_pf_data_timeout(const struct type_pf_elem *data) 618 + { 619 + const struct type_pf_telem *tdata = 620 + (const struct type_pf_telem *) data; 621 + 622 + return tdata->timeout; 623 + } 624 + 625 + static inline bool 626 + type_pf_data_expired(const struct type_pf_elem *data) 627 + { 628 + const struct type_pf_telem *tdata = 629 + (const struct type_pf_telem *) data; 630 + 631 + return ip_set_timeout_expired(tdata->timeout); 632 + } 633 + 634 + static inline void 635 + type_pf_data_timeout_set(struct type_pf_elem *data, u32 timeout) 636 + { 637 + struct type_pf_telem *tdata = (struct type_pf_telem *) data; 638 + 639 + tdata->timeout = ip_set_timeout_set(timeout); 640 + } 641 + 642 + static int 643 + type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value, 644 + u32 timeout) 645 + { 646 + struct type_pf_elem *data; 647 + 648 + if (n->pos >= n->size) { 649 + void *tmp; 650 + 651 + if (n->size >= AHASH_MAX_SIZE) 652 + /* Trigger rehashing */ 653 + return -EAGAIN; 654 + 655 + tmp = kzalloc((n->size + AHASH_INIT_SIZE) 656 + * sizeof(struct type_pf_telem), 657 + GFP_ATOMIC); 658 + if (!tmp) 659 + return -ENOMEM; 660 + if (n->size) { 661 + memcpy(tmp, n->value, 662 + sizeof(struct type_pf_telem) * n->size); 663 + kfree(n->value); 664 + } 665 + n->value = tmp; 666 + n->size += AHASH_INIT_SIZE; 667 + } 668 + data = ahash_tdata(n, n->pos++); 669 + type_pf_data_copy(data, value); 670 + type_pf_data_timeout_set(data, timeout); 671 + return 0; 672 + } 673 + 674 + /* Delete expired elements from the hashtable */ 675 + static void 676 + type_pf_expire(struct ip_set_hash *h) 677 + { 678 + struct htable *t = h->table; 679 + struct hbucket *n; 680 + struct type_pf_elem *data; 681 + u32 i; 682 + int j; 683 + 684 + for (i = 0; i < jhash_size(t->htable_bits); i++) { 685 + n = hbucket(t, i); 686 + for (j = 0; j < n->pos; j++) { 687 + data = ahash_tdata(n, j); 688 + if (type_pf_data_expired(data)) { 689 + pr_debug("expired %u/%u\n", i, j); 690 + #ifdef IP_SET_HASH_WITH_NETS 691 + del_cidr(h, data->cidr, HOST_MASK); 692 + #endif 693 + if (j != n->pos - 1) 694 + /* Not last one */ 695 + type_pf_data_copy(data, 696 + ahash_tdata(n, n->pos - 1)); 697 + n->pos--; 698 + h->elements--; 699 + } 700 + } 701 + if (n->pos + AHASH_INIT_SIZE < n->size) { 702 + void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) 703 + * sizeof(struct type_pf_telem), 704 + GFP_ATOMIC); 705 + if (!tmp) 706 + /* Still try to delete expired elements */ 707 + continue; 708 + n->size -= AHASH_INIT_SIZE; 709 + memcpy(tmp, n->value, 710 + n->size * sizeof(struct type_pf_telem)); 711 + kfree(n->value); 712 + n->value = tmp; 713 + } 714 + } 715 + } 716 + 717 + static int 718 + type_pf_tresize(struct ip_set *set, bool retried) 719 + { 720 + struct ip_set_hash *h = set->data; 721 + struct htable *t, *orig = h->table; 722 + u8 htable_bits = orig->htable_bits; 723 + const struct type_pf_elem *data; 724 + struct hbucket *n, *m; 725 + u32 i, j; 726 + int ret; 727 + 728 + /* Try to cleanup once */ 729 + if (!retried) { 730 + i = h->elements; 731 + write_lock_bh(&set->lock); 732 + type_pf_expire(set->data); 733 + write_unlock_bh(&set->lock); 734 + if (h->elements < i) 735 + return 0; 736 + } 737 + 738 + retry: 739 + ret = 0; 740 + htable_bits++; 741 + if (!htable_bits) 742 + /* In case we have plenty of memory :-) */ 743 + return -IPSET_ERR_HASH_FULL; 744 + t = ip_set_alloc(sizeof(*t) 745 + + jhash_size(htable_bits) * sizeof(struct hbucket)); 746 + if (!t) 747 + return -ENOMEM; 748 + t->htable_bits = htable_bits; 749 + 750 + read_lock_bh(&set->lock); 751 + for (i = 0; i < jhash_size(orig->htable_bits); i++) { 752 + n = hbucket(orig, i); 753 + for (j = 0; j < n->pos; j++) { 754 + data = ahash_tdata(n, j); 755 + m = hbucket(t, HKEY(data, h->initval, htable_bits)); 756 + ret = type_pf_elem_tadd(m, data, 757 + type_pf_data_timeout(data)); 758 + if (ret < 0) { 759 + read_unlock_bh(&set->lock); 760 + ahash_destroy(t); 761 + if (ret == -EAGAIN) 762 + goto retry; 763 + return ret; 764 + } 765 + } 766 + } 767 + 768 + rcu_assign_pointer(h->table, t); 769 + read_unlock_bh(&set->lock); 770 + 771 + /* Give time to other readers of the set */ 772 + synchronize_rcu_bh(); 773 + 774 + ahash_destroy(orig); 775 + 776 + return 0; 777 + } 778 + 779 + static int 780 + type_pf_tadd(struct ip_set *set, void *value, u32 timeout) 781 + { 782 + struct ip_set_hash *h = set->data; 783 + struct htable *t = h->table; 784 + const struct type_pf_elem *d = value; 785 + struct hbucket *n; 786 + struct type_pf_elem *data; 787 + int ret = 0, i, j = AHASH_MAX_SIZE + 1; 788 + u32 key; 789 + 790 + if (h->elements >= h->maxelem) 791 + /* FIXME: when set is full, we slow down here */ 792 + type_pf_expire(h); 793 + if (h->elements >= h->maxelem) 794 + return -IPSET_ERR_HASH_FULL; 795 + 796 + rcu_read_lock_bh(); 797 + t = rcu_dereference_bh(h->table); 798 + key = HKEY(d, h->initval, t->htable_bits); 799 + n = hbucket(t, key); 800 + for (i = 0; i < n->pos; i++) { 801 + data = ahash_tdata(n, i); 802 + if (type_pf_data_equal(data, d)) { 803 + if (type_pf_data_expired(data)) 804 + j = i; 805 + else { 806 + ret = -IPSET_ERR_EXIST; 807 + goto out; 808 + } 809 + } else if (j == AHASH_MAX_SIZE + 1 && 810 + type_pf_data_expired(data)) 811 + j = i; 812 + } 813 + if (j != AHASH_MAX_SIZE + 1) { 814 + data = ahash_tdata(n, j); 815 + #ifdef IP_SET_HASH_WITH_NETS 816 + del_cidr(h, data->cidr, HOST_MASK); 817 + add_cidr(h, d->cidr, HOST_MASK); 818 + #endif 819 + type_pf_data_copy(data, d); 820 + type_pf_data_timeout_set(data, timeout); 821 + goto out; 822 + } 823 + ret = type_pf_elem_tadd(n, d, timeout); 824 + if (ret != 0) 825 + goto out; 826 + 827 + #ifdef IP_SET_HASH_WITH_NETS 828 + add_cidr(h, d->cidr, HOST_MASK); 829 + #endif 830 + h->elements++; 831 + out: 832 + rcu_read_unlock_bh(); 833 + return ret; 834 + } 835 + 836 + static int 837 + type_pf_tdel(struct ip_set *set, void *value, u32 timeout) 838 + { 839 + struct ip_set_hash *h = set->data; 840 + struct htable *t = h->table; 841 + const struct type_pf_elem *d = value; 842 + struct hbucket *n; 843 + int i, ret = 0; 844 + struct type_pf_elem *data; 845 + u32 key; 846 + 847 + key = HKEY(value, h->initval, t->htable_bits); 848 + n = hbucket(t, key); 849 + for (i = 0; i < n->pos; i++) { 850 + data = ahash_tdata(n, i); 851 + if (!type_pf_data_equal(data, d)) 852 + continue; 853 + if (type_pf_data_expired(data)) 854 + ret = -IPSET_ERR_EXIST; 855 + if (i != n->pos - 1) 856 + /* Not last one */ 857 + type_pf_data_copy(data, ahash_tdata(n, n->pos - 1)); 858 + 859 + n->pos--; 860 + h->elements--; 861 + #ifdef IP_SET_HASH_WITH_NETS 862 + del_cidr(h, d->cidr, HOST_MASK); 863 + #endif 864 + if (n->pos + AHASH_INIT_SIZE < n->size) { 865 + void *tmp = kzalloc((n->size - AHASH_INIT_SIZE) 866 + * sizeof(struct type_pf_telem), 867 + GFP_ATOMIC); 868 + if (!tmp) 869 + return 0; 870 + n->size -= AHASH_INIT_SIZE; 871 + memcpy(tmp, n->value, 872 + n->size * sizeof(struct type_pf_telem)); 873 + kfree(n->value); 874 + n->value = tmp; 875 + } 876 + return 0; 877 + } 878 + 879 + return -IPSET_ERR_EXIST; 880 + } 881 + 882 + #ifdef IP_SET_HASH_WITH_NETS 883 + static int 884 + type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout) 885 + { 886 + struct ip_set_hash *h = set->data; 887 + struct htable *t = h->table; 888 + struct type_pf_elem *data; 889 + struct hbucket *n; 890 + int i, j = 0; 891 + u32 key; 892 + u8 host_mask = SET_HOST_MASK(set->family); 893 + 894 + for (; j < host_mask && h->nets[j].cidr; j++) { 895 + type_pf_data_netmask(d, h->nets[j].cidr); 896 + key = HKEY(d, h->initval, t->htable_bits); 897 + n = hbucket(t, key); 898 + for (i = 0; i < n->pos; i++) { 899 + data = ahash_tdata(n, i); 900 + if (type_pf_data_equal(data, d)) 901 + return !type_pf_data_expired(data); 902 + } 903 + } 904 + return 0; 905 + } 906 + #endif 907 + 908 + static int 909 + type_pf_ttest(struct ip_set *set, void *value, u32 timeout) 910 + { 911 + struct ip_set_hash *h = set->data; 912 + struct htable *t = h->table; 913 + struct type_pf_elem *data, *d = value; 914 + struct hbucket *n; 915 + int i; 916 + u32 key; 917 + 918 + #ifdef IP_SET_HASH_WITH_NETS 919 + if (d->cidr == SET_HOST_MASK(set->family)) 920 + return type_pf_ttest_cidrs(set, d, timeout); 921 + #endif 922 + key = HKEY(d, h->initval, t->htable_bits); 923 + n = hbucket(t, key); 924 + for (i = 0; i < n->pos; i++) { 925 + data = ahash_tdata(n, i); 926 + if (type_pf_data_equal(data, d)) 927 + return !type_pf_data_expired(data); 928 + } 929 + return 0; 930 + } 931 + 932 + static int 933 + type_pf_tlist(const struct ip_set *set, 934 + struct sk_buff *skb, struct netlink_callback *cb) 935 + { 936 + const struct ip_set_hash *h = set->data; 937 + const struct htable *t = h->table; 938 + struct nlattr *atd, *nested; 939 + const struct hbucket *n; 940 + const struct type_pf_elem *data; 941 + u32 first = cb->args[2]; 942 + /* We assume that one hash bucket fills into one page */ 943 + void *incomplete; 944 + int i; 945 + 946 + atd = ipset_nest_start(skb, IPSET_ATTR_ADT); 947 + if (!atd) 948 + return -EMSGSIZE; 949 + for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) { 950 + incomplete = skb_tail_pointer(skb); 951 + n = hbucket(t, cb->args[2]); 952 + for (i = 0; i < n->pos; i++) { 953 + data = ahash_tdata(n, i); 954 + pr_debug("list %p %u\n", n, i); 955 + if (type_pf_data_expired(data)) 956 + continue; 957 + pr_debug("do list %p %u\n", n, i); 958 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 959 + if (!nested) { 960 + if (cb->args[2] == first) { 961 + nla_nest_cancel(skb, atd); 962 + return -EMSGSIZE; 963 + } else 964 + goto nla_put_failure; 965 + } 966 + if (type_pf_data_tlist(skb, data)) 967 + goto nla_put_failure; 968 + ipset_nest_end(skb, nested); 969 + } 970 + } 971 + ipset_nest_end(skb, atd); 972 + /* Set listing finished */ 973 + cb->args[2] = 0; 974 + 975 + return 0; 976 + 977 + nla_put_failure: 978 + nlmsg_trim(skb, incomplete); 979 + ipset_nest_end(skb, atd); 980 + if (unlikely(first == cb->args[2])) { 981 + pr_warning("Can't list set %s: one bucket does not fit into " 982 + "a message. Please report it!\n", set->name); 983 + cb->args[2] = 0; 984 + return -EMSGSIZE; 985 + } 986 + return 0; 987 + } 988 + 989 + static const struct ip_set_type_variant type_pf_tvariant = { 990 + .kadt = type_pf_kadt, 991 + .uadt = type_pf_uadt, 992 + .adt = { 993 + [IPSET_ADD] = type_pf_tadd, 994 + [IPSET_DEL] = type_pf_tdel, 995 + [IPSET_TEST] = type_pf_ttest, 996 + }, 997 + .destroy = type_pf_destroy, 998 + .flush = type_pf_flush, 999 + .head = type_pf_head, 1000 + .list = type_pf_tlist, 1001 + .resize = type_pf_tresize, 1002 + .same_set = type_pf_same_set, 1003 + }; 1004 + 1005 + static void 1006 + type_pf_gc(unsigned long ul_set) 1007 + { 1008 + struct ip_set *set = (struct ip_set *) ul_set; 1009 + struct ip_set_hash *h = set->data; 1010 + 1011 + pr_debug("called\n"); 1012 + write_lock_bh(&set->lock); 1013 + type_pf_expire(h); 1014 + write_unlock_bh(&set->lock); 1015 + 1016 + h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ; 1017 + add_timer(&h->gc); 1018 + } 1019 + 1020 + static void 1021 + type_pf_gc_init(struct ip_set *set) 1022 + { 1023 + struct ip_set_hash *h = set->data; 1024 + 1025 + init_timer(&h->gc); 1026 + h->gc.data = (unsigned long) set; 1027 + h->gc.function = type_pf_gc; 1028 + h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ; 1029 + add_timer(&h->gc); 1030 + pr_debug("gc initialized, run in every %u\n", 1031 + IPSET_GC_PERIOD(h->timeout)); 1032 + } 1033 + 1034 + #undef type_pf_data_equal 1035 + #undef type_pf_data_isnull 1036 + #undef type_pf_data_copy 1037 + #undef type_pf_data_zero_out 1038 + #undef type_pf_data_list 1039 + #undef type_pf_data_tlist 1040 + 1041 + #undef type_pf_elem 1042 + #undef type_pf_telem 1043 + #undef type_pf_data_timeout 1044 + #undef type_pf_data_expired 1045 + #undef type_pf_data_netmask 1046 + #undef type_pf_data_timeout_set 1047 + 1048 + #undef type_pf_elem_add 1049 + #undef type_pf_add 1050 + #undef type_pf_del 1051 + #undef type_pf_test_cidrs 1052 + #undef type_pf_test 1053 + 1054 + #undef type_pf_elem_tadd 1055 + #undef type_pf_expire 1056 + #undef type_pf_tadd 1057 + #undef type_pf_tdel 1058 + #undef type_pf_ttest_cidrs 1059 + #undef type_pf_ttest 1060 + 1061 + #undef type_pf_resize 1062 + #undef type_pf_tresize 1063 + #undef type_pf_flush 1064 + #undef type_pf_destroy 1065 + #undef type_pf_head 1066 + #undef type_pf_list 1067 + #undef type_pf_tlist 1068 + #undef type_pf_same_set 1069 + #undef type_pf_kadt 1070 + #undef type_pf_uadt 1071 + #undef type_pf_gc 1072 + #undef type_pf_gc_init 1073 + #undef type_pf_variant 1074 + #undef type_pf_tvariant
+31
include/linux/netfilter/ipset/ip_set_bitmap.h
··· 1 + #ifndef __IP_SET_BITMAP_H 2 + #define __IP_SET_BITMAP_H 3 + 4 + /* Bitmap type specific error codes */ 5 + enum { 6 + /* The element is out of the range of the set */ 7 + IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC, 8 + /* The range exceeds the size limit of the set type */ 9 + IPSET_ERR_BITMAP_RANGE_SIZE, 10 + }; 11 + 12 + #ifdef __KERNEL__ 13 + #define IPSET_BITMAP_MAX_RANGE 0x0000FFFF 14 + 15 + /* Common functions */ 16 + 17 + static inline u32 18 + range_to_mask(u32 from, u32 to, u8 *bits) 19 + { 20 + u32 mask = 0xFFFFFFFE; 21 + 22 + *bits = 32; 23 + while (--(*bits) > 0 && mask && (to & mask) != from) 24 + mask <<= 1; 25 + 26 + return mask; 27 + } 28 + 29 + #endif /* __KERNEL__ */ 30 + 31 + #endif /* __IP_SET_BITMAP_H */
+21
include/linux/netfilter/ipset/ip_set_getport.h
··· 1 + #ifndef _IP_SET_GETPORT_H 2 + #define _IP_SET_GETPORT_H 3 + 4 + extern bool ip_set_get_ip4_port(const struct sk_buff *skb, bool src, 5 + __be16 *port, u8 *proto); 6 + 7 + #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) 8 + extern bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src, 9 + __be16 *port, u8 *proto); 10 + #else 11 + static inline bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src, 12 + __be16 *port, u8 *proto) 13 + { 14 + return false; 15 + } 16 + #endif 17 + 18 + extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, 19 + __be16 *port); 20 + 21 + #endif /*_IP_SET_GETPORT_H*/
+26
include/linux/netfilter/ipset/ip_set_hash.h
··· 1 + #ifndef __IP_SET_HASH_H 2 + #define __IP_SET_HASH_H 3 + 4 + /* Hash type specific error codes */ 5 + enum { 6 + /* Hash is full */ 7 + IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC, 8 + /* Null-valued element */ 9 + IPSET_ERR_HASH_ELEM, 10 + /* Invalid protocol */ 11 + IPSET_ERR_INVALID_PROTO, 12 + /* Protocol missing but must be specified */ 13 + IPSET_ERR_MISSING_PROTO, 14 + }; 15 + 16 + #ifdef __KERNEL__ 17 + 18 + #define IPSET_DEFAULT_HASHSIZE 1024 19 + #define IPSET_MIMINAL_HASHSIZE 64 20 + #define IPSET_DEFAULT_MAXELEM 65536 21 + #define IPSET_DEFAULT_PROBES 4 22 + #define IPSET_DEFAULT_RESIZE 100 23 + 24 + #endif /* __KERNEL__ */ 25 + 26 + #endif /* __IP_SET_HASH_H */
+27
include/linux/netfilter/ipset/ip_set_list.h
··· 1 + #ifndef __IP_SET_LIST_H 2 + #define __IP_SET_LIST_H 3 + 4 + /* List type specific error codes */ 5 + enum { 6 + /* Set name to be added/deleted/tested does not exist. */ 7 + IPSET_ERR_NAME = IPSET_ERR_TYPE_SPECIFIC, 8 + /* list:set type is not permitted to add */ 9 + IPSET_ERR_LOOP, 10 + /* Missing reference set */ 11 + IPSET_ERR_BEFORE, 12 + /* Reference set does not exist */ 13 + IPSET_ERR_NAMEREF, 14 + /* Set is full */ 15 + IPSET_ERR_LIST_FULL, 16 + /* Reference set is not added to the set */ 17 + IPSET_ERR_REF_EXIST, 18 + }; 19 + 20 + #ifdef __KERNEL__ 21 + 22 + #define IP_SET_LIST_DEFAULT_SIZE 8 23 + #define IP_SET_LIST_MIN_SIZE 4 24 + 25 + #endif /* __KERNEL__ */ 26 + 27 + #endif /* __IP_SET_LIST_H */
+127
include/linux/netfilter/ipset/ip_set_timeout.h
··· 1 + #ifndef _IP_SET_TIMEOUT_H 2 + #define _IP_SET_TIMEOUT_H 3 + 4 + /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + 11 + #ifdef __KERNEL__ 12 + 13 + /* How often should the gc be run by default */ 14 + #define IPSET_GC_TIME (3 * 60) 15 + 16 + /* Timeout period depending on the timeout value of the given set */ 17 + #define IPSET_GC_PERIOD(timeout) \ 18 + ((timeout/3) ? min_t(u32, (timeout)/3, IPSET_GC_TIME) : 1) 19 + 20 + /* Set is defined without timeout support: timeout value may be 0 */ 21 + #define IPSET_NO_TIMEOUT UINT_MAX 22 + 23 + #define with_timeout(timeout) ((timeout) != IPSET_NO_TIMEOUT) 24 + 25 + static inline unsigned int 26 + ip_set_timeout_uget(struct nlattr *tb) 27 + { 28 + unsigned int timeout = ip_set_get_h32(tb); 29 + 30 + /* Userspace supplied TIMEOUT parameter: adjust crazy size */ 31 + return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout; 32 + } 33 + 34 + #ifdef IP_SET_BITMAP_TIMEOUT 35 + 36 + /* Bitmap specific timeout constants and macros for the entries */ 37 + 38 + /* Bitmap entry is unset */ 39 + #define IPSET_ELEM_UNSET 0 40 + /* Bitmap entry is set with no timeout value */ 41 + #define IPSET_ELEM_PERMANENT (UINT_MAX/2) 42 + 43 + static inline bool 44 + ip_set_timeout_test(unsigned long timeout) 45 + { 46 + return timeout != IPSET_ELEM_UNSET && 47 + (timeout == IPSET_ELEM_PERMANENT || 48 + time_after(timeout, jiffies)); 49 + } 50 + 51 + static inline bool 52 + ip_set_timeout_expired(unsigned long timeout) 53 + { 54 + return timeout != IPSET_ELEM_UNSET && 55 + timeout != IPSET_ELEM_PERMANENT && 56 + time_before(timeout, jiffies); 57 + } 58 + 59 + static inline unsigned long 60 + ip_set_timeout_set(u32 timeout) 61 + { 62 + unsigned long t; 63 + 64 + if (!timeout) 65 + return IPSET_ELEM_PERMANENT; 66 + 67 + t = timeout * HZ + jiffies; 68 + if (t == IPSET_ELEM_UNSET || t == IPSET_ELEM_PERMANENT) 69 + /* Bingo! */ 70 + t++; 71 + 72 + return t; 73 + } 74 + 75 + static inline u32 76 + ip_set_timeout_get(unsigned long timeout) 77 + { 78 + return timeout == IPSET_ELEM_PERMANENT ? 0 : (timeout - jiffies)/HZ; 79 + } 80 + 81 + #else 82 + 83 + /* Hash specific timeout constants and macros for the entries */ 84 + 85 + /* Hash entry is set with no timeout value */ 86 + #define IPSET_ELEM_PERMANENT 0 87 + 88 + static inline bool 89 + ip_set_timeout_test(unsigned long timeout) 90 + { 91 + return timeout == IPSET_ELEM_PERMANENT || 92 + time_after(timeout, jiffies); 93 + } 94 + 95 + static inline bool 96 + ip_set_timeout_expired(unsigned long timeout) 97 + { 98 + return timeout != IPSET_ELEM_PERMANENT && 99 + time_before(timeout, jiffies); 100 + } 101 + 102 + static inline unsigned long 103 + ip_set_timeout_set(u32 timeout) 104 + { 105 + unsigned long t; 106 + 107 + if (!timeout) 108 + return IPSET_ELEM_PERMANENT; 109 + 110 + t = timeout * HZ + jiffies; 111 + if (t == IPSET_ELEM_PERMANENT) 112 + /* Bingo! :-) */ 113 + t++; 114 + 115 + return t; 116 + } 117 + 118 + static inline u32 119 + ip_set_timeout_get(unsigned long timeout) 120 + { 121 + return timeout == IPSET_ELEM_PERMANENT ? 0 : (timeout - jiffies)/HZ; 122 + } 123 + #endif /* ! IP_SET_BITMAP_TIMEOUT */ 124 + 125 + #endif /* __KERNEL__ */ 126 + 127 + #endif /* _IP_SET_TIMEOUT_H */
+35
include/linux/netfilter/ipset/pfxlen.h
··· 1 + #ifndef _PFXLEN_H 2 + #define _PFXLEN_H 3 + 4 + #include <asm/byteorder.h> 5 + #include <linux/netfilter.h> 6 + 7 + /* Prefixlen maps, by Jan Engelhardt */ 8 + extern const union nf_inet_addr ip_set_netmask_map[]; 9 + extern const union nf_inet_addr ip_set_hostmask_map[]; 10 + 11 + static inline __be32 12 + ip_set_netmask(u8 pfxlen) 13 + { 14 + return ip_set_netmask_map[pfxlen].ip; 15 + } 16 + 17 + static inline const __be32 * 18 + ip_set_netmask6(u8 pfxlen) 19 + { 20 + return &ip_set_netmask_map[pfxlen].ip6[0]; 21 + } 22 + 23 + static inline u32 24 + ip_set_hostmask(u8 pfxlen) 25 + { 26 + return (__force u32) ip_set_hostmask_map[pfxlen].ip; 27 + } 28 + 29 + static inline const __be32 * 30 + ip_set_hostmask6(u8 pfxlen) 31 + { 32 + return &ip_set_hostmask_map[pfxlen].ip6[0]; 33 + } 34 + 35 + #endif /*_PFXLEN_H */
+2 -1
include/linux/netfilter/nfnetlink.h
··· 47 47 #define NFNL_SUBSYS_QUEUE 3 48 48 #define NFNL_SUBSYS_ULOG 4 49 49 #define NFNL_SUBSYS_OSF 5 50 - #define NFNL_SUBSYS_COUNT 6 50 + #define NFNL_SUBSYS_IPSET 6 51 + #define NFNL_SUBSYS_COUNT 7 51 52 52 53 #ifdef __KERNEL__ 53 54
+21
include/linux/netfilter/xt_devgroup.h
··· 1 + #ifndef _XT_DEVGROUP_H 2 + #define _XT_DEVGROUP_H 3 + 4 + #include <linux/types.h> 5 + 6 + enum xt_devgroup_flags { 7 + XT_DEVGROUP_MATCH_SRC = 0x1, 8 + XT_DEVGROUP_INVERT_SRC = 0x2, 9 + XT_DEVGROUP_MATCH_DST = 0x4, 10 + XT_DEVGROUP_INVERT_DST = 0x8, 11 + }; 12 + 13 + struct xt_devgroup_info { 14 + __u32 flags; 15 + __u32 src_group; 16 + __u32 src_mask; 17 + __u32 dst_group; 18 + __u32 dst_mask; 19 + }; 20 + 21 + #endif /* _XT_DEVGROUP_H */
+56
include/linux/netfilter/xt_set.h
··· 1 + #ifndef _XT_SET_H 2 + #define _XT_SET_H 3 + 4 + #include <linux/types.h> 5 + #include <linux/netfilter/ipset/ip_set.h> 6 + 7 + /* Revision 0 interface: backward compatible with netfilter/iptables */ 8 + 9 + /* 10 + * Option flags for kernel operations (xt_set_info_v0) 11 + */ 12 + #define IPSET_SRC 0x01 /* Source match/add */ 13 + #define IPSET_DST 0x02 /* Destination match/add */ 14 + #define IPSET_MATCH_INV 0x04 /* Inverse matching */ 15 + 16 + struct xt_set_info_v0 { 17 + ip_set_id_t index; 18 + union { 19 + __u32 flags[IPSET_DIM_MAX + 1]; 20 + struct { 21 + __u32 __flags[IPSET_DIM_MAX]; 22 + __u8 dim; 23 + __u8 flags; 24 + } compat; 25 + } u; 26 + }; 27 + 28 + /* match and target infos */ 29 + struct xt_set_info_match_v0 { 30 + struct xt_set_info_v0 match_set; 31 + }; 32 + 33 + struct xt_set_info_target_v0 { 34 + struct xt_set_info_v0 add_set; 35 + struct xt_set_info_v0 del_set; 36 + }; 37 + 38 + /* Revision 1: current interface to netfilter/iptables */ 39 + 40 + struct xt_set_info { 41 + ip_set_id_t index; 42 + __u8 dim; 43 + __u8 flags; 44 + }; 45 + 46 + /* match and target infos */ 47 + struct xt_set_info_match { 48 + struct xt_set_info match_set; 49 + }; 50 + 51 + struct xt_set_info_target { 52 + struct xt_set_info add_set; 53 + struct xt_set_info del_set; 54 + }; 55 + 56 + #endif /*_XT_SET_H*/
-2
include/net/ip_vs.h
··· 1109 1109 * we are loaded. Just set ip_vs_drop_rate to 'n' and 1110 1110 * we start to drop 1/rate of the packets 1111 1111 */ 1112 - extern int ip_vs_drop_rate; 1113 - extern int ip_vs_drop_counter; 1114 1112 1115 1113 static inline int ip_vs_todrop(struct netns_ipvs *ipvs) 1116 1114 {
+9
include/net/netlink.h
··· 856 856 #define NLA_PUT_BE16(skb, attrtype, value) \ 857 857 NLA_PUT_TYPE(skb, __be16, attrtype, value) 858 858 859 + #define NLA_PUT_NET16(skb, attrtype, value) \ 860 + NLA_PUT_BE16(skb, attrtype | NLA_F_NET_BYTEORDER, value) 861 + 859 862 #define NLA_PUT_U32(skb, attrtype, value) \ 860 863 NLA_PUT_TYPE(skb, u32, attrtype, value) 861 864 862 865 #define NLA_PUT_BE32(skb, attrtype, value) \ 863 866 NLA_PUT_TYPE(skb, __be32, attrtype, value) 864 867 868 + #define NLA_PUT_NET32(skb, attrtype, value) \ 869 + NLA_PUT_BE32(skb, attrtype | NLA_F_NET_BYTEORDER, value) 870 + 865 871 #define NLA_PUT_U64(skb, attrtype, value) \ 866 872 NLA_PUT_TYPE(skb, u64, attrtype, value) 867 873 868 874 #define NLA_PUT_BE64(skb, attrtype, value) \ 869 875 NLA_PUT_TYPE(skb, __be64, attrtype, value) 876 + 877 + #define NLA_PUT_NET64(skb, attrtype, value) \ 878 + NLA_PUT_BE64(skb, attrtype | NLA_F_NET_BYTEORDER, value) 870 879 871 880 #define NLA_PUT_STRING(skb, attrtype, value) \ 872 881 NLA_PUT(skb, attrtype, strlen(value) + 1, value)
+23
net/netfilter/Kconfig
··· 352 352 ctmark), similarly to the packet mark (nfmark). Using this 353 353 target and match, you can set and match on this mark. 354 354 355 + config NETFILTER_XT_SET 356 + tristate 'set target and match support' 357 + depends on IP_SET 358 + depends on NETFILTER_ADVANCED 359 + help 360 + This option adds the "SET" target and "set" match. 361 + 362 + Using this target and match, you can add/delete and match 363 + elements in the sets created by ipset(8). 364 + 365 + To compile it as a module, choose M here. If unsure, say N. 366 + 355 367 # alphabetically ordered list of targets 356 368 357 369 comment "Xtables targets" ··· 738 726 If you want to compile it as a module, say M here and read 739 727 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. 740 728 729 + config NETFILTER_XT_MATCH_DEVGROUP 730 + tristate '"devgroup" match support' 731 + depends on NETFILTER_ADVANCED 732 + help 733 + This options adds a `devgroup' match, which allows to match on the 734 + device group a network device is assigned to. 735 + 736 + To compile it as a module, choose M here. If unsure, say N. 737 + 741 738 config NETFILTER_XT_MATCH_DSCP 742 739 tristate '"dscp" and "tos" match support' 743 740 depends on NETFILTER_ADVANCED ··· 1072 1051 endif # NETFILTER_XTABLES 1073 1052 1074 1053 endmenu 1054 + 1055 + source "net/netfilter/ipset/Kconfig" 1075 1056 1076 1057 source "net/netfilter/ipvs/Kconfig"
+5
net/netfilter/Makefile
··· 46 46 # combos 47 47 obj-$(CONFIG_NETFILTER_XT_MARK) += xt_mark.o 48 48 obj-$(CONFIG_NETFILTER_XT_CONNMARK) += xt_connmark.o 49 + obj-$(CONFIG_NETFILTER_XT_SET) += xt_set.o 49 50 50 51 # targets 51 52 obj-$(CONFIG_NETFILTER_XT_TARGET_AUDIT) += xt_AUDIT.o ··· 77 76 obj-$(CONFIG_NETFILTER_XT_MATCH_CONNTRACK) += xt_conntrack.o 78 77 obj-$(CONFIG_NETFILTER_XT_MATCH_CPU) += xt_cpu.o 79 78 obj-$(CONFIG_NETFILTER_XT_MATCH_DCCP) += xt_dccp.o 79 + obj-$(CONFIG_NETFILTER_XT_MATCH_DEVGROUP) += xt_devgroup.o 80 80 obj-$(CONFIG_NETFILTER_XT_MATCH_DSCP) += xt_dscp.o 81 81 obj-$(CONFIG_NETFILTER_XT_MATCH_ESP) += xt_esp.o 82 82 obj-$(CONFIG_NETFILTER_XT_MATCH_HASHLIMIT) += xt_hashlimit.o ··· 106 104 obj-$(CONFIG_NETFILTER_XT_MATCH_TCPMSS) += xt_tcpmss.o 107 105 obj-$(CONFIG_NETFILTER_XT_MATCH_TIME) += xt_time.o 108 106 obj-$(CONFIG_NETFILTER_XT_MATCH_U32) += xt_u32.o 107 + 108 + # ipset 109 + obj-$(CONFIG_IP_SET) += ipset/ 109 110 110 111 # IPVS 111 112 obj-$(CONFIG_IP_VS) += ipvs/
+121
net/netfilter/ipset/Kconfig
··· 1 + menuconfig IP_SET 2 + tristate "IP set support" 3 + depends on INET && NETFILTER 4 + help 5 + This option adds IP set support to the kernel. 6 + In order to define and use the sets, you need the userspace utility 7 + ipset(8). You can use the sets in netfilter via the "set" match 8 + and "SET" target. 9 + 10 + To compile it as a module, choose M here. If unsure, say N. 11 + 12 + if IP_SET 13 + 14 + config IP_SET_MAX 15 + int "Maximum number of IP sets" 16 + default 256 17 + range 2 65534 18 + depends on IP_SET 19 + help 20 + You can define here default value of the maximum number 21 + of IP sets for the kernel. 22 + 23 + The value can be overriden by the 'max_sets' module 24 + parameter of the 'ip_set' module. 25 + 26 + config IP_SET_BITMAP_IP 27 + tristate "bitmap:ip set support" 28 + depends on IP_SET 29 + help 30 + This option adds the bitmap:ip set type support, by which one 31 + can store IPv4 addresses (or network addresse) from a range. 32 + 33 + To compile it as a module, choose M here. If unsure, say N. 34 + 35 + config IP_SET_BITMAP_IPMAC 36 + tristate "bitmap:ip,mac set support" 37 + depends on IP_SET 38 + help 39 + This option adds the bitmap:ip,mac set type support, by which one 40 + can store IPv4 address and (source) MAC address pairs from a range. 41 + 42 + To compile it as a module, choose M here. If unsure, say N. 43 + 44 + config IP_SET_BITMAP_PORT 45 + tristate "bitmap:port set support" 46 + depends on IP_SET 47 + help 48 + This option adds the bitmap:port set type support, by which one 49 + can store TCP/UDP port numbers from a range. 50 + 51 + To compile it as a module, choose M here. If unsure, say N. 52 + 53 + config IP_SET_HASH_IP 54 + tristate "hash:ip set support" 55 + depends on IP_SET 56 + help 57 + This option adds the hash:ip set type support, by which one 58 + can store arbitrary IPv4 or IPv6 addresses (or network addresses) 59 + in a set. 60 + 61 + To compile it as a module, choose M here. If unsure, say N. 62 + 63 + config IP_SET_HASH_IPPORT 64 + tristate "hash:ip,port set support" 65 + depends on IP_SET 66 + help 67 + This option adds the hash:ip,port set type support, by which one 68 + can store IPv4/IPv6 address and protocol/port pairs. 69 + 70 + To compile it as a module, choose M here. If unsure, say N. 71 + 72 + config IP_SET_HASH_IPPORTIP 73 + tristate "hash:ip,port,ip set support" 74 + depends on IP_SET 75 + help 76 + This option adds the hash:ip,port,ip set type support, by which 77 + one can store IPv4/IPv6 address, protocol/port, and IPv4/IPv6 78 + address triples in a set. 79 + 80 + To compile it as a module, choose M here. If unsure, say N. 81 + 82 + config IP_SET_HASH_IPPORTNET 83 + tristate "hash:ip,port,net set support" 84 + depends on IP_SET 85 + help 86 + This option adds the hash:ip,port,net set type support, by which 87 + one can store IPv4/IPv6 address, protocol/port, and IPv4/IPv6 88 + network address/prefix triples in a set. 89 + 90 + To compile it as a module, choose M here. If unsure, say N. 91 + 92 + config IP_SET_HASH_NET 93 + tristate "hash:net set support" 94 + depends on IP_SET 95 + help 96 + This option adds the hash:net set type support, by which 97 + one can store IPv4/IPv6 network address/prefix elements in a set. 98 + 99 + To compile it as a module, choose M here. If unsure, say N. 100 + 101 + config IP_SET_HASH_NETPORT 102 + tristate "hash:net,port set support" 103 + depends on IP_SET 104 + help 105 + This option adds the hash:net,port set type support, by which 106 + one can store IPv4/IPv6 network address/prefix and 107 + protocol/port pairs as elements in a set. 108 + 109 + To compile it as a module, choose M here. If unsure, say N. 110 + 111 + config IP_SET_LIST_SET 112 + tristate "list:set set support" 113 + depends on IP_SET 114 + help 115 + This option adds the list:set set type support. In this 116 + kind of set one can store the name of other sets and it forms 117 + an ordered union of the member sets. 118 + 119 + To compile it as a module, choose M here. If unsure, say N. 120 + 121 + endif # IP_SET
+24
net/netfilter/ipset/Makefile
··· 1 + # 2 + # Makefile for the ipset modules 3 + # 4 + 5 + ip_set-y := ip_set_core.o ip_set_getport.o pfxlen.o 6 + 7 + # ipset core 8 + obj-$(CONFIG_IP_SET) += ip_set.o 9 + 10 + # bitmap types 11 + obj-$(CONFIG_IP_SET_BITMAP_IP) += ip_set_bitmap_ip.o 12 + obj-$(CONFIG_IP_SET_BITMAP_IPMAC) += ip_set_bitmap_ipmac.o 13 + obj-$(CONFIG_IP_SET_BITMAP_PORT) += ip_set_bitmap_port.o 14 + 15 + # hash types 16 + obj-$(CONFIG_IP_SET_HASH_IP) += ip_set_hash_ip.o 17 + obj-$(CONFIG_IP_SET_HASH_IPPORT) += ip_set_hash_ipport.o 18 + obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o 19 + obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o 20 + obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o 21 + obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o 22 + 23 + # list types 24 + obj-$(CONFIG_IP_SET_LIST_SET) += ip_set_list_set.o
+587
net/netfilter/ipset/ip_set_bitmap_ip.c
··· 1 + /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> 2 + * Patrick Schaaf <bof@bof.de> 3 + * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + */ 9 + 10 + /* Kernel module implementing an IP set type: the bitmap:ip type */ 11 + 12 + #include <linux/module.h> 13 + #include <linux/ip.h> 14 + #include <linux/skbuff.h> 15 + #include <linux/errno.h> 16 + #include <linux/bitops.h> 17 + #include <linux/spinlock.h> 18 + #include <linux/netlink.h> 19 + #include <linux/jiffies.h> 20 + #include <linux/timer.h> 21 + #include <net/netlink.h> 22 + #include <net/tcp.h> 23 + 24 + #include <linux/netfilter/ipset/pfxlen.h> 25 + #include <linux/netfilter/ipset/ip_set.h> 26 + #include <linux/netfilter/ipset/ip_set_bitmap.h> 27 + #define IP_SET_BITMAP_TIMEOUT 28 + #include <linux/netfilter/ipset/ip_set_timeout.h> 29 + 30 + MODULE_LICENSE("GPL"); 31 + MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 32 + MODULE_DESCRIPTION("bitmap:ip type of IP sets"); 33 + MODULE_ALIAS("ip_set_bitmap:ip"); 34 + 35 + /* Type structure */ 36 + struct bitmap_ip { 37 + void *members; /* the set members */ 38 + u32 first_ip; /* host byte order, included in range */ 39 + u32 last_ip; /* host byte order, included in range */ 40 + u32 elements; /* number of max elements in the set */ 41 + u32 hosts; /* number of hosts in a subnet */ 42 + size_t memsize; /* members size */ 43 + u8 netmask; /* subnet netmask */ 44 + u32 timeout; /* timeout parameter */ 45 + struct timer_list gc; /* garbage collection */ 46 + }; 47 + 48 + /* Base variant */ 49 + 50 + static inline u32 51 + ip_to_id(const struct bitmap_ip *m, u32 ip) 52 + { 53 + return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts; 54 + } 55 + 56 + static int 57 + bitmap_ip_test(struct ip_set *set, void *value, u32 timeout) 58 + { 59 + const struct bitmap_ip *map = set->data; 60 + u16 id = *(u16 *)value; 61 + 62 + return !!test_bit(id, map->members); 63 + } 64 + 65 + static int 66 + bitmap_ip_add(struct ip_set *set, void *value, u32 timeout) 67 + { 68 + struct bitmap_ip *map = set->data; 69 + u16 id = *(u16 *)value; 70 + 71 + if (test_and_set_bit(id, map->members)) 72 + return -IPSET_ERR_EXIST; 73 + 74 + return 0; 75 + } 76 + 77 + static int 78 + bitmap_ip_del(struct ip_set *set, void *value, u32 timeout) 79 + { 80 + struct bitmap_ip *map = set->data; 81 + u16 id = *(u16 *)value; 82 + 83 + if (!test_and_clear_bit(id, map->members)) 84 + return -IPSET_ERR_EXIST; 85 + 86 + return 0; 87 + } 88 + 89 + static int 90 + bitmap_ip_list(const struct ip_set *set, 91 + struct sk_buff *skb, struct netlink_callback *cb) 92 + { 93 + const struct bitmap_ip *map = set->data; 94 + struct nlattr *atd, *nested; 95 + u32 id, first = cb->args[2]; 96 + 97 + atd = ipset_nest_start(skb, IPSET_ATTR_ADT); 98 + if (!atd) 99 + return -EMSGSIZE; 100 + for (; cb->args[2] < map->elements; cb->args[2]++) { 101 + id = cb->args[2]; 102 + if (!test_bit(id, map->members)) 103 + continue; 104 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 105 + if (!nested) { 106 + if (id == first) { 107 + nla_nest_cancel(skb, atd); 108 + return -EMSGSIZE; 109 + } else 110 + goto nla_put_failure; 111 + } 112 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, 113 + htonl(map->first_ip + id * map->hosts)); 114 + ipset_nest_end(skb, nested); 115 + } 116 + ipset_nest_end(skb, atd); 117 + /* Set listing finished */ 118 + cb->args[2] = 0; 119 + return 0; 120 + 121 + nla_put_failure: 122 + nla_nest_cancel(skb, nested); 123 + ipset_nest_end(skb, atd); 124 + if (unlikely(id == first)) { 125 + cb->args[2] = 0; 126 + return -EMSGSIZE; 127 + } 128 + return 0; 129 + } 130 + 131 + /* Timeout variant */ 132 + 133 + static int 134 + bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout) 135 + { 136 + const struct bitmap_ip *map = set->data; 137 + const unsigned long *members = map->members; 138 + u16 id = *(u16 *)value; 139 + 140 + return ip_set_timeout_test(members[id]); 141 + } 142 + 143 + static int 144 + bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout) 145 + { 146 + struct bitmap_ip *map = set->data; 147 + unsigned long *members = map->members; 148 + u16 id = *(u16 *)value; 149 + 150 + if (ip_set_timeout_test(members[id])) 151 + return -IPSET_ERR_EXIST; 152 + 153 + members[id] = ip_set_timeout_set(timeout); 154 + 155 + return 0; 156 + } 157 + 158 + static int 159 + bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout) 160 + { 161 + struct bitmap_ip *map = set->data; 162 + unsigned long *members = map->members; 163 + u16 id = *(u16 *)value; 164 + int ret = -IPSET_ERR_EXIST; 165 + 166 + if (ip_set_timeout_test(members[id])) 167 + ret = 0; 168 + 169 + members[id] = IPSET_ELEM_UNSET; 170 + return ret; 171 + } 172 + 173 + static int 174 + bitmap_ip_tlist(const struct ip_set *set, 175 + struct sk_buff *skb, struct netlink_callback *cb) 176 + { 177 + const struct bitmap_ip *map = set->data; 178 + struct nlattr *adt, *nested; 179 + u32 id, first = cb->args[2]; 180 + const unsigned long *members = map->members; 181 + 182 + adt = ipset_nest_start(skb, IPSET_ATTR_ADT); 183 + if (!adt) 184 + return -EMSGSIZE; 185 + for (; cb->args[2] < map->elements; cb->args[2]++) { 186 + id = cb->args[2]; 187 + if (!ip_set_timeout_test(members[id])) 188 + continue; 189 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 190 + if (!nested) { 191 + if (id == first) { 192 + nla_nest_cancel(skb, adt); 193 + return -EMSGSIZE; 194 + } else 195 + goto nla_put_failure; 196 + } 197 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, 198 + htonl(map->first_ip + id * map->hosts)); 199 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 200 + htonl(ip_set_timeout_get(members[id]))); 201 + ipset_nest_end(skb, nested); 202 + } 203 + ipset_nest_end(skb, adt); 204 + 205 + /* Set listing finished */ 206 + cb->args[2] = 0; 207 + 208 + return 0; 209 + 210 + nla_put_failure: 211 + nla_nest_cancel(skb, nested); 212 + ipset_nest_end(skb, adt); 213 + if (unlikely(id == first)) { 214 + cb->args[2] = 0; 215 + return -EMSGSIZE; 216 + } 217 + return 0; 218 + } 219 + 220 + static int 221 + bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb, 222 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 223 + { 224 + struct bitmap_ip *map = set->data; 225 + ipset_adtfn adtfn = set->variant->adt[adt]; 226 + u32 ip; 227 + 228 + ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC)); 229 + if (ip < map->first_ip || ip > map->last_ip) 230 + return -IPSET_ERR_BITMAP_RANGE; 231 + 232 + ip = ip_to_id(map, ip); 233 + 234 + return adtfn(set, &ip, map->timeout); 235 + } 236 + 237 + static int 238 + bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[], 239 + enum ipset_adt adt, u32 *lineno, u32 flags) 240 + { 241 + struct bitmap_ip *map = set->data; 242 + ipset_adtfn adtfn = set->variant->adt[adt]; 243 + u32 timeout = map->timeout; 244 + u32 ip, ip_to, id; 245 + int ret = 0; 246 + 247 + if (unlikely(!tb[IPSET_ATTR_IP] || 248 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 249 + return -IPSET_ERR_PROTOCOL; 250 + 251 + if (tb[IPSET_ATTR_LINENO]) 252 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 253 + 254 + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 255 + if (ret) 256 + return ret; 257 + 258 + if (ip < map->first_ip || ip > map->last_ip) 259 + return -IPSET_ERR_BITMAP_RANGE; 260 + 261 + if (tb[IPSET_ATTR_TIMEOUT]) { 262 + if (!with_timeout(map->timeout)) 263 + return -IPSET_ERR_TIMEOUT; 264 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 265 + } 266 + 267 + if (adt == IPSET_TEST) { 268 + id = ip_to_id(map, ip); 269 + return adtfn(set, &id, timeout); 270 + } 271 + 272 + if (tb[IPSET_ATTR_IP_TO]) { 273 + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 274 + if (ret) 275 + return ret; 276 + if (ip > ip_to) { 277 + swap(ip, ip_to); 278 + if (ip < map->first_ip) 279 + return -IPSET_ERR_BITMAP_RANGE; 280 + } 281 + } else if (tb[IPSET_ATTR_CIDR]) { 282 + u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 283 + 284 + if (cidr > 32) 285 + return -IPSET_ERR_INVALID_CIDR; 286 + ip &= ip_set_hostmask(cidr); 287 + ip_to = ip | ~ip_set_hostmask(cidr); 288 + } else 289 + ip_to = ip; 290 + 291 + if (ip_to > map->last_ip) 292 + return -IPSET_ERR_BITMAP_RANGE; 293 + 294 + for (; !before(ip_to, ip); ip += map->hosts) { 295 + id = ip_to_id(map, ip); 296 + ret = adtfn(set, &id, timeout);; 297 + 298 + if (ret && !ip_set_eexist(ret, flags)) 299 + return ret; 300 + else 301 + ret = 0; 302 + } 303 + return ret; 304 + } 305 + 306 + static void 307 + bitmap_ip_destroy(struct ip_set *set) 308 + { 309 + struct bitmap_ip *map = set->data; 310 + 311 + if (with_timeout(map->timeout)) 312 + del_timer_sync(&map->gc); 313 + 314 + ip_set_free(map->members); 315 + kfree(map); 316 + 317 + set->data = NULL; 318 + } 319 + 320 + static void 321 + bitmap_ip_flush(struct ip_set *set) 322 + { 323 + struct bitmap_ip *map = set->data; 324 + 325 + memset(map->members, 0, map->memsize); 326 + } 327 + 328 + static int 329 + bitmap_ip_head(struct ip_set *set, struct sk_buff *skb) 330 + { 331 + const struct bitmap_ip *map = set->data; 332 + struct nlattr *nested; 333 + 334 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 335 + if (!nested) 336 + goto nla_put_failure; 337 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip)); 338 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); 339 + if (map->netmask != 32) 340 + NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask); 341 + NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, 342 + htonl(atomic_read(&set->ref) - 1)); 343 + NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, 344 + htonl(sizeof(*map) + map->memsize)); 345 + if (with_timeout(map->timeout)) 346 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); 347 + ipset_nest_end(skb, nested); 348 + 349 + return 0; 350 + nla_put_failure: 351 + return -EMSGSIZE; 352 + } 353 + 354 + static bool 355 + bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b) 356 + { 357 + const struct bitmap_ip *x = a->data; 358 + const struct bitmap_ip *y = b->data; 359 + 360 + return x->first_ip == y->first_ip && 361 + x->last_ip == y->last_ip && 362 + x->netmask == y->netmask && 363 + x->timeout == y->timeout; 364 + } 365 + 366 + static const struct ip_set_type_variant bitmap_ip = { 367 + .kadt = bitmap_ip_kadt, 368 + .uadt = bitmap_ip_uadt, 369 + .adt = { 370 + [IPSET_ADD] = bitmap_ip_add, 371 + [IPSET_DEL] = bitmap_ip_del, 372 + [IPSET_TEST] = bitmap_ip_test, 373 + }, 374 + .destroy = bitmap_ip_destroy, 375 + .flush = bitmap_ip_flush, 376 + .head = bitmap_ip_head, 377 + .list = bitmap_ip_list, 378 + .same_set = bitmap_ip_same_set, 379 + }; 380 + 381 + static const struct ip_set_type_variant bitmap_tip = { 382 + .kadt = bitmap_ip_kadt, 383 + .uadt = bitmap_ip_uadt, 384 + .adt = { 385 + [IPSET_ADD] = bitmap_ip_tadd, 386 + [IPSET_DEL] = bitmap_ip_tdel, 387 + [IPSET_TEST] = bitmap_ip_ttest, 388 + }, 389 + .destroy = bitmap_ip_destroy, 390 + .flush = bitmap_ip_flush, 391 + .head = bitmap_ip_head, 392 + .list = bitmap_ip_tlist, 393 + .same_set = bitmap_ip_same_set, 394 + }; 395 + 396 + static void 397 + bitmap_ip_gc(unsigned long ul_set) 398 + { 399 + struct ip_set *set = (struct ip_set *) ul_set; 400 + struct bitmap_ip *map = set->data; 401 + unsigned long *table = map->members; 402 + u32 id; 403 + 404 + /* We run parallel with other readers (test element) 405 + * but adding/deleting new entries is locked out */ 406 + read_lock_bh(&set->lock); 407 + for (id = 0; id < map->elements; id++) 408 + if (ip_set_timeout_expired(table[id])) 409 + table[id] = IPSET_ELEM_UNSET; 410 + read_unlock_bh(&set->lock); 411 + 412 + map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 413 + add_timer(&map->gc); 414 + } 415 + 416 + static void 417 + bitmap_ip_gc_init(struct ip_set *set) 418 + { 419 + struct bitmap_ip *map = set->data; 420 + 421 + init_timer(&map->gc); 422 + map->gc.data = (unsigned long) set; 423 + map->gc.function = bitmap_ip_gc; 424 + map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 425 + add_timer(&map->gc); 426 + } 427 + 428 + /* Create bitmap:ip type of sets */ 429 + 430 + static bool 431 + init_map_ip(struct ip_set *set, struct bitmap_ip *map, 432 + u32 first_ip, u32 last_ip, 433 + u32 elements, u32 hosts, u8 netmask) 434 + { 435 + map->members = ip_set_alloc(map->memsize); 436 + if (!map->members) 437 + return false; 438 + map->first_ip = first_ip; 439 + map->last_ip = last_ip; 440 + map->elements = elements; 441 + map->hosts = hosts; 442 + map->netmask = netmask; 443 + map->timeout = IPSET_NO_TIMEOUT; 444 + 445 + set->data = map; 446 + set->family = AF_INET; 447 + 448 + return true; 449 + } 450 + 451 + static int 452 + bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) 453 + { 454 + struct bitmap_ip *map; 455 + u32 first_ip, last_ip, hosts, elements; 456 + u8 netmask = 32; 457 + int ret; 458 + 459 + if (unlikely(!tb[IPSET_ATTR_IP] || 460 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 461 + return -IPSET_ERR_PROTOCOL; 462 + 463 + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip); 464 + if (ret) 465 + return ret; 466 + 467 + if (tb[IPSET_ATTR_IP_TO]) { 468 + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip); 469 + if (ret) 470 + return ret; 471 + if (first_ip > last_ip) { 472 + u32 tmp = first_ip; 473 + 474 + first_ip = last_ip; 475 + last_ip = tmp; 476 + } 477 + } else if (tb[IPSET_ATTR_CIDR]) { 478 + u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 479 + 480 + if (cidr >= 32) 481 + return -IPSET_ERR_INVALID_CIDR; 482 + last_ip = first_ip | ~ip_set_hostmask(cidr); 483 + } else 484 + return -IPSET_ERR_PROTOCOL; 485 + 486 + if (tb[IPSET_ATTR_NETMASK]) { 487 + netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]); 488 + 489 + if (netmask > 32) 490 + return -IPSET_ERR_INVALID_NETMASK; 491 + 492 + first_ip &= ip_set_hostmask(netmask); 493 + last_ip |= ~ip_set_hostmask(netmask); 494 + } 495 + 496 + if (netmask == 32) { 497 + hosts = 1; 498 + elements = last_ip - first_ip + 1; 499 + } else { 500 + u8 mask_bits; 501 + u32 mask; 502 + 503 + mask = range_to_mask(first_ip, last_ip, &mask_bits); 504 + 505 + if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) || 506 + netmask <= mask_bits) 507 + return -IPSET_ERR_BITMAP_RANGE; 508 + 509 + pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask); 510 + hosts = 2 << (32 - netmask - 1); 511 + elements = 2 << (netmask - mask_bits - 1); 512 + } 513 + if (elements > IPSET_BITMAP_MAX_RANGE + 1) 514 + return -IPSET_ERR_BITMAP_RANGE_SIZE; 515 + 516 + pr_debug("hosts %u, elements %u\n", hosts, elements); 517 + 518 + map = kzalloc(sizeof(*map), GFP_KERNEL); 519 + if (!map) 520 + return -ENOMEM; 521 + 522 + if (tb[IPSET_ATTR_TIMEOUT]) { 523 + map->memsize = elements * sizeof(unsigned long); 524 + 525 + if (!init_map_ip(set, map, first_ip, last_ip, 526 + elements, hosts, netmask)) { 527 + kfree(map); 528 + return -ENOMEM; 529 + } 530 + 531 + map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 532 + set->variant = &bitmap_tip; 533 + 534 + bitmap_ip_gc_init(set); 535 + } else { 536 + map->memsize = bitmap_bytes(0, elements - 1); 537 + 538 + if (!init_map_ip(set, map, first_ip, last_ip, 539 + elements, hosts, netmask)) { 540 + kfree(map); 541 + return -ENOMEM; 542 + } 543 + 544 + set->variant = &bitmap_ip; 545 + } 546 + return 0; 547 + } 548 + 549 + static struct ip_set_type bitmap_ip_type __read_mostly = { 550 + .name = "bitmap:ip", 551 + .protocol = IPSET_PROTOCOL, 552 + .features = IPSET_TYPE_IP, 553 + .dimension = IPSET_DIM_ONE, 554 + .family = AF_INET, 555 + .revision = 0, 556 + .create = bitmap_ip_create, 557 + .create_policy = { 558 + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 559 + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 560 + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 561 + [IPSET_ATTR_NETMASK] = { .type = NLA_U8 }, 562 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 563 + }, 564 + .adt_policy = { 565 + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 566 + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 567 + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 568 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 569 + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 570 + }, 571 + .me = THIS_MODULE, 572 + }; 573 + 574 + static int __init 575 + bitmap_ip_init(void) 576 + { 577 + return ip_set_type_register(&bitmap_ip_type); 578 + } 579 + 580 + static void __exit 581 + bitmap_ip_fini(void) 582 + { 583 + ip_set_type_unregister(&bitmap_ip_type); 584 + } 585 + 586 + module_init(bitmap_ip_init); 587 + module_exit(bitmap_ip_fini);
+652
net/netfilter/ipset/ip_set_bitmap_ipmac.c
··· 1 + /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> 2 + * Patrick Schaaf <bof@bof.de> 3 + * Martin Josefsson <gandalf@wlug.westbo.se> 4 + * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + 11 + /* Kernel module implementing an IP set type: the bitmap:ip,mac type */ 12 + 13 + #include <linux/module.h> 14 + #include <linux/ip.h> 15 + #include <linux/etherdevice.h> 16 + #include <linux/skbuff.h> 17 + #include <linux/errno.h> 18 + #include <linux/if_ether.h> 19 + #include <linux/netlink.h> 20 + #include <linux/jiffies.h> 21 + #include <linux/timer.h> 22 + #include <net/netlink.h> 23 + 24 + #include <linux/netfilter/ipset/pfxlen.h> 25 + #include <linux/netfilter/ipset/ip_set.h> 26 + #include <linux/netfilter/ipset/ip_set_timeout.h> 27 + #include <linux/netfilter/ipset/ip_set_bitmap.h> 28 + 29 + MODULE_LICENSE("GPL"); 30 + MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 31 + MODULE_DESCRIPTION("bitmap:ip,mac type of IP sets"); 32 + MODULE_ALIAS("ip_set_bitmap:ip,mac"); 33 + 34 + enum { 35 + MAC_EMPTY, /* element is not set */ 36 + MAC_FILLED, /* element is set with MAC */ 37 + MAC_UNSET, /* element is set, without MAC */ 38 + }; 39 + 40 + /* Type structure */ 41 + struct bitmap_ipmac { 42 + void *members; /* the set members */ 43 + u32 first_ip; /* host byte order, included in range */ 44 + u32 last_ip; /* host byte order, included in range */ 45 + u32 timeout; /* timeout value */ 46 + struct timer_list gc; /* garbage collector */ 47 + size_t dsize; /* size of element */ 48 + }; 49 + 50 + /* ADT structure for generic function args */ 51 + struct ipmac { 52 + u32 id; /* id in array */ 53 + unsigned char *ether; /* ethernet address */ 54 + }; 55 + 56 + /* Member element without and with timeout */ 57 + 58 + struct ipmac_elem { 59 + unsigned char ether[ETH_ALEN]; 60 + unsigned char match; 61 + } __attribute__ ((aligned)); 62 + 63 + struct ipmac_telem { 64 + unsigned char ether[ETH_ALEN]; 65 + unsigned char match; 66 + unsigned long timeout; 67 + } __attribute__ ((aligned)); 68 + 69 + static inline void * 70 + bitmap_ipmac_elem(const struct bitmap_ipmac *map, u32 id) 71 + { 72 + return (void *)((char *)map->members + id * map->dsize); 73 + } 74 + 75 + static inline bool 76 + bitmap_timeout(const struct bitmap_ipmac *map, u32 id) 77 + { 78 + const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id); 79 + 80 + return ip_set_timeout_test(elem->timeout); 81 + } 82 + 83 + static inline bool 84 + bitmap_expired(const struct bitmap_ipmac *map, u32 id) 85 + { 86 + const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id); 87 + 88 + return ip_set_timeout_expired(elem->timeout); 89 + } 90 + 91 + static inline int 92 + bitmap_ipmac_exist(const struct ipmac_telem *elem) 93 + { 94 + return elem->match == MAC_UNSET || 95 + (elem->match == MAC_FILLED && 96 + !ip_set_timeout_expired(elem->timeout)); 97 + } 98 + 99 + /* Base variant */ 100 + 101 + static int 102 + bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout) 103 + { 104 + const struct bitmap_ipmac *map = set->data; 105 + const struct ipmac *data = value; 106 + const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id); 107 + 108 + switch (elem->match) { 109 + case MAC_UNSET: 110 + /* Trigger kernel to fill out the ethernet address */ 111 + return -EAGAIN; 112 + case MAC_FILLED: 113 + return data->ether == NULL || 114 + compare_ether_addr(data->ether, elem->ether) == 0; 115 + } 116 + return 0; 117 + } 118 + 119 + static int 120 + bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout) 121 + { 122 + struct bitmap_ipmac *map = set->data; 123 + const struct ipmac *data = value; 124 + struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id); 125 + 126 + switch (elem->match) { 127 + case MAC_UNSET: 128 + if (!data->ether) 129 + /* Already added without ethernet address */ 130 + return -IPSET_ERR_EXIST; 131 + /* Fill the MAC address */ 132 + memcpy(elem->ether, data->ether, ETH_ALEN); 133 + elem->match = MAC_FILLED; 134 + break; 135 + case MAC_FILLED: 136 + return -IPSET_ERR_EXIST; 137 + case MAC_EMPTY: 138 + if (data->ether) { 139 + memcpy(elem->ether, data->ether, ETH_ALEN); 140 + elem->match = MAC_FILLED; 141 + } else 142 + elem->match = MAC_UNSET; 143 + } 144 + 145 + return 0; 146 + } 147 + 148 + static int 149 + bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout) 150 + { 151 + struct bitmap_ipmac *map = set->data; 152 + const struct ipmac *data = value; 153 + struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id); 154 + 155 + if (elem->match == MAC_EMPTY) 156 + return -IPSET_ERR_EXIST; 157 + 158 + elem->match = MAC_EMPTY; 159 + 160 + return 0; 161 + } 162 + 163 + static int 164 + bitmap_ipmac_list(const struct ip_set *set, 165 + struct sk_buff *skb, struct netlink_callback *cb) 166 + { 167 + const struct bitmap_ipmac *map = set->data; 168 + const struct ipmac_elem *elem; 169 + struct nlattr *atd, *nested; 170 + u32 id, first = cb->args[2]; 171 + u32 last = map->last_ip - map->first_ip; 172 + 173 + atd = ipset_nest_start(skb, IPSET_ATTR_ADT); 174 + if (!atd) 175 + return -EMSGSIZE; 176 + for (; cb->args[2] <= last; cb->args[2]++) { 177 + id = cb->args[2]; 178 + elem = bitmap_ipmac_elem(map, id); 179 + if (elem->match == MAC_EMPTY) 180 + continue; 181 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 182 + if (!nested) { 183 + if (id == first) { 184 + nla_nest_cancel(skb, atd); 185 + return -EMSGSIZE; 186 + } else 187 + goto nla_put_failure; 188 + } 189 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, 190 + htonl(map->first_ip + id)); 191 + if (elem->match == MAC_FILLED) 192 + NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN, 193 + elem->ether); 194 + ipset_nest_end(skb, nested); 195 + } 196 + ipset_nest_end(skb, atd); 197 + /* Set listing finished */ 198 + cb->args[2] = 0; 199 + 200 + return 0; 201 + 202 + nla_put_failure: 203 + nla_nest_cancel(skb, nested); 204 + ipset_nest_end(skb, atd); 205 + if (unlikely(id == first)) { 206 + cb->args[2] = 0; 207 + return -EMSGSIZE; 208 + } 209 + return 0; 210 + } 211 + 212 + /* Timeout variant */ 213 + 214 + static int 215 + bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout) 216 + { 217 + const struct bitmap_ipmac *map = set->data; 218 + const struct ipmac *data = value; 219 + const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id); 220 + 221 + switch (elem->match) { 222 + case MAC_UNSET: 223 + /* Trigger kernel to fill out the ethernet address */ 224 + return -EAGAIN; 225 + case MAC_FILLED: 226 + return (data->ether == NULL || 227 + compare_ether_addr(data->ether, elem->ether) == 0) && 228 + !bitmap_expired(map, data->id); 229 + } 230 + return 0; 231 + } 232 + 233 + static int 234 + bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout) 235 + { 236 + struct bitmap_ipmac *map = set->data; 237 + const struct ipmac *data = value; 238 + struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id); 239 + 240 + switch (elem->match) { 241 + case MAC_UNSET: 242 + if (!data->ether) 243 + /* Already added without ethernet address */ 244 + return -IPSET_ERR_EXIST; 245 + /* Fill the MAC address and activate the timer */ 246 + memcpy(elem->ether, data->ether, ETH_ALEN); 247 + elem->match = MAC_FILLED; 248 + if (timeout == map->timeout) 249 + /* Timeout was not specified, get stored one */ 250 + timeout = elem->timeout; 251 + elem->timeout = ip_set_timeout_set(timeout); 252 + break; 253 + case MAC_FILLED: 254 + if (!bitmap_expired(map, data->id)) 255 + return -IPSET_ERR_EXIST; 256 + /* Fall through */ 257 + case MAC_EMPTY: 258 + if (data->ether) { 259 + memcpy(elem->ether, data->ether, ETH_ALEN); 260 + elem->match = MAC_FILLED; 261 + } else 262 + elem->match = MAC_UNSET; 263 + /* If MAC is unset yet, we store plain timeout value 264 + * because the timer is not activated yet 265 + * and we can reuse it later when MAC is filled out, 266 + * possibly by the kernel */ 267 + elem->timeout = data->ether ? ip_set_timeout_set(timeout) 268 + : timeout; 269 + break; 270 + } 271 + 272 + return 0; 273 + } 274 + 275 + static int 276 + bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout) 277 + { 278 + struct bitmap_ipmac *map = set->data; 279 + const struct ipmac *data = value; 280 + struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id); 281 + 282 + if (elem->match == MAC_EMPTY || bitmap_expired(map, data->id)) 283 + return -IPSET_ERR_EXIST; 284 + 285 + elem->match = MAC_EMPTY; 286 + 287 + return 0; 288 + } 289 + 290 + static int 291 + bitmap_ipmac_tlist(const struct ip_set *set, 292 + struct sk_buff *skb, struct netlink_callback *cb) 293 + { 294 + const struct bitmap_ipmac *map = set->data; 295 + const struct ipmac_telem *elem; 296 + struct nlattr *atd, *nested; 297 + u32 id, first = cb->args[2]; 298 + u32 timeout, last = map->last_ip - map->first_ip; 299 + 300 + atd = ipset_nest_start(skb, IPSET_ATTR_ADT); 301 + if (!atd) 302 + return -EMSGSIZE; 303 + for (; cb->args[2] <= last; cb->args[2]++) { 304 + id = cb->args[2]; 305 + elem = bitmap_ipmac_elem(map, id); 306 + if (!bitmap_ipmac_exist(elem)) 307 + continue; 308 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 309 + if (!nested) { 310 + if (id == first) { 311 + nla_nest_cancel(skb, atd); 312 + return -EMSGSIZE; 313 + } else 314 + goto nla_put_failure; 315 + } 316 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, 317 + htonl(map->first_ip + id)); 318 + if (elem->match == MAC_FILLED) 319 + NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN, 320 + elem->ether); 321 + timeout = elem->match == MAC_UNSET ? elem->timeout 322 + : ip_set_timeout_get(elem->timeout); 323 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout)); 324 + ipset_nest_end(skb, nested); 325 + } 326 + ipset_nest_end(skb, atd); 327 + /* Set listing finished */ 328 + cb->args[2] = 0; 329 + 330 + return 0; 331 + 332 + nla_put_failure: 333 + nla_nest_cancel(skb, nested); 334 + ipset_nest_end(skb, atd); 335 + return -EMSGSIZE; 336 + } 337 + 338 + static int 339 + bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb, 340 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 341 + { 342 + struct bitmap_ipmac *map = set->data; 343 + ipset_adtfn adtfn = set->variant->adt[adt]; 344 + struct ipmac data; 345 + 346 + data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC)); 347 + if (data.id < map->first_ip || data.id > map->last_ip) 348 + return -IPSET_ERR_BITMAP_RANGE; 349 + 350 + /* Backward compatibility: we don't check the second flag */ 351 + if (skb_mac_header(skb) < skb->head || 352 + (skb_mac_header(skb) + ETH_HLEN) > skb->data) 353 + return -EINVAL; 354 + 355 + data.id -= map->first_ip; 356 + data.ether = eth_hdr(skb)->h_source; 357 + 358 + return adtfn(set, &data, map->timeout); 359 + } 360 + 361 + static int 362 + bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[], 363 + enum ipset_adt adt, u32 *lineno, u32 flags) 364 + { 365 + const struct bitmap_ipmac *map = set->data; 366 + ipset_adtfn adtfn = set->variant->adt[adt]; 367 + struct ipmac data; 368 + u32 timeout = map->timeout; 369 + int ret = 0; 370 + 371 + if (unlikely(!tb[IPSET_ATTR_IP] || 372 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 373 + return -IPSET_ERR_PROTOCOL; 374 + 375 + if (tb[IPSET_ATTR_LINENO]) 376 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 377 + 378 + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &data.id); 379 + if (ret) 380 + return ret; 381 + 382 + if (data.id < map->first_ip || data.id > map->last_ip) 383 + return -IPSET_ERR_BITMAP_RANGE; 384 + 385 + if (tb[IPSET_ATTR_ETHER]) 386 + data.ether = nla_data(tb[IPSET_ATTR_ETHER]); 387 + else 388 + data.ether = NULL; 389 + 390 + if (tb[IPSET_ATTR_TIMEOUT]) { 391 + if (!with_timeout(map->timeout)) 392 + return -IPSET_ERR_TIMEOUT; 393 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 394 + } 395 + 396 + data.id -= map->first_ip; 397 + 398 + ret = adtfn(set, &data, timeout); 399 + 400 + return ip_set_eexist(ret, flags) ? 0 : ret; 401 + } 402 + 403 + static void 404 + bitmap_ipmac_destroy(struct ip_set *set) 405 + { 406 + struct bitmap_ipmac *map = set->data; 407 + 408 + if (with_timeout(map->timeout)) 409 + del_timer_sync(&map->gc); 410 + 411 + ip_set_free(map->members); 412 + kfree(map); 413 + 414 + set->data = NULL; 415 + } 416 + 417 + static void 418 + bitmap_ipmac_flush(struct ip_set *set) 419 + { 420 + struct bitmap_ipmac *map = set->data; 421 + 422 + memset(map->members, 0, 423 + (map->last_ip - map->first_ip + 1) * map->dsize); 424 + } 425 + 426 + static int 427 + bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb) 428 + { 429 + const struct bitmap_ipmac *map = set->data; 430 + struct nlattr *nested; 431 + 432 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 433 + if (!nested) 434 + goto nla_put_failure; 435 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip)); 436 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); 437 + NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, 438 + htonl(atomic_read(&set->ref) - 1)); 439 + NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, 440 + htonl(sizeof(*map) 441 + + (map->last_ip - map->first_ip + 1) * map->dsize)); 442 + if (with_timeout(map->timeout)) 443 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); 444 + ipset_nest_end(skb, nested); 445 + 446 + return 0; 447 + nla_put_failure: 448 + return -EMSGSIZE; 449 + } 450 + 451 + static bool 452 + bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b) 453 + { 454 + const struct bitmap_ipmac *x = a->data; 455 + const struct bitmap_ipmac *y = b->data; 456 + 457 + return x->first_ip == y->first_ip && 458 + x->last_ip == y->last_ip && 459 + x->timeout == y->timeout; 460 + } 461 + 462 + static const struct ip_set_type_variant bitmap_ipmac = { 463 + .kadt = bitmap_ipmac_kadt, 464 + .uadt = bitmap_ipmac_uadt, 465 + .adt = { 466 + [IPSET_ADD] = bitmap_ipmac_add, 467 + [IPSET_DEL] = bitmap_ipmac_del, 468 + [IPSET_TEST] = bitmap_ipmac_test, 469 + }, 470 + .destroy = bitmap_ipmac_destroy, 471 + .flush = bitmap_ipmac_flush, 472 + .head = bitmap_ipmac_head, 473 + .list = bitmap_ipmac_list, 474 + .same_set = bitmap_ipmac_same_set, 475 + }; 476 + 477 + static const struct ip_set_type_variant bitmap_tipmac = { 478 + .kadt = bitmap_ipmac_kadt, 479 + .uadt = bitmap_ipmac_uadt, 480 + .adt = { 481 + [IPSET_ADD] = bitmap_ipmac_tadd, 482 + [IPSET_DEL] = bitmap_ipmac_tdel, 483 + [IPSET_TEST] = bitmap_ipmac_ttest, 484 + }, 485 + .destroy = bitmap_ipmac_destroy, 486 + .flush = bitmap_ipmac_flush, 487 + .head = bitmap_ipmac_head, 488 + .list = bitmap_ipmac_tlist, 489 + .same_set = bitmap_ipmac_same_set, 490 + }; 491 + 492 + static void 493 + bitmap_ipmac_gc(unsigned long ul_set) 494 + { 495 + struct ip_set *set = (struct ip_set *) ul_set; 496 + struct bitmap_ipmac *map = set->data; 497 + struct ipmac_telem *elem; 498 + u32 id, last = map->last_ip - map->first_ip; 499 + 500 + /* We run parallel with other readers (test element) 501 + * but adding/deleting new entries is locked out */ 502 + read_lock_bh(&set->lock); 503 + for (id = 0; id <= last; id++) { 504 + elem = bitmap_ipmac_elem(map, id); 505 + if (elem->match == MAC_FILLED && 506 + ip_set_timeout_expired(elem->timeout)) 507 + elem->match = MAC_EMPTY; 508 + } 509 + read_unlock_bh(&set->lock); 510 + 511 + map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 512 + add_timer(&map->gc); 513 + } 514 + 515 + static void 516 + bitmap_ipmac_gc_init(struct ip_set *set) 517 + { 518 + struct bitmap_ipmac *map = set->data; 519 + 520 + init_timer(&map->gc); 521 + map->gc.data = (unsigned long) set; 522 + map->gc.function = bitmap_ipmac_gc; 523 + map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 524 + add_timer(&map->gc); 525 + } 526 + 527 + /* Create bitmap:ip,mac type of sets */ 528 + 529 + static bool 530 + init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map, 531 + u32 first_ip, u32 last_ip) 532 + { 533 + map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize); 534 + if (!map->members) 535 + return false; 536 + map->first_ip = first_ip; 537 + map->last_ip = last_ip; 538 + map->timeout = IPSET_NO_TIMEOUT; 539 + 540 + set->data = map; 541 + set->family = AF_INET; 542 + 543 + return true; 544 + } 545 + 546 + static int 547 + bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[], 548 + u32 flags) 549 + { 550 + u32 first_ip, last_ip, elements; 551 + struct bitmap_ipmac *map; 552 + int ret; 553 + 554 + if (unlikely(!tb[IPSET_ATTR_IP] || 555 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 556 + return -IPSET_ERR_PROTOCOL; 557 + 558 + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip); 559 + if (ret) 560 + return ret; 561 + 562 + if (tb[IPSET_ATTR_IP_TO]) { 563 + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip); 564 + if (ret) 565 + return ret; 566 + if (first_ip > last_ip) { 567 + u32 tmp = first_ip; 568 + 569 + first_ip = last_ip; 570 + last_ip = tmp; 571 + } 572 + } else if (tb[IPSET_ATTR_CIDR]) { 573 + u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 574 + 575 + if (cidr >= 32) 576 + return -IPSET_ERR_INVALID_CIDR; 577 + last_ip = first_ip | ~ip_set_hostmask(cidr); 578 + } else 579 + return -IPSET_ERR_PROTOCOL; 580 + 581 + elements = last_ip - first_ip + 1; 582 + 583 + if (elements > IPSET_BITMAP_MAX_RANGE + 1) 584 + return -IPSET_ERR_BITMAP_RANGE_SIZE; 585 + 586 + map = kzalloc(sizeof(*map), GFP_KERNEL); 587 + if (!map) 588 + return -ENOMEM; 589 + 590 + if (tb[IPSET_ATTR_TIMEOUT]) { 591 + map->dsize = sizeof(struct ipmac_telem); 592 + 593 + if (!init_map_ipmac(set, map, first_ip, last_ip)) { 594 + kfree(map); 595 + return -ENOMEM; 596 + } 597 + 598 + map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 599 + 600 + set->variant = &bitmap_tipmac; 601 + 602 + bitmap_ipmac_gc_init(set); 603 + } else { 604 + map->dsize = sizeof(struct ipmac_elem); 605 + 606 + if (!init_map_ipmac(set, map, first_ip, last_ip)) { 607 + kfree(map); 608 + return -ENOMEM; 609 + } 610 + set->variant = &bitmap_ipmac; 611 + 612 + } 613 + return 0; 614 + } 615 + 616 + static struct ip_set_type bitmap_ipmac_type = { 617 + .name = "bitmap:ip,mac", 618 + .protocol = IPSET_PROTOCOL, 619 + .features = IPSET_TYPE_IP | IPSET_TYPE_MAC, 620 + .dimension = IPSET_DIM_TWO, 621 + .family = AF_INET, 622 + .revision = 0, 623 + .create = bitmap_ipmac_create, 624 + .create_policy = { 625 + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 626 + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 627 + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 628 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 629 + }, 630 + .adt_policy = { 631 + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 632 + [IPSET_ATTR_ETHER] = { .type = NLA_BINARY, .len = ETH_ALEN }, 633 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 634 + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 635 + }, 636 + .me = THIS_MODULE, 637 + }; 638 + 639 + static int __init 640 + bitmap_ipmac_init(void) 641 + { 642 + return ip_set_type_register(&bitmap_ipmac_type); 643 + } 644 + 645 + static void __exit 646 + bitmap_ipmac_fini(void) 647 + { 648 + ip_set_type_unregister(&bitmap_ipmac_type); 649 + } 650 + 651 + module_init(bitmap_ipmac_init); 652 + module_exit(bitmap_ipmac_fini);
+515
net/netfilter/ipset/ip_set_bitmap_port.c
··· 1 + /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 2 + * 3 + * This program is free software; you can redistribute it and/or modify 4 + * it under the terms of the GNU General Public License version 2 as 5 + * published by the Free Software Foundation. 6 + */ 7 + 8 + /* Kernel module implementing an IP set type: the bitmap:port type */ 9 + 10 + #include <linux/module.h> 11 + #include <linux/ip.h> 12 + #include <linux/skbuff.h> 13 + #include <linux/errno.h> 14 + #include <linux/netlink.h> 15 + #include <linux/jiffies.h> 16 + #include <linux/timer.h> 17 + #include <net/netlink.h> 18 + 19 + #include <linux/netfilter/ipset/ip_set.h> 20 + #include <linux/netfilter/ipset/ip_set_bitmap.h> 21 + #include <linux/netfilter/ipset/ip_set_getport.h> 22 + #define IP_SET_BITMAP_TIMEOUT 23 + #include <linux/netfilter/ipset/ip_set_timeout.h> 24 + 25 + MODULE_LICENSE("GPL"); 26 + MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 27 + MODULE_DESCRIPTION("bitmap:port type of IP sets"); 28 + MODULE_ALIAS("ip_set_bitmap:port"); 29 + 30 + /* Type structure */ 31 + struct bitmap_port { 32 + void *members; /* the set members */ 33 + u16 first_port; /* host byte order, included in range */ 34 + u16 last_port; /* host byte order, included in range */ 35 + size_t memsize; /* members size */ 36 + u32 timeout; /* timeout parameter */ 37 + struct timer_list gc; /* garbage collection */ 38 + }; 39 + 40 + /* Base variant */ 41 + 42 + static int 43 + bitmap_port_test(struct ip_set *set, void *value, u32 timeout) 44 + { 45 + const struct bitmap_port *map = set->data; 46 + u16 id = *(u16 *)value; 47 + 48 + return !!test_bit(id, map->members); 49 + } 50 + 51 + static int 52 + bitmap_port_add(struct ip_set *set, void *value, u32 timeout) 53 + { 54 + struct bitmap_port *map = set->data; 55 + u16 id = *(u16 *)value; 56 + 57 + if (test_and_set_bit(id, map->members)) 58 + return -IPSET_ERR_EXIST; 59 + 60 + return 0; 61 + } 62 + 63 + static int 64 + bitmap_port_del(struct ip_set *set, void *value, u32 timeout) 65 + { 66 + struct bitmap_port *map = set->data; 67 + u16 id = *(u16 *)value; 68 + 69 + if (!test_and_clear_bit(id, map->members)) 70 + return -IPSET_ERR_EXIST; 71 + 72 + return 0; 73 + } 74 + 75 + static int 76 + bitmap_port_list(const struct ip_set *set, 77 + struct sk_buff *skb, struct netlink_callback *cb) 78 + { 79 + const struct bitmap_port *map = set->data; 80 + struct nlattr *atd, *nested; 81 + u16 id, first = cb->args[2]; 82 + u16 last = map->last_port - map->first_port; 83 + 84 + atd = ipset_nest_start(skb, IPSET_ATTR_ADT); 85 + if (!atd) 86 + return -EMSGSIZE; 87 + for (; cb->args[2] <= last; cb->args[2]++) { 88 + id = cb->args[2]; 89 + if (!test_bit(id, map->members)) 90 + continue; 91 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 92 + if (!nested) { 93 + if (id == first) { 94 + nla_nest_cancel(skb, atd); 95 + return -EMSGSIZE; 96 + } else 97 + goto nla_put_failure; 98 + } 99 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, 100 + htons(map->first_port + id)); 101 + ipset_nest_end(skb, nested); 102 + } 103 + ipset_nest_end(skb, atd); 104 + /* Set listing finished */ 105 + cb->args[2] = 0; 106 + 107 + return 0; 108 + 109 + nla_put_failure: 110 + nla_nest_cancel(skb, nested); 111 + ipset_nest_end(skb, atd); 112 + if (unlikely(id == first)) { 113 + cb->args[2] = 0; 114 + return -EMSGSIZE; 115 + } 116 + return 0; 117 + } 118 + 119 + /* Timeout variant */ 120 + 121 + static int 122 + bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout) 123 + { 124 + const struct bitmap_port *map = set->data; 125 + const unsigned long *members = map->members; 126 + u16 id = *(u16 *)value; 127 + 128 + return ip_set_timeout_test(members[id]); 129 + } 130 + 131 + static int 132 + bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout) 133 + { 134 + struct bitmap_port *map = set->data; 135 + unsigned long *members = map->members; 136 + u16 id = *(u16 *)value; 137 + 138 + if (ip_set_timeout_test(members[id])) 139 + return -IPSET_ERR_EXIST; 140 + 141 + members[id] = ip_set_timeout_set(timeout); 142 + 143 + return 0; 144 + } 145 + 146 + static int 147 + bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout) 148 + { 149 + struct bitmap_port *map = set->data; 150 + unsigned long *members = map->members; 151 + u16 id = *(u16 *)value; 152 + int ret = -IPSET_ERR_EXIST; 153 + 154 + if (ip_set_timeout_test(members[id])) 155 + ret = 0; 156 + 157 + members[id] = IPSET_ELEM_UNSET; 158 + return ret; 159 + } 160 + 161 + static int 162 + bitmap_port_tlist(const struct ip_set *set, 163 + struct sk_buff *skb, struct netlink_callback *cb) 164 + { 165 + const struct bitmap_port *map = set->data; 166 + struct nlattr *adt, *nested; 167 + u16 id, first = cb->args[2]; 168 + u16 last = map->last_port - map->first_port; 169 + const unsigned long *members = map->members; 170 + 171 + adt = ipset_nest_start(skb, IPSET_ATTR_ADT); 172 + if (!adt) 173 + return -EMSGSIZE; 174 + for (; cb->args[2] <= last; cb->args[2]++) { 175 + id = cb->args[2]; 176 + if (!ip_set_timeout_test(members[id])) 177 + continue; 178 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 179 + if (!nested) { 180 + if (id == first) { 181 + nla_nest_cancel(skb, adt); 182 + return -EMSGSIZE; 183 + } else 184 + goto nla_put_failure; 185 + } 186 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, 187 + htons(map->first_port + id)); 188 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 189 + htonl(ip_set_timeout_get(members[id]))); 190 + ipset_nest_end(skb, nested); 191 + } 192 + ipset_nest_end(skb, adt); 193 + 194 + /* Set listing finished */ 195 + cb->args[2] = 0; 196 + 197 + return 0; 198 + 199 + nla_put_failure: 200 + nla_nest_cancel(skb, nested); 201 + ipset_nest_end(skb, adt); 202 + if (unlikely(id == first)) { 203 + cb->args[2] = 0; 204 + return -EMSGSIZE; 205 + } 206 + return 0; 207 + } 208 + 209 + static int 210 + bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb, 211 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 212 + { 213 + struct bitmap_port *map = set->data; 214 + ipset_adtfn adtfn = set->variant->adt[adt]; 215 + __be16 __port; 216 + u16 port = 0; 217 + 218 + if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port)) 219 + return -EINVAL; 220 + 221 + port = ntohs(__port); 222 + 223 + if (port < map->first_port || port > map->last_port) 224 + return -IPSET_ERR_BITMAP_RANGE; 225 + 226 + port -= map->first_port; 227 + 228 + return adtfn(set, &port, map->timeout); 229 + } 230 + 231 + static int 232 + bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[], 233 + enum ipset_adt adt, u32 *lineno, u32 flags) 234 + { 235 + struct bitmap_port *map = set->data; 236 + ipset_adtfn adtfn = set->variant->adt[adt]; 237 + u32 timeout = map->timeout; 238 + u32 port; /* wraparound */ 239 + u16 id, port_to; 240 + int ret = 0; 241 + 242 + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 243 + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 244 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 245 + return -IPSET_ERR_PROTOCOL; 246 + 247 + if (tb[IPSET_ATTR_LINENO]) 248 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 249 + 250 + port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); 251 + if (port < map->first_port || port > map->last_port) 252 + return -IPSET_ERR_BITMAP_RANGE; 253 + 254 + if (tb[IPSET_ATTR_TIMEOUT]) { 255 + if (!with_timeout(map->timeout)) 256 + return -IPSET_ERR_TIMEOUT; 257 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 258 + } 259 + 260 + if (adt == IPSET_TEST) { 261 + id = port - map->first_port; 262 + return adtfn(set, &id, timeout); 263 + } 264 + 265 + if (tb[IPSET_ATTR_PORT_TO]) { 266 + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 267 + if (port > port_to) { 268 + swap(port, port_to); 269 + if (port < map->first_port) 270 + return -IPSET_ERR_BITMAP_RANGE; 271 + } 272 + } else 273 + port_to = port; 274 + 275 + if (port_to > map->last_port) 276 + return -IPSET_ERR_BITMAP_RANGE; 277 + 278 + for (; port <= port_to; port++) { 279 + id = port - map->first_port; 280 + ret = adtfn(set, &id, timeout); 281 + 282 + if (ret && !ip_set_eexist(ret, flags)) 283 + return ret; 284 + else 285 + ret = 0; 286 + } 287 + return ret; 288 + } 289 + 290 + static void 291 + bitmap_port_destroy(struct ip_set *set) 292 + { 293 + struct bitmap_port *map = set->data; 294 + 295 + if (with_timeout(map->timeout)) 296 + del_timer_sync(&map->gc); 297 + 298 + ip_set_free(map->members); 299 + kfree(map); 300 + 301 + set->data = NULL; 302 + } 303 + 304 + static void 305 + bitmap_port_flush(struct ip_set *set) 306 + { 307 + struct bitmap_port *map = set->data; 308 + 309 + memset(map->members, 0, map->memsize); 310 + } 311 + 312 + static int 313 + bitmap_port_head(struct ip_set *set, struct sk_buff *skb) 314 + { 315 + const struct bitmap_port *map = set->data; 316 + struct nlattr *nested; 317 + 318 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 319 + if (!nested) 320 + goto nla_put_failure; 321 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port)); 322 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)); 323 + NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, 324 + htonl(atomic_read(&set->ref) - 1)); 325 + NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, 326 + htonl(sizeof(*map) + map->memsize)); 327 + if (with_timeout(map->timeout)) 328 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); 329 + ipset_nest_end(skb, nested); 330 + 331 + return 0; 332 + nla_put_failure: 333 + return -EMSGSIZE; 334 + } 335 + 336 + static bool 337 + bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b) 338 + { 339 + const struct bitmap_port *x = a->data; 340 + const struct bitmap_port *y = b->data; 341 + 342 + return x->first_port == y->first_port && 343 + x->last_port == y->last_port && 344 + x->timeout == y->timeout; 345 + } 346 + 347 + static const struct ip_set_type_variant bitmap_port = { 348 + .kadt = bitmap_port_kadt, 349 + .uadt = bitmap_port_uadt, 350 + .adt = { 351 + [IPSET_ADD] = bitmap_port_add, 352 + [IPSET_DEL] = bitmap_port_del, 353 + [IPSET_TEST] = bitmap_port_test, 354 + }, 355 + .destroy = bitmap_port_destroy, 356 + .flush = bitmap_port_flush, 357 + .head = bitmap_port_head, 358 + .list = bitmap_port_list, 359 + .same_set = bitmap_port_same_set, 360 + }; 361 + 362 + static const struct ip_set_type_variant bitmap_tport = { 363 + .kadt = bitmap_port_kadt, 364 + .uadt = bitmap_port_uadt, 365 + .adt = { 366 + [IPSET_ADD] = bitmap_port_tadd, 367 + [IPSET_DEL] = bitmap_port_tdel, 368 + [IPSET_TEST] = bitmap_port_ttest, 369 + }, 370 + .destroy = bitmap_port_destroy, 371 + .flush = bitmap_port_flush, 372 + .head = bitmap_port_head, 373 + .list = bitmap_port_tlist, 374 + .same_set = bitmap_port_same_set, 375 + }; 376 + 377 + static void 378 + bitmap_port_gc(unsigned long ul_set) 379 + { 380 + struct ip_set *set = (struct ip_set *) ul_set; 381 + struct bitmap_port *map = set->data; 382 + unsigned long *table = map->members; 383 + u32 id; /* wraparound */ 384 + u16 last = map->last_port - map->first_port; 385 + 386 + /* We run parallel with other readers (test element) 387 + * but adding/deleting new entries is locked out */ 388 + read_lock_bh(&set->lock); 389 + for (id = 0; id <= last; id++) 390 + if (ip_set_timeout_expired(table[id])) 391 + table[id] = IPSET_ELEM_UNSET; 392 + read_unlock_bh(&set->lock); 393 + 394 + map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 395 + add_timer(&map->gc); 396 + } 397 + 398 + static void 399 + bitmap_port_gc_init(struct ip_set *set) 400 + { 401 + struct bitmap_port *map = set->data; 402 + 403 + init_timer(&map->gc); 404 + map->gc.data = (unsigned long) set; 405 + map->gc.function = bitmap_port_gc; 406 + map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 407 + add_timer(&map->gc); 408 + } 409 + 410 + /* Create bitmap:ip type of sets */ 411 + 412 + static bool 413 + init_map_port(struct ip_set *set, struct bitmap_port *map, 414 + u16 first_port, u16 last_port) 415 + { 416 + map->members = ip_set_alloc(map->memsize); 417 + if (!map->members) 418 + return false; 419 + map->first_port = first_port; 420 + map->last_port = last_port; 421 + map->timeout = IPSET_NO_TIMEOUT; 422 + 423 + set->data = map; 424 + set->family = AF_UNSPEC; 425 + 426 + return true; 427 + } 428 + 429 + static int 430 + bitmap_port_create(struct ip_set *set, struct nlattr *tb[], 431 + u32 flags) 432 + { 433 + struct bitmap_port *map; 434 + u16 first_port, last_port; 435 + 436 + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 437 + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) || 438 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 439 + return -IPSET_ERR_PROTOCOL; 440 + 441 + first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); 442 + last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 443 + if (first_port > last_port) { 444 + u16 tmp = first_port; 445 + 446 + first_port = last_port; 447 + last_port = tmp; 448 + } 449 + 450 + map = kzalloc(sizeof(*map), GFP_KERNEL); 451 + if (!map) 452 + return -ENOMEM; 453 + 454 + if (tb[IPSET_ATTR_TIMEOUT]) { 455 + map->memsize = (last_port - first_port + 1) 456 + * sizeof(unsigned long); 457 + 458 + if (!init_map_port(set, map, first_port, last_port)) { 459 + kfree(map); 460 + return -ENOMEM; 461 + } 462 + 463 + map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 464 + set->variant = &bitmap_tport; 465 + 466 + bitmap_port_gc_init(set); 467 + } else { 468 + map->memsize = bitmap_bytes(0, last_port - first_port); 469 + pr_debug("memsize: %zu\n", map->memsize); 470 + if (!init_map_port(set, map, first_port, last_port)) { 471 + kfree(map); 472 + return -ENOMEM; 473 + } 474 + 475 + set->variant = &bitmap_port; 476 + } 477 + return 0; 478 + } 479 + 480 + static struct ip_set_type bitmap_port_type = { 481 + .name = "bitmap:port", 482 + .protocol = IPSET_PROTOCOL, 483 + .features = IPSET_TYPE_PORT, 484 + .dimension = IPSET_DIM_ONE, 485 + .family = AF_UNSPEC, 486 + .revision = 0, 487 + .create = bitmap_port_create, 488 + .create_policy = { 489 + [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 490 + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 491 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 492 + }, 493 + .adt_policy = { 494 + [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 495 + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 496 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 497 + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 498 + }, 499 + .me = THIS_MODULE, 500 + }; 501 + 502 + static int __init 503 + bitmap_port_init(void) 504 + { 505 + return ip_set_type_register(&bitmap_port_type); 506 + } 507 + 508 + static void __exit 509 + bitmap_port_fini(void) 510 + { 511 + ip_set_type_unregister(&bitmap_port_type); 512 + } 513 + 514 + module_init(bitmap_port_init); 515 + module_exit(bitmap_port_fini);
+1671
net/netfilter/ipset/ip_set_core.c
··· 1 + /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> 2 + * Patrick Schaaf <bof@bof.de> 3 + * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + */ 9 + 10 + /* Kernel module for IP set management */ 11 + 12 + #include <linux/init.h> 13 + #include <linux/module.h> 14 + #include <linux/moduleparam.h> 15 + #include <linux/ip.h> 16 + #include <linux/skbuff.h> 17 + #include <linux/spinlock.h> 18 + #include <linux/netlink.h> 19 + #include <linux/rculist.h> 20 + #include <linux/version.h> 21 + #include <net/netlink.h> 22 + 23 + #include <linux/netfilter.h> 24 + #include <linux/netfilter/nfnetlink.h> 25 + #include <linux/netfilter/ipset/ip_set.h> 26 + 27 + static LIST_HEAD(ip_set_type_list); /* all registered set types */ 28 + static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */ 29 + 30 + static struct ip_set **ip_set_list; /* all individual sets */ 31 + static ip_set_id_t ip_set_max = CONFIG_IP_SET_MAX; /* max number of sets */ 32 + 33 + #define STREQ(a, b) (strncmp(a, b, IPSET_MAXNAMELEN) == 0) 34 + 35 + static unsigned int max_sets; 36 + 37 + module_param(max_sets, int, 0600); 38 + MODULE_PARM_DESC(max_sets, "maximal number of sets"); 39 + MODULE_LICENSE("GPL"); 40 + MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 41 + MODULE_DESCRIPTION("core IP set support"); 42 + MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET); 43 + 44 + /* 45 + * The set types are implemented in modules and registered set types 46 + * can be found in ip_set_type_list. Adding/deleting types is 47 + * serialized by ip_set_type_mutex. 48 + */ 49 + 50 + static inline void 51 + ip_set_type_lock(void) 52 + { 53 + mutex_lock(&ip_set_type_mutex); 54 + } 55 + 56 + static inline void 57 + ip_set_type_unlock(void) 58 + { 59 + mutex_unlock(&ip_set_type_mutex); 60 + } 61 + 62 + /* Register and deregister settype */ 63 + 64 + static struct ip_set_type * 65 + find_set_type(const char *name, u8 family, u8 revision) 66 + { 67 + struct ip_set_type *type; 68 + 69 + list_for_each_entry_rcu(type, &ip_set_type_list, list) 70 + if (STREQ(type->name, name) && 71 + (type->family == family || type->family == AF_UNSPEC) && 72 + type->revision == revision) 73 + return type; 74 + return NULL; 75 + } 76 + 77 + /* Unlock, try to load a set type module and lock again */ 78 + static int 79 + try_to_load_type(const char *name) 80 + { 81 + nfnl_unlock(); 82 + pr_debug("try to load ip_set_%s\n", name); 83 + if (request_module("ip_set_%s", name) < 0) { 84 + pr_warning("Can't find ip_set type %s\n", name); 85 + nfnl_lock(); 86 + return -IPSET_ERR_FIND_TYPE; 87 + } 88 + nfnl_lock(); 89 + return -EAGAIN; 90 + } 91 + 92 + /* Find a set type and reference it */ 93 + static int 94 + find_set_type_get(const char *name, u8 family, u8 revision, 95 + struct ip_set_type **found) 96 + { 97 + rcu_read_lock(); 98 + *found = find_set_type(name, family, revision); 99 + if (*found) { 100 + int err = !try_module_get((*found)->me); 101 + rcu_read_unlock(); 102 + return err ? -EFAULT : 0; 103 + } 104 + rcu_read_unlock(); 105 + 106 + return try_to_load_type(name); 107 + } 108 + 109 + /* Find a given set type by name and family. 110 + * If we succeeded, the supported minimal and maximum revisions are 111 + * filled out. 112 + */ 113 + static int 114 + find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max) 115 + { 116 + struct ip_set_type *type; 117 + bool found = false; 118 + 119 + *min = *max = 0; 120 + rcu_read_lock(); 121 + list_for_each_entry_rcu(type, &ip_set_type_list, list) 122 + if (STREQ(type->name, name) && 123 + (type->family == family || type->family == AF_UNSPEC)) { 124 + found = true; 125 + if (type->revision < *min) 126 + *min = type->revision; 127 + else if (type->revision > *max) 128 + *max = type->revision; 129 + } 130 + rcu_read_unlock(); 131 + if (found) 132 + return 0; 133 + 134 + return try_to_load_type(name); 135 + } 136 + 137 + #define family_name(f) ((f) == AF_INET ? "inet" : \ 138 + (f) == AF_INET6 ? "inet6" : "any") 139 + 140 + /* Register a set type structure. The type is identified by 141 + * the unique triple of name, family and revision. 142 + */ 143 + int 144 + ip_set_type_register(struct ip_set_type *type) 145 + { 146 + int ret = 0; 147 + 148 + if (type->protocol != IPSET_PROTOCOL) { 149 + pr_warning("ip_set type %s, family %s, revision %u uses " 150 + "wrong protocol version %u (want %u)\n", 151 + type->name, family_name(type->family), 152 + type->revision, type->protocol, IPSET_PROTOCOL); 153 + return -EINVAL; 154 + } 155 + 156 + ip_set_type_lock(); 157 + if (find_set_type(type->name, type->family, type->revision)) { 158 + /* Duplicate! */ 159 + pr_warning("ip_set type %s, family %s, revision %u " 160 + "already registered!\n", type->name, 161 + family_name(type->family), type->revision); 162 + ret = -EINVAL; 163 + goto unlock; 164 + } 165 + list_add_rcu(&type->list, &ip_set_type_list); 166 + pr_debug("type %s, family %s, revision %u registered.\n", 167 + type->name, family_name(type->family), type->revision); 168 + unlock: 169 + ip_set_type_unlock(); 170 + return ret; 171 + } 172 + EXPORT_SYMBOL_GPL(ip_set_type_register); 173 + 174 + /* Unregister a set type. There's a small race with ip_set_create */ 175 + void 176 + ip_set_type_unregister(struct ip_set_type *type) 177 + { 178 + ip_set_type_lock(); 179 + if (!find_set_type(type->name, type->family, type->revision)) { 180 + pr_warning("ip_set type %s, family %s, revision %u " 181 + "not registered\n", type->name, 182 + family_name(type->family), type->revision); 183 + goto unlock; 184 + } 185 + list_del_rcu(&type->list); 186 + pr_debug("type %s, family %s, revision %u unregistered.\n", 187 + type->name, family_name(type->family), type->revision); 188 + unlock: 189 + ip_set_type_unlock(); 190 + 191 + synchronize_rcu(); 192 + } 193 + EXPORT_SYMBOL_GPL(ip_set_type_unregister); 194 + 195 + /* Utility functions */ 196 + void * 197 + ip_set_alloc(size_t size) 198 + { 199 + void *members = NULL; 200 + 201 + if (size < KMALLOC_MAX_SIZE) 202 + members = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); 203 + 204 + if (members) { 205 + pr_debug("%p: allocated with kmalloc\n", members); 206 + return members; 207 + } 208 + 209 + members = vzalloc(size); 210 + if (!members) 211 + return NULL; 212 + pr_debug("%p: allocated with vmalloc\n", members); 213 + 214 + return members; 215 + } 216 + EXPORT_SYMBOL_GPL(ip_set_alloc); 217 + 218 + void 219 + ip_set_free(void *members) 220 + { 221 + pr_debug("%p: free with %s\n", members, 222 + is_vmalloc_addr(members) ? "vfree" : "kfree"); 223 + if (is_vmalloc_addr(members)) 224 + vfree(members); 225 + else 226 + kfree(members); 227 + } 228 + EXPORT_SYMBOL_GPL(ip_set_free); 229 + 230 + static inline bool 231 + flag_nested(const struct nlattr *nla) 232 + { 233 + return nla->nla_type & NLA_F_NESTED; 234 + } 235 + 236 + static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = { 237 + [IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 }, 238 + [IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY, 239 + .len = sizeof(struct in6_addr) }, 240 + }; 241 + 242 + int 243 + ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr) 244 + { 245 + struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1]; 246 + 247 + if (unlikely(!flag_nested(nla))) 248 + return -IPSET_ERR_PROTOCOL; 249 + if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy)) 250 + return -IPSET_ERR_PROTOCOL; 251 + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV4))) 252 + return -IPSET_ERR_PROTOCOL; 253 + 254 + *ipaddr = nla_get_be32(tb[IPSET_ATTR_IPADDR_IPV4]); 255 + return 0; 256 + } 257 + EXPORT_SYMBOL_GPL(ip_set_get_ipaddr4); 258 + 259 + int 260 + ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr) 261 + { 262 + struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1]; 263 + 264 + if (unlikely(!flag_nested(nla))) 265 + return -IPSET_ERR_PROTOCOL; 266 + 267 + if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy)) 268 + return -IPSET_ERR_PROTOCOL; 269 + if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV6))) 270 + return -IPSET_ERR_PROTOCOL; 271 + 272 + memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]), 273 + sizeof(struct in6_addr)); 274 + return 0; 275 + } 276 + EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6); 277 + 278 + /* 279 + * Creating/destroying/renaming/swapping affect the existence and 280 + * the properties of a set. All of these can be executed from userspace 281 + * only and serialized by the nfnl mutex indirectly from nfnetlink. 282 + * 283 + * Sets are identified by their index in ip_set_list and the index 284 + * is used by the external references (set/SET netfilter modules). 285 + * 286 + * The set behind an index may change by swapping only, from userspace. 287 + */ 288 + 289 + static inline void 290 + __ip_set_get(ip_set_id_t index) 291 + { 292 + atomic_inc(&ip_set_list[index]->ref); 293 + } 294 + 295 + static inline void 296 + __ip_set_put(ip_set_id_t index) 297 + { 298 + atomic_dec(&ip_set_list[index]->ref); 299 + } 300 + 301 + /* 302 + * Add, del and test set entries from kernel. 303 + * 304 + * The set behind the index must exist and must be referenced 305 + * so it can't be destroyed (or changed) under our foot. 306 + */ 307 + 308 + int 309 + ip_set_test(ip_set_id_t index, const struct sk_buff *skb, 310 + u8 family, u8 dim, u8 flags) 311 + { 312 + struct ip_set *set = ip_set_list[index]; 313 + int ret = 0; 314 + 315 + BUG_ON(set == NULL || atomic_read(&set->ref) == 0); 316 + pr_debug("set %s, index %u\n", set->name, index); 317 + 318 + if (dim < set->type->dimension || 319 + !(family == set->family || set->family == AF_UNSPEC)) 320 + return 0; 321 + 322 + read_lock_bh(&set->lock); 323 + ret = set->variant->kadt(set, skb, IPSET_TEST, family, dim, flags); 324 + read_unlock_bh(&set->lock); 325 + 326 + if (ret == -EAGAIN) { 327 + /* Type requests element to be completed */ 328 + pr_debug("element must be competed, ADD is triggered\n"); 329 + write_lock_bh(&set->lock); 330 + set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags); 331 + write_unlock_bh(&set->lock); 332 + ret = 1; 333 + } 334 + 335 + /* Convert error codes to nomatch */ 336 + return (ret < 0 ? 0 : ret); 337 + } 338 + EXPORT_SYMBOL_GPL(ip_set_test); 339 + 340 + int 341 + ip_set_add(ip_set_id_t index, const struct sk_buff *skb, 342 + u8 family, u8 dim, u8 flags) 343 + { 344 + struct ip_set *set = ip_set_list[index]; 345 + int ret; 346 + 347 + BUG_ON(set == NULL || atomic_read(&set->ref) == 0); 348 + pr_debug("set %s, index %u\n", set->name, index); 349 + 350 + if (dim < set->type->dimension || 351 + !(family == set->family || set->family == AF_UNSPEC)) 352 + return 0; 353 + 354 + write_lock_bh(&set->lock); 355 + ret = set->variant->kadt(set, skb, IPSET_ADD, family, dim, flags); 356 + write_unlock_bh(&set->lock); 357 + 358 + return ret; 359 + } 360 + EXPORT_SYMBOL_GPL(ip_set_add); 361 + 362 + int 363 + ip_set_del(ip_set_id_t index, const struct sk_buff *skb, 364 + u8 family, u8 dim, u8 flags) 365 + { 366 + struct ip_set *set = ip_set_list[index]; 367 + int ret = 0; 368 + 369 + BUG_ON(set == NULL || atomic_read(&set->ref) == 0); 370 + pr_debug("set %s, index %u\n", set->name, index); 371 + 372 + if (dim < set->type->dimension || 373 + !(family == set->family || set->family == AF_UNSPEC)) 374 + return 0; 375 + 376 + write_lock_bh(&set->lock); 377 + ret = set->variant->kadt(set, skb, IPSET_DEL, family, dim, flags); 378 + write_unlock_bh(&set->lock); 379 + 380 + return ret; 381 + } 382 + EXPORT_SYMBOL_GPL(ip_set_del); 383 + 384 + /* 385 + * Find set by name, reference it once. The reference makes sure the 386 + * thing pointed to, does not go away under our feet. 387 + * 388 + * The nfnl mutex must already be activated. 389 + */ 390 + ip_set_id_t 391 + ip_set_get_byname(const char *name, struct ip_set **set) 392 + { 393 + ip_set_id_t i, index = IPSET_INVALID_ID; 394 + struct ip_set *s; 395 + 396 + for (i = 0; i < ip_set_max; i++) { 397 + s = ip_set_list[i]; 398 + if (s != NULL && STREQ(s->name, name)) { 399 + __ip_set_get(i); 400 + index = i; 401 + *set = s; 402 + } 403 + } 404 + 405 + return index; 406 + } 407 + EXPORT_SYMBOL_GPL(ip_set_get_byname); 408 + 409 + /* 410 + * If the given set pointer points to a valid set, decrement 411 + * reference count by 1. The caller shall not assume the index 412 + * to be valid, after calling this function. 413 + * 414 + * The nfnl mutex must already be activated. 415 + */ 416 + void 417 + ip_set_put_byindex(ip_set_id_t index) 418 + { 419 + if (ip_set_list[index] != NULL) { 420 + BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0); 421 + __ip_set_put(index); 422 + } 423 + } 424 + EXPORT_SYMBOL_GPL(ip_set_put_byindex); 425 + 426 + /* 427 + * Get the name of a set behind a set index. 428 + * We assume the set is referenced, so it does exist and 429 + * can't be destroyed. The set cannot be renamed due to 430 + * the referencing either. 431 + * 432 + * The nfnl mutex must already be activated. 433 + */ 434 + const char * 435 + ip_set_name_byindex(ip_set_id_t index) 436 + { 437 + const struct ip_set *set = ip_set_list[index]; 438 + 439 + BUG_ON(set == NULL); 440 + BUG_ON(atomic_read(&set->ref) == 0); 441 + 442 + /* Referenced, so it's safe */ 443 + return set->name; 444 + } 445 + EXPORT_SYMBOL_GPL(ip_set_name_byindex); 446 + 447 + /* 448 + * Routines to call by external subsystems, which do not 449 + * call nfnl_lock for us. 450 + */ 451 + 452 + /* 453 + * Find set by name, reference it once. The reference makes sure the 454 + * thing pointed to, does not go away under our feet. 455 + * 456 + * The nfnl mutex is used in the function. 457 + */ 458 + ip_set_id_t 459 + ip_set_nfnl_get(const char *name) 460 + { 461 + struct ip_set *s; 462 + ip_set_id_t index; 463 + 464 + nfnl_lock(); 465 + index = ip_set_get_byname(name, &s); 466 + nfnl_unlock(); 467 + 468 + return index; 469 + } 470 + EXPORT_SYMBOL_GPL(ip_set_nfnl_get); 471 + 472 + /* 473 + * Find set by index, reference it once. The reference makes sure the 474 + * thing pointed to, does not go away under our feet. 475 + * 476 + * The nfnl mutex is used in the function. 477 + */ 478 + ip_set_id_t 479 + ip_set_nfnl_get_byindex(ip_set_id_t index) 480 + { 481 + if (index > ip_set_max) 482 + return IPSET_INVALID_ID; 483 + 484 + nfnl_lock(); 485 + if (ip_set_list[index]) 486 + __ip_set_get(index); 487 + else 488 + index = IPSET_INVALID_ID; 489 + nfnl_unlock(); 490 + 491 + return index; 492 + } 493 + EXPORT_SYMBOL_GPL(ip_set_nfnl_get_byindex); 494 + 495 + /* 496 + * If the given set pointer points to a valid set, decrement 497 + * reference count by 1. The caller shall not assume the index 498 + * to be valid, after calling this function. 499 + * 500 + * The nfnl mutex is used in the function. 501 + */ 502 + void 503 + ip_set_nfnl_put(ip_set_id_t index) 504 + { 505 + nfnl_lock(); 506 + if (ip_set_list[index] != NULL) { 507 + BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0); 508 + __ip_set_put(index); 509 + } 510 + nfnl_unlock(); 511 + } 512 + EXPORT_SYMBOL_GPL(ip_set_nfnl_put); 513 + 514 + /* 515 + * Communication protocol with userspace over netlink. 516 + * 517 + * We already locked by nfnl_lock. 518 + */ 519 + 520 + static inline bool 521 + protocol_failed(const struct nlattr * const tb[]) 522 + { 523 + return !tb[IPSET_ATTR_PROTOCOL] || 524 + nla_get_u8(tb[IPSET_ATTR_PROTOCOL]) != IPSET_PROTOCOL; 525 + } 526 + 527 + static inline u32 528 + flag_exist(const struct nlmsghdr *nlh) 529 + { 530 + return nlh->nlmsg_flags & NLM_F_EXCL ? 0 : IPSET_FLAG_EXIST; 531 + } 532 + 533 + static struct nlmsghdr * 534 + start_msg(struct sk_buff *skb, u32 pid, u32 seq, unsigned int flags, 535 + enum ipset_cmd cmd) 536 + { 537 + struct nlmsghdr *nlh; 538 + struct nfgenmsg *nfmsg; 539 + 540 + nlh = nlmsg_put(skb, pid, seq, cmd | (NFNL_SUBSYS_IPSET << 8), 541 + sizeof(*nfmsg), flags); 542 + if (nlh == NULL) 543 + return NULL; 544 + 545 + nfmsg = nlmsg_data(nlh); 546 + nfmsg->nfgen_family = AF_INET; 547 + nfmsg->version = NFNETLINK_V0; 548 + nfmsg->res_id = 0; 549 + 550 + return nlh; 551 + } 552 + 553 + /* Create a set */ 554 + 555 + static const struct nla_policy ip_set_create_policy[IPSET_ATTR_CMD_MAX + 1] = { 556 + [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 }, 557 + [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING, 558 + .len = IPSET_MAXNAMELEN - 1 }, 559 + [IPSET_ATTR_TYPENAME] = { .type = NLA_NUL_STRING, 560 + .len = IPSET_MAXNAMELEN - 1}, 561 + [IPSET_ATTR_REVISION] = { .type = NLA_U8 }, 562 + [IPSET_ATTR_FAMILY] = { .type = NLA_U8 }, 563 + [IPSET_ATTR_DATA] = { .type = NLA_NESTED }, 564 + }; 565 + 566 + static ip_set_id_t 567 + find_set_id(const char *name) 568 + { 569 + ip_set_id_t i, index = IPSET_INVALID_ID; 570 + const struct ip_set *set; 571 + 572 + for (i = 0; index == IPSET_INVALID_ID && i < ip_set_max; i++) { 573 + set = ip_set_list[i]; 574 + if (set != NULL && STREQ(set->name, name)) 575 + index = i; 576 + } 577 + return index; 578 + } 579 + 580 + static inline struct ip_set * 581 + find_set(const char *name) 582 + { 583 + ip_set_id_t index = find_set_id(name); 584 + 585 + return index == IPSET_INVALID_ID ? NULL : ip_set_list[index]; 586 + } 587 + 588 + static int 589 + find_free_id(const char *name, ip_set_id_t *index, struct ip_set **set) 590 + { 591 + ip_set_id_t i; 592 + 593 + *index = IPSET_INVALID_ID; 594 + for (i = 0; i < ip_set_max; i++) { 595 + if (ip_set_list[i] == NULL) { 596 + if (*index == IPSET_INVALID_ID) 597 + *index = i; 598 + } else if (STREQ(name, ip_set_list[i]->name)) { 599 + /* Name clash */ 600 + *set = ip_set_list[i]; 601 + return -EEXIST; 602 + } 603 + } 604 + if (*index == IPSET_INVALID_ID) 605 + /* No free slot remained */ 606 + return -IPSET_ERR_MAX_SETS; 607 + return 0; 608 + } 609 + 610 + static int 611 + ip_set_create(struct sock *ctnl, struct sk_buff *skb, 612 + const struct nlmsghdr *nlh, 613 + const struct nlattr * const attr[]) 614 + { 615 + struct ip_set *set, *clash; 616 + ip_set_id_t index = IPSET_INVALID_ID; 617 + struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1] = {}; 618 + const char *name, *typename; 619 + u8 family, revision; 620 + u32 flags = flag_exist(nlh); 621 + int ret = 0; 622 + 623 + if (unlikely(protocol_failed(attr) || 624 + attr[IPSET_ATTR_SETNAME] == NULL || 625 + attr[IPSET_ATTR_TYPENAME] == NULL || 626 + attr[IPSET_ATTR_REVISION] == NULL || 627 + attr[IPSET_ATTR_FAMILY] == NULL || 628 + (attr[IPSET_ATTR_DATA] != NULL && 629 + !flag_nested(attr[IPSET_ATTR_DATA])))) 630 + return -IPSET_ERR_PROTOCOL; 631 + 632 + name = nla_data(attr[IPSET_ATTR_SETNAME]); 633 + typename = nla_data(attr[IPSET_ATTR_TYPENAME]); 634 + family = nla_get_u8(attr[IPSET_ATTR_FAMILY]); 635 + revision = nla_get_u8(attr[IPSET_ATTR_REVISION]); 636 + pr_debug("setname: %s, typename: %s, family: %s, revision: %u\n", 637 + name, typename, family_name(family), revision); 638 + 639 + /* 640 + * First, and without any locks, allocate and initialize 641 + * a normal base set structure. 642 + */ 643 + set = kzalloc(sizeof(struct ip_set), GFP_KERNEL); 644 + if (!set) 645 + return -ENOMEM; 646 + rwlock_init(&set->lock); 647 + strlcpy(set->name, name, IPSET_MAXNAMELEN); 648 + atomic_set(&set->ref, 0); 649 + set->family = family; 650 + 651 + /* 652 + * Next, check that we know the type, and take 653 + * a reference on the type, to make sure it stays available 654 + * while constructing our new set. 655 + * 656 + * After referencing the type, we try to create the type 657 + * specific part of the set without holding any locks. 658 + */ 659 + ret = find_set_type_get(typename, family, revision, &(set->type)); 660 + if (ret) 661 + goto out; 662 + 663 + /* 664 + * Without holding any locks, create private part. 665 + */ 666 + if (attr[IPSET_ATTR_DATA] && 667 + nla_parse_nested(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA], 668 + set->type->create_policy)) { 669 + ret = -IPSET_ERR_PROTOCOL; 670 + goto put_out; 671 + } 672 + 673 + ret = set->type->create(set, tb, flags); 674 + if (ret != 0) 675 + goto put_out; 676 + 677 + /* BTW, ret==0 here. */ 678 + 679 + /* 680 + * Here, we have a valid, constructed set and we are protected 681 + * by nfnl_lock. Find the first free index in ip_set_list and 682 + * check clashing. 683 + */ 684 + if ((ret = find_free_id(set->name, &index, &clash)) != 0) { 685 + /* If this is the same set and requested, ignore error */ 686 + if (ret == -EEXIST && 687 + (flags & IPSET_FLAG_EXIST) && 688 + STREQ(set->type->name, clash->type->name) && 689 + set->type->family == clash->type->family && 690 + set->type->revision == clash->type->revision && 691 + set->variant->same_set(set, clash)) 692 + ret = 0; 693 + goto cleanup; 694 + } 695 + 696 + /* 697 + * Finally! Add our shiny new set to the list, and be done. 698 + */ 699 + pr_debug("create: '%s' created with index %u!\n", set->name, index); 700 + ip_set_list[index] = set; 701 + 702 + return ret; 703 + 704 + cleanup: 705 + set->variant->destroy(set); 706 + put_out: 707 + module_put(set->type->me); 708 + out: 709 + kfree(set); 710 + return ret; 711 + } 712 + 713 + /* Destroy sets */ 714 + 715 + static const struct nla_policy 716 + ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = { 717 + [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 }, 718 + [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING, 719 + .len = IPSET_MAXNAMELEN - 1 }, 720 + }; 721 + 722 + static void 723 + ip_set_destroy_set(ip_set_id_t index) 724 + { 725 + struct ip_set *set = ip_set_list[index]; 726 + 727 + pr_debug("set: %s\n", set->name); 728 + ip_set_list[index] = NULL; 729 + 730 + /* Must call it without holding any lock */ 731 + set->variant->destroy(set); 732 + module_put(set->type->me); 733 + kfree(set); 734 + } 735 + 736 + static int 737 + ip_set_destroy(struct sock *ctnl, struct sk_buff *skb, 738 + const struct nlmsghdr *nlh, 739 + const struct nlattr * const attr[]) 740 + { 741 + ip_set_id_t i; 742 + 743 + if (unlikely(protocol_failed(attr))) 744 + return -IPSET_ERR_PROTOCOL; 745 + 746 + /* References are protected by the nfnl mutex */ 747 + if (!attr[IPSET_ATTR_SETNAME]) { 748 + for (i = 0; i < ip_set_max; i++) { 749 + if (ip_set_list[i] != NULL && 750 + (atomic_read(&ip_set_list[i]->ref))) 751 + return -IPSET_ERR_BUSY; 752 + } 753 + for (i = 0; i < ip_set_max; i++) { 754 + if (ip_set_list[i] != NULL) 755 + ip_set_destroy_set(i); 756 + } 757 + } else { 758 + i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); 759 + if (i == IPSET_INVALID_ID) 760 + return -ENOENT; 761 + else if (atomic_read(&ip_set_list[i]->ref)) 762 + return -IPSET_ERR_BUSY; 763 + 764 + ip_set_destroy_set(i); 765 + } 766 + return 0; 767 + } 768 + 769 + /* Flush sets */ 770 + 771 + static void 772 + ip_set_flush_set(struct ip_set *set) 773 + { 774 + pr_debug("set: %s\n", set->name); 775 + 776 + write_lock_bh(&set->lock); 777 + set->variant->flush(set); 778 + write_unlock_bh(&set->lock); 779 + } 780 + 781 + static int 782 + ip_set_flush(struct sock *ctnl, struct sk_buff *skb, 783 + const struct nlmsghdr *nlh, 784 + const struct nlattr * const attr[]) 785 + { 786 + ip_set_id_t i; 787 + 788 + if (unlikely(protocol_failed(attr))) 789 + return -EPROTO; 790 + 791 + if (!attr[IPSET_ATTR_SETNAME]) { 792 + for (i = 0; i < ip_set_max; i++) 793 + if (ip_set_list[i] != NULL) 794 + ip_set_flush_set(ip_set_list[i]); 795 + } else { 796 + i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); 797 + if (i == IPSET_INVALID_ID) 798 + return -ENOENT; 799 + 800 + ip_set_flush_set(ip_set_list[i]); 801 + } 802 + 803 + return 0; 804 + } 805 + 806 + /* Rename a set */ 807 + 808 + static const struct nla_policy 809 + ip_set_setname2_policy[IPSET_ATTR_CMD_MAX + 1] = { 810 + [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 }, 811 + [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING, 812 + .len = IPSET_MAXNAMELEN - 1 }, 813 + [IPSET_ATTR_SETNAME2] = { .type = NLA_NUL_STRING, 814 + .len = IPSET_MAXNAMELEN - 1 }, 815 + }; 816 + 817 + static int 818 + ip_set_rename(struct sock *ctnl, struct sk_buff *skb, 819 + const struct nlmsghdr *nlh, 820 + const struct nlattr * const attr[]) 821 + { 822 + struct ip_set *set; 823 + const char *name2; 824 + ip_set_id_t i; 825 + 826 + if (unlikely(protocol_failed(attr) || 827 + attr[IPSET_ATTR_SETNAME] == NULL || 828 + attr[IPSET_ATTR_SETNAME2] == NULL)) 829 + return -IPSET_ERR_PROTOCOL; 830 + 831 + set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); 832 + if (set == NULL) 833 + return -ENOENT; 834 + if (atomic_read(&set->ref) != 0) 835 + return -IPSET_ERR_REFERENCED; 836 + 837 + name2 = nla_data(attr[IPSET_ATTR_SETNAME2]); 838 + for (i = 0; i < ip_set_max; i++) { 839 + if (ip_set_list[i] != NULL && 840 + STREQ(ip_set_list[i]->name, name2)) 841 + return -IPSET_ERR_EXIST_SETNAME2; 842 + } 843 + strncpy(set->name, name2, IPSET_MAXNAMELEN); 844 + 845 + return 0; 846 + } 847 + 848 + /* Swap two sets so that name/index points to the other. 849 + * References and set names are also swapped. 850 + * 851 + * We are protected by the nfnl mutex and references are 852 + * manipulated only by holding the mutex. The kernel interfaces 853 + * do not hold the mutex but the pointer settings are atomic 854 + * so the ip_set_list always contains valid pointers to the sets. 855 + */ 856 + 857 + static int 858 + ip_set_swap(struct sock *ctnl, struct sk_buff *skb, 859 + const struct nlmsghdr *nlh, 860 + const struct nlattr * const attr[]) 861 + { 862 + struct ip_set *from, *to; 863 + ip_set_id_t from_id, to_id; 864 + char from_name[IPSET_MAXNAMELEN]; 865 + u32 from_ref; 866 + 867 + if (unlikely(protocol_failed(attr) || 868 + attr[IPSET_ATTR_SETNAME] == NULL || 869 + attr[IPSET_ATTR_SETNAME2] == NULL)) 870 + return -IPSET_ERR_PROTOCOL; 871 + 872 + from_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); 873 + if (from_id == IPSET_INVALID_ID) 874 + return -ENOENT; 875 + 876 + to_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME2])); 877 + if (to_id == IPSET_INVALID_ID) 878 + return -IPSET_ERR_EXIST_SETNAME2; 879 + 880 + from = ip_set_list[from_id]; 881 + to = ip_set_list[to_id]; 882 + 883 + /* Features must not change. 884 + * Not an artifical restriction anymore, as we must prevent 885 + * possible loops created by swapping in setlist type of sets. */ 886 + if (!(from->type->features == to->type->features && 887 + from->type->family == to->type->family)) 888 + return -IPSET_ERR_TYPE_MISMATCH; 889 + 890 + /* No magic here: ref munging protected by the nfnl_lock */ 891 + strncpy(from_name, from->name, IPSET_MAXNAMELEN); 892 + from_ref = atomic_read(&from->ref); 893 + 894 + strncpy(from->name, to->name, IPSET_MAXNAMELEN); 895 + atomic_set(&from->ref, atomic_read(&to->ref)); 896 + strncpy(to->name, from_name, IPSET_MAXNAMELEN); 897 + atomic_set(&to->ref, from_ref); 898 + 899 + ip_set_list[from_id] = to; 900 + ip_set_list[to_id] = from; 901 + 902 + return 0; 903 + } 904 + 905 + /* List/save set data */ 906 + 907 + #define DUMP_INIT 0L 908 + #define DUMP_ALL 1L 909 + #define DUMP_ONE 2L 910 + #define DUMP_LAST 3L 911 + 912 + static int 913 + ip_set_dump_done(struct netlink_callback *cb) 914 + { 915 + if (cb->args[2]) { 916 + pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name); 917 + __ip_set_put((ip_set_id_t) cb->args[1]); 918 + } 919 + return 0; 920 + } 921 + 922 + static inline void 923 + dump_attrs(struct nlmsghdr *nlh) 924 + { 925 + const struct nlattr *attr; 926 + int rem; 927 + 928 + pr_debug("dump nlmsg\n"); 929 + nlmsg_for_each_attr(attr, nlh, sizeof(struct nfgenmsg), rem) { 930 + pr_debug("type: %u, len %u\n", nla_type(attr), attr->nla_len); 931 + } 932 + } 933 + 934 + static int 935 + dump_init(struct netlink_callback *cb) 936 + { 937 + struct nlmsghdr *nlh = nlmsg_hdr(cb->skb); 938 + int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); 939 + struct nlattr *cda[IPSET_ATTR_CMD_MAX+1]; 940 + struct nlattr *attr = (void *)nlh + min_len; 941 + ip_set_id_t index; 942 + 943 + /* Second pass, so parser can't fail */ 944 + nla_parse(cda, IPSET_ATTR_CMD_MAX, 945 + attr, nlh->nlmsg_len - min_len, ip_set_setname_policy); 946 + 947 + /* cb->args[0] : dump single set/all sets 948 + * [1] : set index 949 + * [..]: type specific 950 + */ 951 + 952 + if (!cda[IPSET_ATTR_SETNAME]) { 953 + cb->args[0] = DUMP_ALL; 954 + return 0; 955 + } 956 + 957 + index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME])); 958 + if (index == IPSET_INVALID_ID) 959 + return -ENOENT; 960 + 961 + cb->args[0] = DUMP_ONE; 962 + cb->args[1] = index; 963 + return 0; 964 + } 965 + 966 + static int 967 + ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) 968 + { 969 + ip_set_id_t index = IPSET_INVALID_ID, max; 970 + struct ip_set *set = NULL; 971 + struct nlmsghdr *nlh = NULL; 972 + unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0; 973 + int ret = 0; 974 + 975 + if (cb->args[0] == DUMP_INIT) { 976 + ret = dump_init(cb); 977 + if (ret < 0) { 978 + nlh = nlmsg_hdr(cb->skb); 979 + /* We have to create and send the error message 980 + * manually :-( */ 981 + if (nlh->nlmsg_flags & NLM_F_ACK) 982 + netlink_ack(cb->skb, nlh, ret); 983 + return ret; 984 + } 985 + } 986 + 987 + if (cb->args[1] >= ip_set_max) 988 + goto out; 989 + 990 + pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]); 991 + max = cb->args[0] == DUMP_ONE ? cb->args[1] + 1 : ip_set_max; 992 + for (; cb->args[1] < max; cb->args[1]++) { 993 + index = (ip_set_id_t) cb->args[1]; 994 + set = ip_set_list[index]; 995 + if (set == NULL) { 996 + if (cb->args[0] == DUMP_ONE) { 997 + ret = -ENOENT; 998 + goto out; 999 + } 1000 + continue; 1001 + } 1002 + /* When dumping all sets, we must dump "sorted" 1003 + * so that lists (unions of sets) are dumped last. 1004 + */ 1005 + if (cb->args[0] != DUMP_ONE && 1006 + !((cb->args[0] == DUMP_ALL) ^ 1007 + (set->type->features & IPSET_DUMP_LAST))) 1008 + continue; 1009 + pr_debug("List set: %s\n", set->name); 1010 + if (!cb->args[2]) { 1011 + /* Start listing: make sure set won't be destroyed */ 1012 + pr_debug("reference set\n"); 1013 + __ip_set_get(index); 1014 + } 1015 + nlh = start_msg(skb, NETLINK_CB(cb->skb).pid, 1016 + cb->nlh->nlmsg_seq, flags, 1017 + IPSET_CMD_LIST); 1018 + if (!nlh) { 1019 + ret = -EMSGSIZE; 1020 + goto release_refcount; 1021 + } 1022 + NLA_PUT_U8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL); 1023 + NLA_PUT_STRING(skb, IPSET_ATTR_SETNAME, set->name); 1024 + switch (cb->args[2]) { 1025 + case 0: 1026 + /* Core header data */ 1027 + NLA_PUT_STRING(skb, IPSET_ATTR_TYPENAME, 1028 + set->type->name); 1029 + NLA_PUT_U8(skb, IPSET_ATTR_FAMILY, 1030 + set->family); 1031 + NLA_PUT_U8(skb, IPSET_ATTR_REVISION, 1032 + set->type->revision); 1033 + ret = set->variant->head(set, skb); 1034 + if (ret < 0) 1035 + goto release_refcount; 1036 + /* Fall through and add elements */ 1037 + default: 1038 + read_lock_bh(&set->lock); 1039 + ret = set->variant->list(set, skb, cb); 1040 + read_unlock_bh(&set->lock); 1041 + if (!cb->args[2]) { 1042 + /* Set is done, proceed with next one */ 1043 + if (cb->args[0] == DUMP_ONE) 1044 + cb->args[1] = IPSET_INVALID_ID; 1045 + else 1046 + cb->args[1]++; 1047 + } 1048 + goto release_refcount; 1049 + } 1050 + } 1051 + goto out; 1052 + 1053 + nla_put_failure: 1054 + ret = -EFAULT; 1055 + release_refcount: 1056 + /* If there was an error or set is done, release set */ 1057 + if (ret || !cb->args[2]) { 1058 + pr_debug("release set %s\n", ip_set_list[index]->name); 1059 + __ip_set_put(index); 1060 + } 1061 + 1062 + /* If we dump all sets, continue with dumping last ones */ 1063 + if (cb->args[0] == DUMP_ALL && cb->args[1] >= max && !cb->args[2]) 1064 + cb->args[0] = DUMP_LAST; 1065 + 1066 + out: 1067 + if (nlh) { 1068 + nlmsg_end(skb, nlh); 1069 + pr_debug("nlmsg_len: %u\n", nlh->nlmsg_len); 1070 + dump_attrs(nlh); 1071 + } 1072 + 1073 + return ret < 0 ? ret : skb->len; 1074 + } 1075 + 1076 + static int 1077 + ip_set_dump(struct sock *ctnl, struct sk_buff *skb, 1078 + const struct nlmsghdr *nlh, 1079 + const struct nlattr * const attr[]) 1080 + { 1081 + if (unlikely(protocol_failed(attr))) 1082 + return -IPSET_ERR_PROTOCOL; 1083 + 1084 + return netlink_dump_start(ctnl, skb, nlh, 1085 + ip_set_dump_start, 1086 + ip_set_dump_done); 1087 + } 1088 + 1089 + /* Add, del and test */ 1090 + 1091 + static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = { 1092 + [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 }, 1093 + [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING, 1094 + .len = IPSET_MAXNAMELEN - 1 }, 1095 + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 1096 + [IPSET_ATTR_DATA] = { .type = NLA_NESTED }, 1097 + [IPSET_ATTR_ADT] = { .type = NLA_NESTED }, 1098 + }; 1099 + 1100 + static int 1101 + call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, 1102 + struct nlattr *tb[], enum ipset_adt adt, 1103 + u32 flags, bool use_lineno) 1104 + { 1105 + int ret, retried = 0; 1106 + u32 lineno = 0; 1107 + bool eexist = flags & IPSET_FLAG_EXIST; 1108 + 1109 + do { 1110 + write_lock_bh(&set->lock); 1111 + ret = set->variant->uadt(set, tb, adt, &lineno, flags); 1112 + write_unlock_bh(&set->lock); 1113 + } while (ret == -EAGAIN && 1114 + set->variant->resize && 1115 + (ret = set->variant->resize(set, retried++)) == 0); 1116 + 1117 + if (!ret || (ret == -IPSET_ERR_EXIST && eexist)) 1118 + return 0; 1119 + if (lineno && use_lineno) { 1120 + /* Error in restore/batch mode: send back lineno */ 1121 + struct nlmsghdr *rep, *nlh = nlmsg_hdr(skb); 1122 + struct sk_buff *skb2; 1123 + struct nlmsgerr *errmsg; 1124 + size_t payload = sizeof(*errmsg) + nlmsg_len(nlh); 1125 + int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); 1126 + struct nlattr *cda[IPSET_ATTR_CMD_MAX+1]; 1127 + struct nlattr *cmdattr; 1128 + u32 *errline; 1129 + 1130 + skb2 = nlmsg_new(payload, GFP_KERNEL); 1131 + if (skb2 == NULL) 1132 + return -ENOMEM; 1133 + rep = __nlmsg_put(skb2, NETLINK_CB(skb).pid, 1134 + nlh->nlmsg_seq, NLMSG_ERROR, payload, 0); 1135 + errmsg = nlmsg_data(rep); 1136 + errmsg->error = ret; 1137 + memcpy(&errmsg->msg, nlh, nlh->nlmsg_len); 1138 + cmdattr = (void *)&errmsg->msg + min_len; 1139 + 1140 + nla_parse(cda, IPSET_ATTR_CMD_MAX, 1141 + cmdattr, nlh->nlmsg_len - min_len, 1142 + ip_set_adt_policy); 1143 + 1144 + errline = nla_data(cda[IPSET_ATTR_LINENO]); 1145 + 1146 + *errline = lineno; 1147 + 1148 + netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); 1149 + /* Signal netlink not to send its ACK/errmsg. */ 1150 + return -EINTR; 1151 + } 1152 + 1153 + return ret; 1154 + } 1155 + 1156 + static int 1157 + ip_set_uadd(struct sock *ctnl, struct sk_buff *skb, 1158 + const struct nlmsghdr *nlh, 1159 + const struct nlattr * const attr[]) 1160 + { 1161 + struct ip_set *set; 1162 + struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {}; 1163 + const struct nlattr *nla; 1164 + u32 flags = flag_exist(nlh); 1165 + bool use_lineno; 1166 + int ret = 0; 1167 + 1168 + if (unlikely(protocol_failed(attr) || 1169 + attr[IPSET_ATTR_SETNAME] == NULL || 1170 + !((attr[IPSET_ATTR_DATA] != NULL) ^ 1171 + (attr[IPSET_ATTR_ADT] != NULL)) || 1172 + (attr[IPSET_ATTR_DATA] != NULL && 1173 + !flag_nested(attr[IPSET_ATTR_DATA])) || 1174 + (attr[IPSET_ATTR_ADT] != NULL && 1175 + (!flag_nested(attr[IPSET_ATTR_ADT]) || 1176 + attr[IPSET_ATTR_LINENO] == NULL)))) 1177 + return -IPSET_ERR_PROTOCOL; 1178 + 1179 + set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); 1180 + if (set == NULL) 1181 + return -ENOENT; 1182 + 1183 + use_lineno = !!attr[IPSET_ATTR_LINENO]; 1184 + if (attr[IPSET_ATTR_DATA]) { 1185 + if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, 1186 + attr[IPSET_ATTR_DATA], 1187 + set->type->adt_policy)) 1188 + return -IPSET_ERR_PROTOCOL; 1189 + ret = call_ad(ctnl, skb, set, tb, IPSET_ADD, flags, 1190 + use_lineno); 1191 + } else { 1192 + int nla_rem; 1193 + 1194 + nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) { 1195 + memset(tb, 0, sizeof(tb)); 1196 + if (nla_type(nla) != IPSET_ATTR_DATA || 1197 + !flag_nested(nla) || 1198 + nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla, 1199 + set->type->adt_policy)) 1200 + return -IPSET_ERR_PROTOCOL; 1201 + ret = call_ad(ctnl, skb, set, tb, IPSET_ADD, 1202 + flags, use_lineno); 1203 + if (ret < 0) 1204 + return ret; 1205 + } 1206 + } 1207 + return ret; 1208 + } 1209 + 1210 + static int 1211 + ip_set_udel(struct sock *ctnl, struct sk_buff *skb, 1212 + const struct nlmsghdr *nlh, 1213 + const struct nlattr * const attr[]) 1214 + { 1215 + struct ip_set *set; 1216 + struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {}; 1217 + const struct nlattr *nla; 1218 + u32 flags = flag_exist(nlh); 1219 + bool use_lineno; 1220 + int ret = 0; 1221 + 1222 + if (unlikely(protocol_failed(attr) || 1223 + attr[IPSET_ATTR_SETNAME] == NULL || 1224 + !((attr[IPSET_ATTR_DATA] != NULL) ^ 1225 + (attr[IPSET_ATTR_ADT] != NULL)) || 1226 + (attr[IPSET_ATTR_DATA] != NULL && 1227 + !flag_nested(attr[IPSET_ATTR_DATA])) || 1228 + (attr[IPSET_ATTR_ADT] != NULL && 1229 + (!flag_nested(attr[IPSET_ATTR_ADT]) || 1230 + attr[IPSET_ATTR_LINENO] == NULL)))) 1231 + return -IPSET_ERR_PROTOCOL; 1232 + 1233 + set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); 1234 + if (set == NULL) 1235 + return -ENOENT; 1236 + 1237 + use_lineno = !!attr[IPSET_ATTR_LINENO]; 1238 + if (attr[IPSET_ATTR_DATA]) { 1239 + if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, 1240 + attr[IPSET_ATTR_DATA], 1241 + set->type->adt_policy)) 1242 + return -IPSET_ERR_PROTOCOL; 1243 + ret = call_ad(ctnl, skb, set, tb, IPSET_DEL, flags, 1244 + use_lineno); 1245 + } else { 1246 + int nla_rem; 1247 + 1248 + nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) { 1249 + memset(tb, 0, sizeof(*tb)); 1250 + if (nla_type(nla) != IPSET_ATTR_DATA || 1251 + !flag_nested(nla) || 1252 + nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla, 1253 + set->type->adt_policy)) 1254 + return -IPSET_ERR_PROTOCOL; 1255 + ret = call_ad(ctnl, skb, set, tb, IPSET_DEL, 1256 + flags, use_lineno); 1257 + if (ret < 0) 1258 + return ret; 1259 + } 1260 + } 1261 + return ret; 1262 + } 1263 + 1264 + static int 1265 + ip_set_utest(struct sock *ctnl, struct sk_buff *skb, 1266 + const struct nlmsghdr *nlh, 1267 + const struct nlattr * const attr[]) 1268 + { 1269 + struct ip_set *set; 1270 + struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {}; 1271 + int ret = 0; 1272 + 1273 + if (unlikely(protocol_failed(attr) || 1274 + attr[IPSET_ATTR_SETNAME] == NULL || 1275 + attr[IPSET_ATTR_DATA] == NULL || 1276 + !flag_nested(attr[IPSET_ATTR_DATA]))) 1277 + return -IPSET_ERR_PROTOCOL; 1278 + 1279 + set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); 1280 + if (set == NULL) 1281 + return -ENOENT; 1282 + 1283 + if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA], 1284 + set->type->adt_policy)) 1285 + return -IPSET_ERR_PROTOCOL; 1286 + 1287 + read_lock_bh(&set->lock); 1288 + ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0); 1289 + read_unlock_bh(&set->lock); 1290 + /* Userspace can't trigger element to be re-added */ 1291 + if (ret == -EAGAIN) 1292 + ret = 1; 1293 + 1294 + return ret < 0 ? ret : ret > 0 ? 0 : -IPSET_ERR_EXIST; 1295 + } 1296 + 1297 + /* Get headed data of a set */ 1298 + 1299 + static int 1300 + ip_set_header(struct sock *ctnl, struct sk_buff *skb, 1301 + const struct nlmsghdr *nlh, 1302 + const struct nlattr * const attr[]) 1303 + { 1304 + const struct ip_set *set; 1305 + struct sk_buff *skb2; 1306 + struct nlmsghdr *nlh2; 1307 + ip_set_id_t index; 1308 + int ret = 0; 1309 + 1310 + if (unlikely(protocol_failed(attr) || 1311 + attr[IPSET_ATTR_SETNAME] == NULL)) 1312 + return -IPSET_ERR_PROTOCOL; 1313 + 1314 + index = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); 1315 + if (index == IPSET_INVALID_ID) 1316 + return -ENOENT; 1317 + set = ip_set_list[index]; 1318 + 1319 + skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1320 + if (skb2 == NULL) 1321 + return -ENOMEM; 1322 + 1323 + nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 1324 + IPSET_CMD_HEADER); 1325 + if (!nlh2) 1326 + goto nlmsg_failure; 1327 + NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL); 1328 + NLA_PUT_STRING(skb2, IPSET_ATTR_SETNAME, set->name); 1329 + NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, set->type->name); 1330 + NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, set->family); 1331 + NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, set->type->revision); 1332 + nlmsg_end(skb2, nlh2); 1333 + 1334 + ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); 1335 + if (ret < 0) 1336 + return ret; 1337 + 1338 + return 0; 1339 + 1340 + nla_put_failure: 1341 + nlmsg_cancel(skb2, nlh2); 1342 + nlmsg_failure: 1343 + kfree_skb(skb2); 1344 + return -EMSGSIZE; 1345 + } 1346 + 1347 + /* Get type data */ 1348 + 1349 + static const struct nla_policy ip_set_type_policy[IPSET_ATTR_CMD_MAX + 1] = { 1350 + [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 }, 1351 + [IPSET_ATTR_TYPENAME] = { .type = NLA_NUL_STRING, 1352 + .len = IPSET_MAXNAMELEN - 1 }, 1353 + [IPSET_ATTR_FAMILY] = { .type = NLA_U8 }, 1354 + }; 1355 + 1356 + static int 1357 + ip_set_type(struct sock *ctnl, struct sk_buff *skb, 1358 + const struct nlmsghdr *nlh, 1359 + const struct nlattr * const attr[]) 1360 + { 1361 + struct sk_buff *skb2; 1362 + struct nlmsghdr *nlh2; 1363 + u8 family, min, max; 1364 + const char *typename; 1365 + int ret = 0; 1366 + 1367 + if (unlikely(protocol_failed(attr) || 1368 + attr[IPSET_ATTR_TYPENAME] == NULL || 1369 + attr[IPSET_ATTR_FAMILY] == NULL)) 1370 + return -IPSET_ERR_PROTOCOL; 1371 + 1372 + family = nla_get_u8(attr[IPSET_ATTR_FAMILY]); 1373 + typename = nla_data(attr[IPSET_ATTR_TYPENAME]); 1374 + ret = find_set_type_minmax(typename, family, &min, &max); 1375 + if (ret) 1376 + return ret; 1377 + 1378 + skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1379 + if (skb2 == NULL) 1380 + return -ENOMEM; 1381 + 1382 + nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 1383 + IPSET_CMD_TYPE); 1384 + if (!nlh2) 1385 + goto nlmsg_failure; 1386 + NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL); 1387 + NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, typename); 1388 + NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, family); 1389 + NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, max); 1390 + NLA_PUT_U8(skb2, IPSET_ATTR_REVISION_MIN, min); 1391 + nlmsg_end(skb2, nlh2); 1392 + 1393 + pr_debug("Send TYPE, nlmsg_len: %u\n", nlh2->nlmsg_len); 1394 + ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); 1395 + if (ret < 0) 1396 + return ret; 1397 + 1398 + return 0; 1399 + 1400 + nla_put_failure: 1401 + nlmsg_cancel(skb2, nlh2); 1402 + nlmsg_failure: 1403 + kfree_skb(skb2); 1404 + return -EMSGSIZE; 1405 + } 1406 + 1407 + /* Get protocol version */ 1408 + 1409 + static const struct nla_policy 1410 + ip_set_protocol_policy[IPSET_ATTR_CMD_MAX + 1] = { 1411 + [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 }, 1412 + }; 1413 + 1414 + static int 1415 + ip_set_protocol(struct sock *ctnl, struct sk_buff *skb, 1416 + const struct nlmsghdr *nlh, 1417 + const struct nlattr * const attr[]) 1418 + { 1419 + struct sk_buff *skb2; 1420 + struct nlmsghdr *nlh2; 1421 + int ret = 0; 1422 + 1423 + if (unlikely(attr[IPSET_ATTR_PROTOCOL] == NULL)) 1424 + return -IPSET_ERR_PROTOCOL; 1425 + 1426 + skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1427 + if (skb2 == NULL) 1428 + return -ENOMEM; 1429 + 1430 + nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 1431 + IPSET_CMD_PROTOCOL); 1432 + if (!nlh2) 1433 + goto nlmsg_failure; 1434 + NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL); 1435 + nlmsg_end(skb2, nlh2); 1436 + 1437 + ret = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); 1438 + if (ret < 0) 1439 + return ret; 1440 + 1441 + return 0; 1442 + 1443 + nla_put_failure: 1444 + nlmsg_cancel(skb2, nlh2); 1445 + nlmsg_failure: 1446 + kfree_skb(skb2); 1447 + return -EMSGSIZE; 1448 + } 1449 + 1450 + static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = { 1451 + [IPSET_CMD_CREATE] = { 1452 + .call = ip_set_create, 1453 + .attr_count = IPSET_ATTR_CMD_MAX, 1454 + .policy = ip_set_create_policy, 1455 + }, 1456 + [IPSET_CMD_DESTROY] = { 1457 + .call = ip_set_destroy, 1458 + .attr_count = IPSET_ATTR_CMD_MAX, 1459 + .policy = ip_set_setname_policy, 1460 + }, 1461 + [IPSET_CMD_FLUSH] = { 1462 + .call = ip_set_flush, 1463 + .attr_count = IPSET_ATTR_CMD_MAX, 1464 + .policy = ip_set_setname_policy, 1465 + }, 1466 + [IPSET_CMD_RENAME] = { 1467 + .call = ip_set_rename, 1468 + .attr_count = IPSET_ATTR_CMD_MAX, 1469 + .policy = ip_set_setname2_policy, 1470 + }, 1471 + [IPSET_CMD_SWAP] = { 1472 + .call = ip_set_swap, 1473 + .attr_count = IPSET_ATTR_CMD_MAX, 1474 + .policy = ip_set_setname2_policy, 1475 + }, 1476 + [IPSET_CMD_LIST] = { 1477 + .call = ip_set_dump, 1478 + .attr_count = IPSET_ATTR_CMD_MAX, 1479 + .policy = ip_set_setname_policy, 1480 + }, 1481 + [IPSET_CMD_SAVE] = { 1482 + .call = ip_set_dump, 1483 + .attr_count = IPSET_ATTR_CMD_MAX, 1484 + .policy = ip_set_setname_policy, 1485 + }, 1486 + [IPSET_CMD_ADD] = { 1487 + .call = ip_set_uadd, 1488 + .attr_count = IPSET_ATTR_CMD_MAX, 1489 + .policy = ip_set_adt_policy, 1490 + }, 1491 + [IPSET_CMD_DEL] = { 1492 + .call = ip_set_udel, 1493 + .attr_count = IPSET_ATTR_CMD_MAX, 1494 + .policy = ip_set_adt_policy, 1495 + }, 1496 + [IPSET_CMD_TEST] = { 1497 + .call = ip_set_utest, 1498 + .attr_count = IPSET_ATTR_CMD_MAX, 1499 + .policy = ip_set_adt_policy, 1500 + }, 1501 + [IPSET_CMD_HEADER] = { 1502 + .call = ip_set_header, 1503 + .attr_count = IPSET_ATTR_CMD_MAX, 1504 + .policy = ip_set_setname_policy, 1505 + }, 1506 + [IPSET_CMD_TYPE] = { 1507 + .call = ip_set_type, 1508 + .attr_count = IPSET_ATTR_CMD_MAX, 1509 + .policy = ip_set_type_policy, 1510 + }, 1511 + [IPSET_CMD_PROTOCOL] = { 1512 + .call = ip_set_protocol, 1513 + .attr_count = IPSET_ATTR_CMD_MAX, 1514 + .policy = ip_set_protocol_policy, 1515 + }, 1516 + }; 1517 + 1518 + static struct nfnetlink_subsystem ip_set_netlink_subsys __read_mostly = { 1519 + .name = "ip_set", 1520 + .subsys_id = NFNL_SUBSYS_IPSET, 1521 + .cb_count = IPSET_MSG_MAX, 1522 + .cb = ip_set_netlink_subsys_cb, 1523 + }; 1524 + 1525 + /* Interface to iptables/ip6tables */ 1526 + 1527 + static int 1528 + ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) 1529 + { 1530 + unsigned *op; 1531 + void *data; 1532 + int copylen = *len, ret = 0; 1533 + 1534 + if (!capable(CAP_NET_ADMIN)) 1535 + return -EPERM; 1536 + if (optval != SO_IP_SET) 1537 + return -EBADF; 1538 + if (*len < sizeof(unsigned)) 1539 + return -EINVAL; 1540 + 1541 + data = vmalloc(*len); 1542 + if (!data) 1543 + return -ENOMEM; 1544 + if (copy_from_user(data, user, *len) != 0) { 1545 + ret = -EFAULT; 1546 + goto done; 1547 + } 1548 + op = (unsigned *) data; 1549 + 1550 + if (*op < IP_SET_OP_VERSION) { 1551 + /* Check the version at the beginning of operations */ 1552 + struct ip_set_req_version *req_version = data; 1553 + if (req_version->version != IPSET_PROTOCOL) { 1554 + ret = -EPROTO; 1555 + goto done; 1556 + } 1557 + } 1558 + 1559 + switch (*op) { 1560 + case IP_SET_OP_VERSION: { 1561 + struct ip_set_req_version *req_version = data; 1562 + 1563 + if (*len != sizeof(struct ip_set_req_version)) { 1564 + ret = -EINVAL; 1565 + goto done; 1566 + } 1567 + 1568 + req_version->version = IPSET_PROTOCOL; 1569 + ret = copy_to_user(user, req_version, 1570 + sizeof(struct ip_set_req_version)); 1571 + goto done; 1572 + } 1573 + case IP_SET_OP_GET_BYNAME: { 1574 + struct ip_set_req_get_set *req_get = data; 1575 + 1576 + if (*len != sizeof(struct ip_set_req_get_set)) { 1577 + ret = -EINVAL; 1578 + goto done; 1579 + } 1580 + req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0'; 1581 + nfnl_lock(); 1582 + req_get->set.index = find_set_id(req_get->set.name); 1583 + nfnl_unlock(); 1584 + goto copy; 1585 + } 1586 + case IP_SET_OP_GET_BYINDEX: { 1587 + struct ip_set_req_get_set *req_get = data; 1588 + 1589 + if (*len != sizeof(struct ip_set_req_get_set) || 1590 + req_get->set.index >= ip_set_max) { 1591 + ret = -EINVAL; 1592 + goto done; 1593 + } 1594 + nfnl_lock(); 1595 + strncpy(req_get->set.name, 1596 + ip_set_list[req_get->set.index] 1597 + ? ip_set_list[req_get->set.index]->name : "", 1598 + IPSET_MAXNAMELEN); 1599 + nfnl_unlock(); 1600 + goto copy; 1601 + } 1602 + default: 1603 + ret = -EBADMSG; 1604 + goto done; 1605 + } /* end of switch(op) */ 1606 + 1607 + copy: 1608 + ret = copy_to_user(user, data, copylen); 1609 + 1610 + done: 1611 + vfree(data); 1612 + if (ret > 0) 1613 + ret = 0; 1614 + return ret; 1615 + } 1616 + 1617 + static struct nf_sockopt_ops so_set __read_mostly = { 1618 + .pf = PF_INET, 1619 + .get_optmin = SO_IP_SET, 1620 + .get_optmax = SO_IP_SET + 1, 1621 + .get = &ip_set_sockfn_get, 1622 + .owner = THIS_MODULE, 1623 + }; 1624 + 1625 + static int __init 1626 + ip_set_init(void) 1627 + { 1628 + int ret; 1629 + 1630 + if (max_sets) 1631 + ip_set_max = max_sets; 1632 + if (ip_set_max >= IPSET_INVALID_ID) 1633 + ip_set_max = IPSET_INVALID_ID - 1; 1634 + 1635 + ip_set_list = kzalloc(sizeof(struct ip_set *) * ip_set_max, 1636 + GFP_KERNEL); 1637 + if (!ip_set_list) { 1638 + pr_err("ip_set: Unable to create ip_set_list\n"); 1639 + return -ENOMEM; 1640 + } 1641 + 1642 + ret = nfnetlink_subsys_register(&ip_set_netlink_subsys); 1643 + if (ret != 0) { 1644 + pr_err("ip_set: cannot register with nfnetlink.\n"); 1645 + kfree(ip_set_list); 1646 + return ret; 1647 + } 1648 + ret = nf_register_sockopt(&so_set); 1649 + if (ret != 0) { 1650 + pr_err("SO_SET registry failed: %d\n", ret); 1651 + nfnetlink_subsys_unregister(&ip_set_netlink_subsys); 1652 + kfree(ip_set_list); 1653 + return ret; 1654 + } 1655 + 1656 + pr_notice("ip_set: protocol %u\n", IPSET_PROTOCOL); 1657 + return 0; 1658 + } 1659 + 1660 + static void __exit 1661 + ip_set_fini(void) 1662 + { 1663 + /* There can't be any existing set */ 1664 + nf_unregister_sockopt(&so_set); 1665 + nfnetlink_subsys_unregister(&ip_set_netlink_subsys); 1666 + kfree(ip_set_list); 1667 + pr_debug("these are the famous last words\n"); 1668 + } 1669 + 1670 + module_init(ip_set_init); 1671 + module_exit(ip_set_fini);
+141
net/netfilter/ipset/ip_set_getport.c
··· 1 + /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 2 + * 3 + * This program is free software; you can redistribute it and/or modify 4 + * it under the terms of the GNU General Public License version 2 as 5 + * published by the Free Software Foundation. 6 + */ 7 + 8 + /* Get Layer-4 data from the packets */ 9 + 10 + #include <linux/ip.h> 11 + #include <linux/skbuff.h> 12 + #include <linux/icmp.h> 13 + #include <linux/icmpv6.h> 14 + #include <linux/netfilter_ipv6/ip6_tables.h> 15 + #include <net/ip.h> 16 + #include <net/ipv6.h> 17 + 18 + #include <linux/netfilter/ipset/ip_set_getport.h> 19 + 20 + /* We must handle non-linear skbs */ 21 + static bool 22 + get_port(const struct sk_buff *skb, int protocol, unsigned int protooff, 23 + bool src, __be16 *port, u8 *proto) 24 + { 25 + switch (protocol) { 26 + case IPPROTO_TCP: { 27 + struct tcphdr _tcph; 28 + const struct tcphdr *th; 29 + 30 + th = skb_header_pointer(skb, protooff, sizeof(_tcph), &_tcph); 31 + if (th == NULL) 32 + /* No choice either */ 33 + return false; 34 + 35 + *port = src ? th->source : th->dest; 36 + break; 37 + } 38 + case IPPROTO_UDP: { 39 + struct udphdr _udph; 40 + const struct udphdr *uh; 41 + 42 + uh = skb_header_pointer(skb, protooff, sizeof(_udph), &_udph); 43 + if (uh == NULL) 44 + /* No choice either */ 45 + return false; 46 + 47 + *port = src ? uh->source : uh->dest; 48 + break; 49 + } 50 + case IPPROTO_ICMP: { 51 + struct icmphdr _ich; 52 + const struct icmphdr *ic; 53 + 54 + ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich); 55 + if (ic == NULL) 56 + return false; 57 + 58 + *port = (__force __be16)htons((ic->type << 8) | ic->code); 59 + break; 60 + } 61 + case IPPROTO_ICMPV6: { 62 + struct icmp6hdr _ich; 63 + const struct icmp6hdr *ic; 64 + 65 + ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich); 66 + if (ic == NULL) 67 + return false; 68 + 69 + *port = (__force __be16) 70 + htons((ic->icmp6_type << 8) | ic->icmp6_code); 71 + break; 72 + } 73 + default: 74 + break; 75 + } 76 + *proto = protocol; 77 + 78 + return true; 79 + } 80 + 81 + bool 82 + ip_set_get_ip4_port(const struct sk_buff *skb, bool src, 83 + __be16 *port, u8 *proto) 84 + { 85 + const struct iphdr *iph = ip_hdr(skb); 86 + unsigned int protooff = ip_hdrlen(skb); 87 + int protocol = iph->protocol; 88 + 89 + /* See comments at tcp_match in ip_tables.c */ 90 + if (protocol <= 0 || (ntohs(iph->frag_off) & IP_OFFSET)) 91 + return false; 92 + 93 + return get_port(skb, protocol, protooff, src, port, proto); 94 + } 95 + EXPORT_SYMBOL_GPL(ip_set_get_ip4_port); 96 + 97 + #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) 98 + bool 99 + ip_set_get_ip6_port(const struct sk_buff *skb, bool src, 100 + __be16 *port, u8 *proto) 101 + { 102 + int protoff; 103 + u8 nexthdr; 104 + 105 + nexthdr = ipv6_hdr(skb)->nexthdr; 106 + protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr); 107 + if (protoff < 0) 108 + return false; 109 + 110 + return get_port(skb, nexthdr, protoff, src, port, proto); 111 + } 112 + EXPORT_SYMBOL_GPL(ip_set_get_ip6_port); 113 + #endif 114 + 115 + bool 116 + ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port) 117 + { 118 + bool ret; 119 + u8 proto; 120 + 121 + switch (pf) { 122 + case AF_INET: 123 + ret = ip_set_get_ip4_port(skb, src, port, &proto); 124 + break; 125 + case AF_INET6: 126 + ret = ip_set_get_ip6_port(skb, src, port, &proto); 127 + break; 128 + default: 129 + return false; 130 + } 131 + if (!ret) 132 + return ret; 133 + switch (proto) { 134 + case IPPROTO_TCP: 135 + case IPPROTO_UDP: 136 + return true; 137 + default: 138 + return false; 139 + } 140 + } 141 + EXPORT_SYMBOL_GPL(ip_set_get_ip_port);
+464
net/netfilter/ipset/ip_set_hash_ip.c
··· 1 + /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 2 + * 3 + * This program is free software; you can redistribute it and/or modify 4 + * it under the terms of the GNU General Public License version 2 as 5 + * published by the Free Software Foundation. 6 + */ 7 + 8 + /* Kernel module implementing an IP set type: the hash:ip type */ 9 + 10 + #include <linux/jhash.h> 11 + #include <linux/module.h> 12 + #include <linux/ip.h> 13 + #include <linux/skbuff.h> 14 + #include <linux/errno.h> 15 + #include <linux/random.h> 16 + #include <net/ip.h> 17 + #include <net/ipv6.h> 18 + #include <net/netlink.h> 19 + #include <net/tcp.h> 20 + 21 + #include <linux/netfilter.h> 22 + #include <linux/netfilter/ipset/pfxlen.h> 23 + #include <linux/netfilter/ipset/ip_set.h> 24 + #include <linux/netfilter/ipset/ip_set_timeout.h> 25 + #include <linux/netfilter/ipset/ip_set_hash.h> 26 + 27 + MODULE_LICENSE("GPL"); 28 + MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 29 + MODULE_DESCRIPTION("hash:ip type of IP sets"); 30 + MODULE_ALIAS("ip_set_hash:ip"); 31 + 32 + /* Type specific function prefix */ 33 + #define TYPE hash_ip 34 + 35 + static bool 36 + hash_ip_same_set(const struct ip_set *a, const struct ip_set *b); 37 + 38 + #define hash_ip4_same_set hash_ip_same_set 39 + #define hash_ip6_same_set hash_ip_same_set 40 + 41 + /* The type variant functions: IPv4 */ 42 + 43 + /* Member elements without timeout */ 44 + struct hash_ip4_elem { 45 + __be32 ip; 46 + }; 47 + 48 + /* Member elements with timeout support */ 49 + struct hash_ip4_telem { 50 + __be32 ip; 51 + unsigned long timeout; 52 + }; 53 + 54 + static inline bool 55 + hash_ip4_data_equal(const struct hash_ip4_elem *ip1, 56 + const struct hash_ip4_elem *ip2) 57 + { 58 + return ip1->ip == ip2->ip; 59 + } 60 + 61 + static inline bool 62 + hash_ip4_data_isnull(const struct hash_ip4_elem *elem) 63 + { 64 + return elem->ip == 0; 65 + } 66 + 67 + static inline void 68 + hash_ip4_data_copy(struct hash_ip4_elem *dst, const struct hash_ip4_elem *src) 69 + { 70 + dst->ip = src->ip; 71 + } 72 + 73 + /* Zero valued IP addresses cannot be stored */ 74 + static inline void 75 + hash_ip4_data_zero_out(struct hash_ip4_elem *elem) 76 + { 77 + elem->ip = 0; 78 + } 79 + 80 + static inline bool 81 + hash_ip4_data_list(struct sk_buff *skb, const struct hash_ip4_elem *data) 82 + { 83 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); 84 + return 0; 85 + 86 + nla_put_failure: 87 + return 1; 88 + } 89 + 90 + static bool 91 + hash_ip4_data_tlist(struct sk_buff *skb, const struct hash_ip4_elem *data) 92 + { 93 + const struct hash_ip4_telem *tdata = 94 + (const struct hash_ip4_telem *)data; 95 + 96 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); 97 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 98 + htonl(ip_set_timeout_get(tdata->timeout))); 99 + 100 + return 0; 101 + 102 + nla_put_failure: 103 + return 1; 104 + } 105 + 106 + #define IP_SET_HASH_WITH_NETMASK 107 + #define PF 4 108 + #define HOST_MASK 32 109 + #include <linux/netfilter/ipset/ip_set_ahash.h> 110 + 111 + static int 112 + hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb, 113 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 114 + { 115 + const struct ip_set_hash *h = set->data; 116 + ipset_adtfn adtfn = set->variant->adt[adt]; 117 + __be32 ip; 118 + 119 + ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip); 120 + ip &= ip_set_netmask(h->netmask); 121 + if (ip == 0) 122 + return -EINVAL; 123 + 124 + return adtfn(set, &ip, h->timeout); 125 + } 126 + 127 + static int 128 + hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], 129 + enum ipset_adt adt, u32 *lineno, u32 flags) 130 + { 131 + const struct ip_set_hash *h = set->data; 132 + ipset_adtfn adtfn = set->variant->adt[adt]; 133 + u32 ip, ip_to, hosts, timeout = h->timeout; 134 + __be32 nip; 135 + int ret = 0; 136 + 137 + if (unlikely(!tb[IPSET_ATTR_IP] || 138 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 139 + return -IPSET_ERR_PROTOCOL; 140 + 141 + if (tb[IPSET_ATTR_LINENO]) 142 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 143 + 144 + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); 145 + if (ret) 146 + return ret; 147 + 148 + ip &= ip_set_hostmask(h->netmask); 149 + 150 + if (tb[IPSET_ATTR_TIMEOUT]) { 151 + if (!with_timeout(h->timeout)) 152 + return -IPSET_ERR_TIMEOUT; 153 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 154 + } 155 + 156 + if (adt == IPSET_TEST) { 157 + nip = htonl(ip); 158 + if (nip == 0) 159 + return -IPSET_ERR_HASH_ELEM; 160 + return adtfn(set, &nip, timeout); 161 + } 162 + 163 + if (tb[IPSET_ATTR_IP_TO]) { 164 + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 165 + if (ret) 166 + return ret; 167 + if (ip > ip_to) 168 + swap(ip, ip_to); 169 + } else if (tb[IPSET_ATTR_CIDR]) { 170 + u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 171 + 172 + if (cidr > 32) 173 + return -IPSET_ERR_INVALID_CIDR; 174 + ip &= ip_set_hostmask(cidr); 175 + ip_to = ip | ~ip_set_hostmask(cidr); 176 + } else 177 + ip_to = ip; 178 + 179 + hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); 180 + 181 + for (; !before(ip_to, ip); ip += hosts) { 182 + nip = htonl(ip); 183 + if (nip == 0) 184 + return -IPSET_ERR_HASH_ELEM; 185 + ret = adtfn(set, &nip, timeout); 186 + 187 + if (ret && !ip_set_eexist(ret, flags)) 188 + return ret; 189 + else 190 + ret = 0; 191 + } 192 + return ret; 193 + } 194 + 195 + static bool 196 + hash_ip_same_set(const struct ip_set *a, const struct ip_set *b) 197 + { 198 + const struct ip_set_hash *x = a->data; 199 + const struct ip_set_hash *y = b->data; 200 + 201 + /* Resizing changes htable_bits, so we ignore it */ 202 + return x->maxelem == y->maxelem && 203 + x->timeout == y->timeout && 204 + x->netmask == y->netmask; 205 + } 206 + 207 + /* The type variant functions: IPv6 */ 208 + 209 + struct hash_ip6_elem { 210 + union nf_inet_addr ip; 211 + }; 212 + 213 + struct hash_ip6_telem { 214 + union nf_inet_addr ip; 215 + unsigned long timeout; 216 + }; 217 + 218 + static inline bool 219 + hash_ip6_data_equal(const struct hash_ip6_elem *ip1, 220 + const struct hash_ip6_elem *ip2) 221 + { 222 + return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0; 223 + } 224 + 225 + static inline bool 226 + hash_ip6_data_isnull(const struct hash_ip6_elem *elem) 227 + { 228 + return ipv6_addr_any(&elem->ip.in6); 229 + } 230 + 231 + static inline void 232 + hash_ip6_data_copy(struct hash_ip6_elem *dst, const struct hash_ip6_elem *src) 233 + { 234 + ipv6_addr_copy(&dst->ip.in6, &src->ip.in6); 235 + } 236 + 237 + static inline void 238 + hash_ip6_data_zero_out(struct hash_ip6_elem *elem) 239 + { 240 + ipv6_addr_set(&elem->ip.in6, 0, 0, 0, 0); 241 + } 242 + 243 + static inline void 244 + ip6_netmask(union nf_inet_addr *ip, u8 prefix) 245 + { 246 + ip->ip6[0] &= ip_set_netmask6(prefix)[0]; 247 + ip->ip6[1] &= ip_set_netmask6(prefix)[1]; 248 + ip->ip6[2] &= ip_set_netmask6(prefix)[2]; 249 + ip->ip6[3] &= ip_set_netmask6(prefix)[3]; 250 + } 251 + 252 + static bool 253 + hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *data) 254 + { 255 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); 256 + return 0; 257 + 258 + nla_put_failure: 259 + return 1; 260 + } 261 + 262 + static bool 263 + hash_ip6_data_tlist(struct sk_buff *skb, const struct hash_ip6_elem *data) 264 + { 265 + const struct hash_ip6_telem *e = 266 + (const struct hash_ip6_telem *)data; 267 + 268 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); 269 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 270 + htonl(ip_set_timeout_get(e->timeout))); 271 + return 0; 272 + 273 + nla_put_failure: 274 + return 1; 275 + } 276 + 277 + #undef PF 278 + #undef HOST_MASK 279 + 280 + #define PF 6 281 + #define HOST_MASK 128 282 + #include <linux/netfilter/ipset/ip_set_ahash.h> 283 + 284 + static int 285 + hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb, 286 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 287 + { 288 + const struct ip_set_hash *h = set->data; 289 + ipset_adtfn adtfn = set->variant->adt[adt]; 290 + union nf_inet_addr ip; 291 + 292 + ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &ip.in6); 293 + ip6_netmask(&ip, h->netmask); 294 + if (ipv6_addr_any(&ip.in6)) 295 + return -EINVAL; 296 + 297 + return adtfn(set, &ip, h->timeout); 298 + } 299 + 300 + static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = { 301 + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 302 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 303 + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 304 + }; 305 + 306 + static int 307 + hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[], 308 + enum ipset_adt adt, u32 *lineno, u32 flags) 309 + { 310 + const struct ip_set_hash *h = set->data; 311 + ipset_adtfn adtfn = set->variant->adt[adt]; 312 + union nf_inet_addr ip; 313 + u32 timeout = h->timeout; 314 + int ret; 315 + 316 + if (unlikely(!tb[IPSET_ATTR_IP] || 317 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 318 + tb[IPSET_ATTR_IP_TO] || 319 + tb[IPSET_ATTR_CIDR])) 320 + return -IPSET_ERR_PROTOCOL; 321 + 322 + if (tb[IPSET_ATTR_LINENO]) 323 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 324 + 325 + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &ip); 326 + if (ret) 327 + return ret; 328 + 329 + ip6_netmask(&ip, h->netmask); 330 + if (ipv6_addr_any(&ip.in6)) 331 + return -IPSET_ERR_HASH_ELEM; 332 + 333 + if (tb[IPSET_ATTR_TIMEOUT]) { 334 + if (!with_timeout(h->timeout)) 335 + return -IPSET_ERR_TIMEOUT; 336 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 337 + } 338 + 339 + ret = adtfn(set, &ip, timeout); 340 + 341 + return ip_set_eexist(ret, flags) ? 0 : ret; 342 + } 343 + 344 + /* Create hash:ip type of sets */ 345 + 346 + static int 347 + hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) 348 + { 349 + u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; 350 + u8 netmask, hbits; 351 + struct ip_set_hash *h; 352 + 353 + if (!(set->family == AF_INET || set->family == AF_INET6)) 354 + return -IPSET_ERR_INVALID_FAMILY; 355 + netmask = set->family == AF_INET ? 32 : 128; 356 + pr_debug("Create set %s with family %s\n", 357 + set->name, set->family == AF_INET ? "inet" : "inet6"); 358 + 359 + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || 360 + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || 361 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 362 + return -IPSET_ERR_PROTOCOL; 363 + 364 + if (tb[IPSET_ATTR_HASHSIZE]) { 365 + hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); 366 + if (hashsize < IPSET_MIMINAL_HASHSIZE) 367 + hashsize = IPSET_MIMINAL_HASHSIZE; 368 + } 369 + 370 + if (tb[IPSET_ATTR_MAXELEM]) 371 + maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]); 372 + 373 + if (tb[IPSET_ATTR_NETMASK]) { 374 + netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]); 375 + 376 + if ((set->family == AF_INET && netmask > 32) || 377 + (set->family == AF_INET6 && netmask > 128) || 378 + netmask == 0) 379 + return -IPSET_ERR_INVALID_NETMASK; 380 + } 381 + 382 + h = kzalloc(sizeof(*h), GFP_KERNEL); 383 + if (!h) 384 + return -ENOMEM; 385 + 386 + h->maxelem = maxelem; 387 + h->netmask = netmask; 388 + get_random_bytes(&h->initval, sizeof(h->initval)); 389 + h->timeout = IPSET_NO_TIMEOUT; 390 + 391 + hbits = htable_bits(hashsize); 392 + h->table = ip_set_alloc( 393 + sizeof(struct htable) 394 + + jhash_size(hbits) * sizeof(struct hbucket)); 395 + if (!h->table) { 396 + kfree(h); 397 + return -ENOMEM; 398 + } 399 + h->table->htable_bits = hbits; 400 + 401 + set->data = h; 402 + 403 + if (tb[IPSET_ATTR_TIMEOUT]) { 404 + h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 405 + 406 + set->variant = set->family == AF_INET 407 + ? &hash_ip4_tvariant : &hash_ip6_tvariant; 408 + 409 + if (set->family == AF_INET) 410 + hash_ip4_gc_init(set); 411 + else 412 + hash_ip6_gc_init(set); 413 + } else { 414 + set->variant = set->family == AF_INET 415 + ? &hash_ip4_variant : &hash_ip6_variant; 416 + } 417 + 418 + pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", 419 + set->name, jhash_size(h->table->htable_bits), 420 + h->table->htable_bits, h->maxelem, set->data, h->table); 421 + 422 + return 0; 423 + } 424 + 425 + static struct ip_set_type hash_ip_type __read_mostly = { 426 + .name = "hash:ip", 427 + .protocol = IPSET_PROTOCOL, 428 + .features = IPSET_TYPE_IP, 429 + .dimension = IPSET_DIM_ONE, 430 + .family = AF_UNSPEC, 431 + .revision = 0, 432 + .create = hash_ip_create, 433 + .create_policy = { 434 + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 435 + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 436 + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 437 + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 438 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 439 + [IPSET_ATTR_NETMASK] = { .type = NLA_U8 }, 440 + }, 441 + .adt_policy = { 442 + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 443 + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 444 + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 445 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 446 + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 447 + }, 448 + .me = THIS_MODULE, 449 + }; 450 + 451 + static int __init 452 + hash_ip_init(void) 453 + { 454 + return ip_set_type_register(&hash_ip_type); 455 + } 456 + 457 + static void __exit 458 + hash_ip_fini(void) 459 + { 460 + ip_set_type_unregister(&hash_ip_type); 461 + } 462 + 463 + module_init(hash_ip_init); 464 + module_exit(hash_ip_fini);
+544
net/netfilter/ipset/ip_set_hash_ipport.c
··· 1 + /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 2 + * 3 + * This program is free software; you can redistribute it and/or modify 4 + * it under the terms of the GNU General Public License version 2 as 5 + * published by the Free Software Foundation. 6 + */ 7 + 8 + /* Kernel module implementing an IP set type: the hash:ip,port type */ 9 + 10 + #include <linux/jhash.h> 11 + #include <linux/module.h> 12 + #include <linux/ip.h> 13 + #include <linux/skbuff.h> 14 + #include <linux/errno.h> 15 + #include <linux/random.h> 16 + #include <net/ip.h> 17 + #include <net/ipv6.h> 18 + #include <net/netlink.h> 19 + #include <net/tcp.h> 20 + 21 + #include <linux/netfilter.h> 22 + #include <linux/netfilter/ipset/pfxlen.h> 23 + #include <linux/netfilter/ipset/ip_set.h> 24 + #include <linux/netfilter/ipset/ip_set_timeout.h> 25 + #include <linux/netfilter/ipset/ip_set_getport.h> 26 + #include <linux/netfilter/ipset/ip_set_hash.h> 27 + 28 + MODULE_LICENSE("GPL"); 29 + MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 30 + MODULE_DESCRIPTION("hash:ip,port type of IP sets"); 31 + MODULE_ALIAS("ip_set_hash:ip,port"); 32 + 33 + /* Type specific function prefix */ 34 + #define TYPE hash_ipport 35 + 36 + static bool 37 + hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b); 38 + 39 + #define hash_ipport4_same_set hash_ipport_same_set 40 + #define hash_ipport6_same_set hash_ipport_same_set 41 + 42 + /* The type variant functions: IPv4 */ 43 + 44 + /* Member elements without timeout */ 45 + struct hash_ipport4_elem { 46 + __be32 ip; 47 + __be16 port; 48 + u8 proto; 49 + u8 padding; 50 + }; 51 + 52 + /* Member elements with timeout support */ 53 + struct hash_ipport4_telem { 54 + __be32 ip; 55 + __be16 port; 56 + u8 proto; 57 + u8 padding; 58 + unsigned long timeout; 59 + }; 60 + 61 + static inline bool 62 + hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1, 63 + const struct hash_ipport4_elem *ip2) 64 + { 65 + return ip1->ip == ip2->ip && 66 + ip1->port == ip2->port && 67 + ip1->proto == ip2->proto; 68 + } 69 + 70 + static inline bool 71 + hash_ipport4_data_isnull(const struct hash_ipport4_elem *elem) 72 + { 73 + return elem->proto == 0; 74 + } 75 + 76 + static inline void 77 + hash_ipport4_data_copy(struct hash_ipport4_elem *dst, 78 + const struct hash_ipport4_elem *src) 79 + { 80 + dst->ip = src->ip; 81 + dst->port = src->port; 82 + dst->proto = src->proto; 83 + } 84 + 85 + static inline void 86 + hash_ipport4_data_zero_out(struct hash_ipport4_elem *elem) 87 + { 88 + elem->proto = 0; 89 + } 90 + 91 + static bool 92 + hash_ipport4_data_list(struct sk_buff *skb, 93 + const struct hash_ipport4_elem *data) 94 + { 95 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); 96 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 97 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 98 + return 0; 99 + 100 + nla_put_failure: 101 + return 1; 102 + } 103 + 104 + static bool 105 + hash_ipport4_data_tlist(struct sk_buff *skb, 106 + const struct hash_ipport4_elem *data) 107 + { 108 + const struct hash_ipport4_telem *tdata = 109 + (const struct hash_ipport4_telem *)data; 110 + 111 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); 112 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port); 113 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 114 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 115 + htonl(ip_set_timeout_get(tdata->timeout))); 116 + 117 + return 0; 118 + 119 + nla_put_failure: 120 + return 1; 121 + } 122 + 123 + #define PF 4 124 + #define HOST_MASK 32 125 + #include <linux/netfilter/ipset/ip_set_ahash.h> 126 + 127 + static int 128 + hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb, 129 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 130 + { 131 + const struct ip_set_hash *h = set->data; 132 + ipset_adtfn adtfn = set->variant->adt[adt]; 133 + struct hash_ipport4_elem data = { }; 134 + 135 + if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC, 136 + &data.port, &data.proto)) 137 + return -EINVAL; 138 + 139 + ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); 140 + 141 + return adtfn(set, &data, h->timeout); 142 + } 143 + 144 + static int 145 + hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], 146 + enum ipset_adt adt, u32 *lineno, u32 flags) 147 + { 148 + const struct ip_set_hash *h = set->data; 149 + ipset_adtfn adtfn = set->variant->adt[adt]; 150 + struct hash_ipport4_elem data = { }; 151 + u32 ip, ip_to, p, port, port_to; 152 + u32 timeout = h->timeout; 153 + int ret; 154 + 155 + if (unlikely(!tb[IPSET_ATTR_IP] || 156 + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 157 + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 158 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 159 + return -IPSET_ERR_PROTOCOL; 160 + 161 + if (tb[IPSET_ATTR_LINENO]) 162 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 163 + 164 + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); 165 + if (ret) 166 + return ret; 167 + 168 + if (tb[IPSET_ATTR_PORT]) 169 + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 170 + else 171 + return -IPSET_ERR_PROTOCOL; 172 + 173 + if (tb[IPSET_ATTR_PROTO]) { 174 + data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 175 + 176 + if (data.proto == 0) 177 + return -IPSET_ERR_INVALID_PROTO; 178 + } else 179 + return -IPSET_ERR_MISSING_PROTO; 180 + 181 + switch (data.proto) { 182 + case IPPROTO_UDP: 183 + case IPPROTO_TCP: 184 + case IPPROTO_ICMP: 185 + break; 186 + default: 187 + data.port = 0; 188 + break; 189 + } 190 + 191 + if (tb[IPSET_ATTR_TIMEOUT]) { 192 + if (!with_timeout(h->timeout)) 193 + return -IPSET_ERR_TIMEOUT; 194 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 195 + } 196 + 197 + if (adt == IPSET_TEST || 198 + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 199 + !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || 200 + tb[IPSET_ATTR_PORT_TO])) { 201 + ret = adtfn(set, &data, timeout); 202 + return ip_set_eexist(ret, flags) ? 0 : ret; 203 + } 204 + 205 + ip = ntohl(data.ip); 206 + if (tb[IPSET_ATTR_IP_TO]) { 207 + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 208 + if (ret) 209 + return ret; 210 + if (ip > ip_to) 211 + swap(ip, ip_to); 212 + } else if (tb[IPSET_ATTR_CIDR]) { 213 + u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 214 + 215 + if (cidr > 32) 216 + return -IPSET_ERR_INVALID_CIDR; 217 + ip &= ip_set_hostmask(cidr); 218 + ip_to = ip | ~ip_set_hostmask(cidr); 219 + } else 220 + ip_to = ip; 221 + 222 + port = ntohs(data.port); 223 + if (tb[IPSET_ATTR_PORT_TO]) { 224 + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 225 + if (port > port_to) 226 + swap(port, port_to); 227 + } else 228 + port_to = port; 229 + 230 + for (; !before(ip_to, ip); ip++) 231 + for (p = port; p <= port_to; p++) { 232 + data.ip = htonl(ip); 233 + data.port = htons(p); 234 + ret = adtfn(set, &data, timeout); 235 + 236 + if (ret && !ip_set_eexist(ret, flags)) 237 + return ret; 238 + else 239 + ret = 0; 240 + } 241 + return ret; 242 + } 243 + 244 + static bool 245 + hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b) 246 + { 247 + const struct ip_set_hash *x = a->data; 248 + const struct ip_set_hash *y = b->data; 249 + 250 + /* Resizing changes htable_bits, so we ignore it */ 251 + return x->maxelem == y->maxelem && 252 + x->timeout == y->timeout; 253 + } 254 + 255 + /* The type variant functions: IPv6 */ 256 + 257 + struct hash_ipport6_elem { 258 + union nf_inet_addr ip; 259 + __be16 port; 260 + u8 proto; 261 + u8 padding; 262 + }; 263 + 264 + struct hash_ipport6_telem { 265 + union nf_inet_addr ip; 266 + __be16 port; 267 + u8 proto; 268 + u8 padding; 269 + unsigned long timeout; 270 + }; 271 + 272 + static inline bool 273 + hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1, 274 + const struct hash_ipport6_elem *ip2) 275 + { 276 + return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 277 + ip1->port == ip2->port && 278 + ip1->proto == ip2->proto; 279 + } 280 + 281 + static inline bool 282 + hash_ipport6_data_isnull(const struct hash_ipport6_elem *elem) 283 + { 284 + return elem->proto == 0; 285 + } 286 + 287 + static inline void 288 + hash_ipport6_data_copy(struct hash_ipport6_elem *dst, 289 + const struct hash_ipport6_elem *src) 290 + { 291 + memcpy(dst, src, sizeof(*dst)); 292 + } 293 + 294 + static inline void 295 + hash_ipport6_data_zero_out(struct hash_ipport6_elem *elem) 296 + { 297 + elem->proto = 0; 298 + } 299 + 300 + static bool 301 + hash_ipport6_data_list(struct sk_buff *skb, 302 + const struct hash_ipport6_elem *data) 303 + { 304 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); 305 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 306 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 307 + return 0; 308 + 309 + nla_put_failure: 310 + return 1; 311 + } 312 + 313 + static bool 314 + hash_ipport6_data_tlist(struct sk_buff *skb, 315 + const struct hash_ipport6_elem *data) 316 + { 317 + const struct hash_ipport6_telem *e = 318 + (const struct hash_ipport6_telem *)data; 319 + 320 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); 321 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 322 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 323 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 324 + htonl(ip_set_timeout_get(e->timeout))); 325 + return 0; 326 + 327 + nla_put_failure: 328 + return 1; 329 + } 330 + 331 + #undef PF 332 + #undef HOST_MASK 333 + 334 + #define PF 6 335 + #define HOST_MASK 128 336 + #include <linux/netfilter/ipset/ip_set_ahash.h> 337 + 338 + static int 339 + hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb, 340 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 341 + { 342 + const struct ip_set_hash *h = set->data; 343 + ipset_adtfn adtfn = set->variant->adt[adt]; 344 + struct hash_ipport6_elem data = { }; 345 + 346 + if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC, 347 + &data.port, &data.proto)) 348 + return -EINVAL; 349 + 350 + ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); 351 + 352 + return adtfn(set, &data, h->timeout); 353 + } 354 + 355 + static int 356 + hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], 357 + enum ipset_adt adt, u32 *lineno, u32 flags) 358 + { 359 + const struct ip_set_hash *h = set->data; 360 + ipset_adtfn adtfn = set->variant->adt[adt]; 361 + struct hash_ipport6_elem data = { }; 362 + u32 port, port_to; 363 + u32 timeout = h->timeout; 364 + int ret; 365 + 366 + if (unlikely(!tb[IPSET_ATTR_IP] || 367 + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 368 + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 369 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 370 + tb[IPSET_ATTR_IP_TO] || 371 + tb[IPSET_ATTR_CIDR])) 372 + return -IPSET_ERR_PROTOCOL; 373 + 374 + if (tb[IPSET_ATTR_LINENO]) 375 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 376 + 377 + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); 378 + if (ret) 379 + return ret; 380 + 381 + if (tb[IPSET_ATTR_PORT]) 382 + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 383 + else 384 + return -IPSET_ERR_PROTOCOL; 385 + 386 + if (tb[IPSET_ATTR_PROTO]) { 387 + data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 388 + 389 + if (data.proto == 0) 390 + return -IPSET_ERR_INVALID_PROTO; 391 + } else 392 + return -IPSET_ERR_MISSING_PROTO; 393 + 394 + switch (data.proto) { 395 + case IPPROTO_UDP: 396 + case IPPROTO_TCP: 397 + case IPPROTO_ICMPV6: 398 + break; 399 + default: 400 + data.port = 0; 401 + break; 402 + } 403 + 404 + if (tb[IPSET_ATTR_TIMEOUT]) { 405 + if (!with_timeout(h->timeout)) 406 + return -IPSET_ERR_TIMEOUT; 407 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 408 + } 409 + 410 + if (adt == IPSET_TEST || 411 + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 412 + !tb[IPSET_ATTR_PORT_TO]) { 413 + ret = adtfn(set, &data, timeout); 414 + return ip_set_eexist(ret, flags) ? 0 : ret; 415 + } 416 + 417 + port = ntohs(data.port); 418 + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 419 + if (port > port_to) 420 + swap(port, port_to); 421 + 422 + for (; port <= port_to; port++) { 423 + data.port = htons(port); 424 + ret = adtfn(set, &data, timeout); 425 + 426 + if (ret && !ip_set_eexist(ret, flags)) 427 + return ret; 428 + else 429 + ret = 0; 430 + } 431 + return ret; 432 + } 433 + 434 + /* Create hash:ip type of sets */ 435 + 436 + static int 437 + hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) 438 + { 439 + struct ip_set_hash *h; 440 + u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; 441 + u8 hbits; 442 + 443 + if (!(set->family == AF_INET || set->family == AF_INET6)) 444 + return -IPSET_ERR_INVALID_FAMILY; 445 + 446 + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || 447 + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || 448 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 449 + return -IPSET_ERR_PROTOCOL; 450 + 451 + if (tb[IPSET_ATTR_HASHSIZE]) { 452 + hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); 453 + if (hashsize < IPSET_MIMINAL_HASHSIZE) 454 + hashsize = IPSET_MIMINAL_HASHSIZE; 455 + } 456 + 457 + if (tb[IPSET_ATTR_MAXELEM]) 458 + maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]); 459 + 460 + h = kzalloc(sizeof(*h), GFP_KERNEL); 461 + if (!h) 462 + return -ENOMEM; 463 + 464 + h->maxelem = maxelem; 465 + get_random_bytes(&h->initval, sizeof(h->initval)); 466 + h->timeout = IPSET_NO_TIMEOUT; 467 + 468 + hbits = htable_bits(hashsize); 469 + h->table = ip_set_alloc( 470 + sizeof(struct htable) 471 + + jhash_size(hbits) * sizeof(struct hbucket)); 472 + if (!h->table) { 473 + kfree(h); 474 + return -ENOMEM; 475 + } 476 + h->table->htable_bits = hbits; 477 + 478 + set->data = h; 479 + 480 + if (tb[IPSET_ATTR_TIMEOUT]) { 481 + h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 482 + 483 + set->variant = set->family == AF_INET 484 + ? &hash_ipport4_tvariant : &hash_ipport6_tvariant; 485 + 486 + if (set->family == AF_INET) 487 + hash_ipport4_gc_init(set); 488 + else 489 + hash_ipport6_gc_init(set); 490 + } else { 491 + set->variant = set->family == AF_INET 492 + ? &hash_ipport4_variant : &hash_ipport6_variant; 493 + } 494 + 495 + pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", 496 + set->name, jhash_size(h->table->htable_bits), 497 + h->table->htable_bits, h->maxelem, set->data, h->table); 498 + 499 + return 0; 500 + } 501 + 502 + static struct ip_set_type hash_ipport_type __read_mostly = { 503 + .name = "hash:ip,port", 504 + .protocol = IPSET_PROTOCOL, 505 + .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, 506 + .dimension = IPSET_DIM_TWO, 507 + .family = AF_UNSPEC, 508 + .revision = 0, 509 + .create = hash_ipport_create, 510 + .create_policy = { 511 + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 512 + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 513 + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 514 + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 515 + [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 516 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 517 + }, 518 + .adt_policy = { 519 + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 520 + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 521 + [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 522 + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 523 + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 524 + [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 525 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 526 + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 527 + }, 528 + .me = THIS_MODULE, 529 + }; 530 + 531 + static int __init 532 + hash_ipport_init(void) 533 + { 534 + return ip_set_type_register(&hash_ipport_type); 535 + } 536 + 537 + static void __exit 538 + hash_ipport_fini(void) 539 + { 540 + ip_set_type_unregister(&hash_ipport_type); 541 + } 542 + 543 + module_init(hash_ipport_init); 544 + module_exit(hash_ipport_fini);
+562
net/netfilter/ipset/ip_set_hash_ipportip.c
··· 1 + /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 2 + * 3 + * This program is free software; you can redistribute it and/or modify 4 + * it under the terms of the GNU General Public License version 2 as 5 + * published by the Free Software Foundation. 6 + */ 7 + 8 + /* Kernel module implementing an IP set type: the hash:ip,port,ip type */ 9 + 10 + #include <linux/jhash.h> 11 + #include <linux/module.h> 12 + #include <linux/ip.h> 13 + #include <linux/skbuff.h> 14 + #include <linux/errno.h> 15 + #include <linux/random.h> 16 + #include <net/ip.h> 17 + #include <net/ipv6.h> 18 + #include <net/netlink.h> 19 + #include <net/tcp.h> 20 + 21 + #include <linux/netfilter.h> 22 + #include <linux/netfilter/ipset/pfxlen.h> 23 + #include <linux/netfilter/ipset/ip_set.h> 24 + #include <linux/netfilter/ipset/ip_set_timeout.h> 25 + #include <linux/netfilter/ipset/ip_set_getport.h> 26 + #include <linux/netfilter/ipset/ip_set_hash.h> 27 + 28 + MODULE_LICENSE("GPL"); 29 + MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 30 + MODULE_DESCRIPTION("hash:ip,port,ip type of IP sets"); 31 + MODULE_ALIAS("ip_set_hash:ip,port,ip"); 32 + 33 + /* Type specific function prefix */ 34 + #define TYPE hash_ipportip 35 + 36 + static bool 37 + hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b); 38 + 39 + #define hash_ipportip4_same_set hash_ipportip_same_set 40 + #define hash_ipportip6_same_set hash_ipportip_same_set 41 + 42 + /* The type variant functions: IPv4 */ 43 + 44 + /* Member elements without timeout */ 45 + struct hash_ipportip4_elem { 46 + __be32 ip; 47 + __be32 ip2; 48 + __be16 port; 49 + u8 proto; 50 + u8 padding; 51 + }; 52 + 53 + /* Member elements with timeout support */ 54 + struct hash_ipportip4_telem { 55 + __be32 ip; 56 + __be32 ip2; 57 + __be16 port; 58 + u8 proto; 59 + u8 padding; 60 + unsigned long timeout; 61 + }; 62 + 63 + static inline bool 64 + hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1, 65 + const struct hash_ipportip4_elem *ip2) 66 + { 67 + return ip1->ip == ip2->ip && 68 + ip1->ip2 == ip2->ip2 && 69 + ip1->port == ip2->port && 70 + ip1->proto == ip2->proto; 71 + } 72 + 73 + static inline bool 74 + hash_ipportip4_data_isnull(const struct hash_ipportip4_elem *elem) 75 + { 76 + return elem->proto == 0; 77 + } 78 + 79 + static inline void 80 + hash_ipportip4_data_copy(struct hash_ipportip4_elem *dst, 81 + const struct hash_ipportip4_elem *src) 82 + { 83 + memcpy(dst, src, sizeof(*dst)); 84 + } 85 + 86 + static inline void 87 + hash_ipportip4_data_zero_out(struct hash_ipportip4_elem *elem) 88 + { 89 + elem->proto = 0; 90 + } 91 + 92 + static bool 93 + hash_ipportip4_data_list(struct sk_buff *skb, 94 + const struct hash_ipportip4_elem *data) 95 + { 96 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); 97 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2); 98 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 99 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 100 + return 0; 101 + 102 + nla_put_failure: 103 + return 1; 104 + } 105 + 106 + static bool 107 + hash_ipportip4_data_tlist(struct sk_buff *skb, 108 + const struct hash_ipportip4_elem *data) 109 + { 110 + const struct hash_ipportip4_telem *tdata = 111 + (const struct hash_ipportip4_telem *)data; 112 + 113 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); 114 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2); 115 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port); 116 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 117 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 118 + htonl(ip_set_timeout_get(tdata->timeout))); 119 + 120 + return 0; 121 + 122 + nla_put_failure: 123 + return 1; 124 + } 125 + 126 + #define PF 4 127 + #define HOST_MASK 32 128 + #include <linux/netfilter/ipset/ip_set_ahash.h> 129 + 130 + static int 131 + hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb, 132 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 133 + { 134 + const struct ip_set_hash *h = set->data; 135 + ipset_adtfn adtfn = set->variant->adt[adt]; 136 + struct hash_ipportip4_elem data = { }; 137 + 138 + if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC, 139 + &data.port, &data.proto)) 140 + return -EINVAL; 141 + 142 + ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); 143 + ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2); 144 + 145 + return adtfn(set, &data, h->timeout); 146 + } 147 + 148 + static int 149 + hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], 150 + enum ipset_adt adt, u32 *lineno, u32 flags) 151 + { 152 + const struct ip_set_hash *h = set->data; 153 + ipset_adtfn adtfn = set->variant->adt[adt]; 154 + struct hash_ipportip4_elem data = { }; 155 + u32 ip, ip_to, p, port, port_to; 156 + u32 timeout = h->timeout; 157 + int ret; 158 + 159 + if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 160 + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 161 + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 162 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 163 + return -IPSET_ERR_PROTOCOL; 164 + 165 + if (tb[IPSET_ATTR_LINENO]) 166 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 167 + 168 + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); 169 + if (ret) 170 + return ret; 171 + 172 + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2); 173 + if (ret) 174 + return ret; 175 + 176 + if (tb[IPSET_ATTR_PORT]) 177 + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 178 + else 179 + return -IPSET_ERR_PROTOCOL; 180 + 181 + if (tb[IPSET_ATTR_PROTO]) { 182 + data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 183 + 184 + if (data.proto == 0) 185 + return -IPSET_ERR_INVALID_PROTO; 186 + } else 187 + return -IPSET_ERR_MISSING_PROTO; 188 + 189 + switch (data.proto) { 190 + case IPPROTO_UDP: 191 + case IPPROTO_TCP: 192 + case IPPROTO_ICMP: 193 + break; 194 + default: 195 + data.port = 0; 196 + break; 197 + } 198 + 199 + if (tb[IPSET_ATTR_TIMEOUT]) { 200 + if (!with_timeout(h->timeout)) 201 + return -IPSET_ERR_TIMEOUT; 202 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 203 + } 204 + 205 + if (adt == IPSET_TEST || 206 + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 207 + !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || 208 + tb[IPSET_ATTR_PORT_TO])) { 209 + ret = adtfn(set, &data, timeout); 210 + return ip_set_eexist(ret, flags) ? 0 : ret; 211 + } 212 + 213 + ip = ntohl(data.ip); 214 + if (tb[IPSET_ATTR_IP_TO]) { 215 + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 216 + if (ret) 217 + return ret; 218 + if (ip > ip_to) 219 + swap(ip, ip_to); 220 + } else if (tb[IPSET_ATTR_CIDR]) { 221 + u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 222 + 223 + if (cidr > 32) 224 + return -IPSET_ERR_INVALID_CIDR; 225 + ip &= ip_set_hostmask(cidr); 226 + ip_to = ip | ~ip_set_hostmask(cidr); 227 + } else 228 + ip_to = ip; 229 + 230 + port = ntohs(data.port); 231 + if (tb[IPSET_ATTR_PORT_TO]) { 232 + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 233 + if (port > port_to) 234 + swap(port, port_to); 235 + } else 236 + port_to = port; 237 + 238 + for (; !before(ip_to, ip); ip++) 239 + for (p = port; p <= port_to; p++) { 240 + data.ip = htonl(ip); 241 + data.port = htons(p); 242 + ret = adtfn(set, &data, timeout); 243 + 244 + if (ret && !ip_set_eexist(ret, flags)) 245 + return ret; 246 + else 247 + ret = 0; 248 + } 249 + return ret; 250 + } 251 + 252 + static bool 253 + hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b) 254 + { 255 + const struct ip_set_hash *x = a->data; 256 + const struct ip_set_hash *y = b->data; 257 + 258 + /* Resizing changes htable_bits, so we ignore it */ 259 + return x->maxelem == y->maxelem && 260 + x->timeout == y->timeout; 261 + } 262 + 263 + /* The type variant functions: IPv6 */ 264 + 265 + struct hash_ipportip6_elem { 266 + union nf_inet_addr ip; 267 + union nf_inet_addr ip2; 268 + __be16 port; 269 + u8 proto; 270 + u8 padding; 271 + }; 272 + 273 + struct hash_ipportip6_telem { 274 + union nf_inet_addr ip; 275 + union nf_inet_addr ip2; 276 + __be16 port; 277 + u8 proto; 278 + u8 padding; 279 + unsigned long timeout; 280 + }; 281 + 282 + static inline bool 283 + hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1, 284 + const struct hash_ipportip6_elem *ip2) 285 + { 286 + return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 287 + ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 && 288 + ip1->port == ip2->port && 289 + ip1->proto == ip2->proto; 290 + } 291 + 292 + static inline bool 293 + hash_ipportip6_data_isnull(const struct hash_ipportip6_elem *elem) 294 + { 295 + return elem->proto == 0; 296 + } 297 + 298 + static inline void 299 + hash_ipportip6_data_copy(struct hash_ipportip6_elem *dst, 300 + const struct hash_ipportip6_elem *src) 301 + { 302 + memcpy(dst, src, sizeof(*dst)); 303 + } 304 + 305 + static inline void 306 + hash_ipportip6_data_zero_out(struct hash_ipportip6_elem *elem) 307 + { 308 + elem->proto = 0; 309 + } 310 + 311 + static bool 312 + hash_ipportip6_data_list(struct sk_buff *skb, 313 + const struct hash_ipportip6_elem *data) 314 + { 315 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); 316 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2); 317 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 318 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 319 + return 0; 320 + 321 + nla_put_failure: 322 + return 1; 323 + } 324 + 325 + static bool 326 + hash_ipportip6_data_tlist(struct sk_buff *skb, 327 + const struct hash_ipportip6_elem *data) 328 + { 329 + const struct hash_ipportip6_telem *e = 330 + (const struct hash_ipportip6_telem *)data; 331 + 332 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); 333 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2); 334 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 335 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 336 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 337 + htonl(ip_set_timeout_get(e->timeout))); 338 + return 0; 339 + 340 + nla_put_failure: 341 + return 1; 342 + } 343 + 344 + #undef PF 345 + #undef HOST_MASK 346 + 347 + #define PF 6 348 + #define HOST_MASK 128 349 + #include <linux/netfilter/ipset/ip_set_ahash.h> 350 + 351 + static int 352 + hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb, 353 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 354 + { 355 + const struct ip_set_hash *h = set->data; 356 + ipset_adtfn adtfn = set->variant->adt[adt]; 357 + struct hash_ipportip6_elem data = { }; 358 + 359 + if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC, 360 + &data.port, &data.proto)) 361 + return -EINVAL; 362 + 363 + ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); 364 + ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6); 365 + 366 + return adtfn(set, &data, h->timeout); 367 + } 368 + 369 + static int 370 + hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], 371 + enum ipset_adt adt, u32 *lineno, u32 flags) 372 + { 373 + const struct ip_set_hash *h = set->data; 374 + ipset_adtfn adtfn = set->variant->adt[adt]; 375 + struct hash_ipportip6_elem data = { }; 376 + u32 port, port_to; 377 + u32 timeout = h->timeout; 378 + int ret; 379 + 380 + if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 381 + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 382 + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 383 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 384 + tb[IPSET_ATTR_IP_TO] || 385 + tb[IPSET_ATTR_CIDR])) 386 + return -IPSET_ERR_PROTOCOL; 387 + 388 + if (tb[IPSET_ATTR_LINENO]) 389 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 390 + 391 + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); 392 + if (ret) 393 + return ret; 394 + 395 + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2); 396 + if (ret) 397 + return ret; 398 + 399 + if (tb[IPSET_ATTR_PORT]) 400 + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 401 + else 402 + return -IPSET_ERR_PROTOCOL; 403 + 404 + if (tb[IPSET_ATTR_PROTO]) { 405 + data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 406 + 407 + if (data.proto == 0) 408 + return -IPSET_ERR_INVALID_PROTO; 409 + } else 410 + return -IPSET_ERR_MISSING_PROTO; 411 + 412 + switch (data.proto) { 413 + case IPPROTO_UDP: 414 + case IPPROTO_TCP: 415 + case IPPROTO_ICMPV6: 416 + break; 417 + default: 418 + data.port = 0; 419 + break; 420 + } 421 + 422 + if (tb[IPSET_ATTR_TIMEOUT]) { 423 + if (!with_timeout(h->timeout)) 424 + return -IPSET_ERR_TIMEOUT; 425 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 426 + } 427 + 428 + if (adt == IPSET_TEST || 429 + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 430 + !tb[IPSET_ATTR_PORT_TO]) { 431 + ret = adtfn(set, &data, timeout); 432 + return ip_set_eexist(ret, flags) ? 0 : ret; 433 + } 434 + 435 + port = ntohs(data.port); 436 + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 437 + if (port > port_to) 438 + swap(port, port_to); 439 + 440 + for (; port <= port_to; port++) { 441 + data.port = htons(port); 442 + ret = adtfn(set, &data, timeout); 443 + 444 + if (ret && !ip_set_eexist(ret, flags)) 445 + return ret; 446 + else 447 + ret = 0; 448 + } 449 + return ret; 450 + } 451 + 452 + /* Create hash:ip type of sets */ 453 + 454 + static int 455 + hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) 456 + { 457 + struct ip_set_hash *h; 458 + u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; 459 + u8 hbits; 460 + 461 + if (!(set->family == AF_INET || set->family == AF_INET6)) 462 + return -IPSET_ERR_INVALID_FAMILY; 463 + 464 + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || 465 + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || 466 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 467 + return -IPSET_ERR_PROTOCOL; 468 + 469 + if (tb[IPSET_ATTR_HASHSIZE]) { 470 + hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); 471 + if (hashsize < IPSET_MIMINAL_HASHSIZE) 472 + hashsize = IPSET_MIMINAL_HASHSIZE; 473 + } 474 + 475 + if (tb[IPSET_ATTR_MAXELEM]) 476 + maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]); 477 + 478 + h = kzalloc(sizeof(*h), GFP_KERNEL); 479 + if (!h) 480 + return -ENOMEM; 481 + 482 + h->maxelem = maxelem; 483 + get_random_bytes(&h->initval, sizeof(h->initval)); 484 + h->timeout = IPSET_NO_TIMEOUT; 485 + 486 + hbits = htable_bits(hashsize); 487 + h->table = ip_set_alloc( 488 + sizeof(struct htable) 489 + + jhash_size(hbits) * sizeof(struct hbucket)); 490 + if (!h->table) { 491 + kfree(h); 492 + return -ENOMEM; 493 + } 494 + h->table->htable_bits = hbits; 495 + 496 + set->data = h; 497 + 498 + if (tb[IPSET_ATTR_TIMEOUT]) { 499 + h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 500 + 501 + set->variant = set->family == AF_INET 502 + ? &hash_ipportip4_tvariant : &hash_ipportip6_tvariant; 503 + 504 + if (set->family == AF_INET) 505 + hash_ipportip4_gc_init(set); 506 + else 507 + hash_ipportip6_gc_init(set); 508 + } else { 509 + set->variant = set->family == AF_INET 510 + ? &hash_ipportip4_variant : &hash_ipportip6_variant; 511 + } 512 + 513 + pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", 514 + set->name, jhash_size(h->table->htable_bits), 515 + h->table->htable_bits, h->maxelem, set->data, h->table); 516 + 517 + return 0; 518 + } 519 + 520 + static struct ip_set_type hash_ipportip_type __read_mostly = { 521 + .name = "hash:ip,port,ip", 522 + .protocol = IPSET_PROTOCOL, 523 + .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, 524 + .dimension = IPSET_DIM_THREE, 525 + .family = AF_UNSPEC, 526 + .revision = 0, 527 + .create = hash_ipportip_create, 528 + .create_policy = { 529 + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 530 + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 531 + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 532 + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 533 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 534 + }, 535 + .adt_policy = { 536 + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 537 + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 538 + [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, 539 + [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 540 + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 541 + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 542 + [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 543 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 544 + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 545 + }, 546 + .me = THIS_MODULE, 547 + }; 548 + 549 + static int __init 550 + hash_ipportip_init(void) 551 + { 552 + return ip_set_type_register(&hash_ipportip_type); 553 + } 554 + 555 + static void __exit 556 + hash_ipportip_fini(void) 557 + { 558 + ip_set_type_unregister(&hash_ipportip_type); 559 + } 560 + 561 + module_init(hash_ipportip_init); 562 + module_exit(hash_ipportip_fini);
+628
net/netfilter/ipset/ip_set_hash_ipportnet.c
··· 1 + /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 2 + * 3 + * This program is free software; you can redistribute it and/or modify 4 + * it under the terms of the GNU General Public License version 2 as 5 + * published by the Free Software Foundation. 6 + */ 7 + 8 + /* Kernel module implementing an IP set type: the hash:ip,port,net type */ 9 + 10 + #include <linux/jhash.h> 11 + #include <linux/module.h> 12 + #include <linux/ip.h> 13 + #include <linux/skbuff.h> 14 + #include <linux/errno.h> 15 + #include <linux/random.h> 16 + #include <net/ip.h> 17 + #include <net/ipv6.h> 18 + #include <net/netlink.h> 19 + #include <net/tcp.h> 20 + 21 + #include <linux/netfilter.h> 22 + #include <linux/netfilter/ipset/pfxlen.h> 23 + #include <linux/netfilter/ipset/ip_set.h> 24 + #include <linux/netfilter/ipset/ip_set_timeout.h> 25 + #include <linux/netfilter/ipset/ip_set_getport.h> 26 + #include <linux/netfilter/ipset/ip_set_hash.h> 27 + 28 + MODULE_LICENSE("GPL"); 29 + MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 30 + MODULE_DESCRIPTION("hash:ip,port,net type of IP sets"); 31 + MODULE_ALIAS("ip_set_hash:ip,port,net"); 32 + 33 + /* Type specific function prefix */ 34 + #define TYPE hash_ipportnet 35 + 36 + static bool 37 + hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b); 38 + 39 + #define hash_ipportnet4_same_set hash_ipportnet_same_set 40 + #define hash_ipportnet6_same_set hash_ipportnet_same_set 41 + 42 + /* The type variant functions: IPv4 */ 43 + 44 + /* Member elements without timeout */ 45 + struct hash_ipportnet4_elem { 46 + __be32 ip; 47 + __be32 ip2; 48 + __be16 port; 49 + u8 cidr; 50 + u8 proto; 51 + }; 52 + 53 + /* Member elements with timeout support */ 54 + struct hash_ipportnet4_telem { 55 + __be32 ip; 56 + __be32 ip2; 57 + __be16 port; 58 + u8 cidr; 59 + u8 proto; 60 + unsigned long timeout; 61 + }; 62 + 63 + static inline bool 64 + hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1, 65 + const struct hash_ipportnet4_elem *ip2) 66 + { 67 + return ip1->ip == ip2->ip && 68 + ip1->ip2 == ip2->ip2 && 69 + ip1->cidr == ip2->cidr && 70 + ip1->port == ip2->port && 71 + ip1->proto == ip2->proto; 72 + } 73 + 74 + static inline bool 75 + hash_ipportnet4_data_isnull(const struct hash_ipportnet4_elem *elem) 76 + { 77 + return elem->proto == 0; 78 + } 79 + 80 + static inline void 81 + hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst, 82 + const struct hash_ipportnet4_elem *src) 83 + { 84 + memcpy(dst, src, sizeof(*dst)); 85 + } 86 + 87 + static inline void 88 + hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr) 89 + { 90 + elem->ip2 &= ip_set_netmask(cidr); 91 + elem->cidr = cidr; 92 + } 93 + 94 + static inline void 95 + hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem) 96 + { 97 + elem->proto = 0; 98 + } 99 + 100 + static bool 101 + hash_ipportnet4_data_list(struct sk_buff *skb, 102 + const struct hash_ipportnet4_elem *data) 103 + { 104 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); 105 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2); 106 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 107 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr); 108 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 109 + return 0; 110 + 111 + nla_put_failure: 112 + return 1; 113 + } 114 + 115 + static bool 116 + hash_ipportnet4_data_tlist(struct sk_buff *skb, 117 + const struct hash_ipportnet4_elem *data) 118 + { 119 + const struct hash_ipportnet4_telem *tdata = 120 + (const struct hash_ipportnet4_telem *)data; 121 + 122 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); 123 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2); 124 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port); 125 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr); 126 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 127 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 128 + htonl(ip_set_timeout_get(tdata->timeout))); 129 + 130 + return 0; 131 + 132 + nla_put_failure: 133 + return 1; 134 + } 135 + 136 + #define IP_SET_HASH_WITH_PROTO 137 + #define IP_SET_HASH_WITH_NETS 138 + 139 + #define PF 4 140 + #define HOST_MASK 32 141 + #include <linux/netfilter/ipset/ip_set_ahash.h> 142 + 143 + static int 144 + hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, 145 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 146 + { 147 + const struct ip_set_hash *h = set->data; 148 + ipset_adtfn adtfn = set->variant->adt[adt]; 149 + struct hash_ipportnet4_elem data = 150 + { .cidr = h->nets[0].cidr || HOST_MASK }; 151 + 152 + if (data.cidr == 0) 153 + return -EINVAL; 154 + if (adt == IPSET_TEST) 155 + data.cidr = HOST_MASK; 156 + 157 + if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC, 158 + &data.port, &data.proto)) 159 + return -EINVAL; 160 + 161 + ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); 162 + ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2); 163 + data.ip2 &= ip_set_netmask(data.cidr); 164 + 165 + return adtfn(set, &data, h->timeout); 166 + } 167 + 168 + static int 169 + hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], 170 + enum ipset_adt adt, u32 *lineno, u32 flags) 171 + { 172 + const struct ip_set_hash *h = set->data; 173 + ipset_adtfn adtfn = set->variant->adt[adt]; 174 + struct hash_ipportnet4_elem data = { .cidr = HOST_MASK }; 175 + u32 ip, ip_to, p, port, port_to; 176 + u32 timeout = h->timeout; 177 + int ret; 178 + 179 + if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 180 + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 181 + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 182 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 183 + return -IPSET_ERR_PROTOCOL; 184 + 185 + if (tb[IPSET_ATTR_LINENO]) 186 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 187 + 188 + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); 189 + if (ret) 190 + return ret; 191 + 192 + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2); 193 + if (ret) 194 + return ret; 195 + 196 + if (tb[IPSET_ATTR_CIDR2]) 197 + data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 198 + 199 + if (!data.cidr) 200 + return -IPSET_ERR_INVALID_CIDR; 201 + 202 + data.ip2 &= ip_set_netmask(data.cidr); 203 + 204 + if (tb[IPSET_ATTR_PORT]) 205 + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 206 + else 207 + return -IPSET_ERR_PROTOCOL; 208 + 209 + if (tb[IPSET_ATTR_PROTO]) { 210 + data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 211 + 212 + if (data.proto == 0) 213 + return -IPSET_ERR_INVALID_PROTO; 214 + } else 215 + return -IPSET_ERR_MISSING_PROTO; 216 + 217 + switch (data.proto) { 218 + case IPPROTO_UDP: 219 + case IPPROTO_TCP: 220 + case IPPROTO_ICMP: 221 + break; 222 + default: 223 + data.port = 0; 224 + break; 225 + } 226 + 227 + if (tb[IPSET_ATTR_TIMEOUT]) { 228 + if (!with_timeout(h->timeout)) 229 + return -IPSET_ERR_TIMEOUT; 230 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 231 + } 232 + 233 + if (adt == IPSET_TEST || 234 + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 235 + !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || 236 + tb[IPSET_ATTR_PORT_TO])) { 237 + ret = adtfn(set, &data, timeout); 238 + return ip_set_eexist(ret, flags) ? 0 : ret; 239 + } 240 + 241 + ip = ntohl(data.ip); 242 + if (tb[IPSET_ATTR_IP_TO]) { 243 + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 244 + if (ret) 245 + return ret; 246 + if (ip > ip_to) 247 + swap(ip, ip_to); 248 + } else if (tb[IPSET_ATTR_CIDR]) { 249 + u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 250 + 251 + if (cidr > 32) 252 + return -IPSET_ERR_INVALID_CIDR; 253 + ip &= ip_set_hostmask(cidr); 254 + ip_to = ip | ~ip_set_hostmask(cidr); 255 + } else 256 + ip_to = ip; 257 + 258 + port = ntohs(data.port); 259 + if (tb[IPSET_ATTR_PORT_TO]) { 260 + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 261 + if (port > port_to) 262 + swap(port, port_to); 263 + } else 264 + port_to = port; 265 + 266 + for (; !before(ip_to, ip); ip++) 267 + for (p = port; p <= port_to; p++) { 268 + data.ip = htonl(ip); 269 + data.port = htons(p); 270 + ret = adtfn(set, &data, timeout); 271 + 272 + if (ret && !ip_set_eexist(ret, flags)) 273 + return ret; 274 + else 275 + ret = 0; 276 + } 277 + return ret; 278 + } 279 + 280 + static bool 281 + hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b) 282 + { 283 + const struct ip_set_hash *x = a->data; 284 + const struct ip_set_hash *y = b->data; 285 + 286 + /* Resizing changes htable_bits, so we ignore it */ 287 + return x->maxelem == y->maxelem && 288 + x->timeout == y->timeout; 289 + } 290 + 291 + /* The type variant functions: IPv6 */ 292 + 293 + struct hash_ipportnet6_elem { 294 + union nf_inet_addr ip; 295 + union nf_inet_addr ip2; 296 + __be16 port; 297 + u8 cidr; 298 + u8 proto; 299 + }; 300 + 301 + struct hash_ipportnet6_telem { 302 + union nf_inet_addr ip; 303 + union nf_inet_addr ip2; 304 + __be16 port; 305 + u8 cidr; 306 + u8 proto; 307 + unsigned long timeout; 308 + }; 309 + 310 + static inline bool 311 + hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1, 312 + const struct hash_ipportnet6_elem *ip2) 313 + { 314 + return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 315 + ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 && 316 + ip1->cidr == ip2->cidr && 317 + ip1->port == ip2->port && 318 + ip1->proto == ip2->proto; 319 + } 320 + 321 + static inline bool 322 + hash_ipportnet6_data_isnull(const struct hash_ipportnet6_elem *elem) 323 + { 324 + return elem->proto == 0; 325 + } 326 + 327 + static inline void 328 + hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst, 329 + const struct hash_ipportnet6_elem *src) 330 + { 331 + memcpy(dst, src, sizeof(*dst)); 332 + } 333 + 334 + static inline void 335 + hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem) 336 + { 337 + elem->proto = 0; 338 + } 339 + 340 + static inline void 341 + ip6_netmask(union nf_inet_addr *ip, u8 prefix) 342 + { 343 + ip->ip6[0] &= ip_set_netmask6(prefix)[0]; 344 + ip->ip6[1] &= ip_set_netmask6(prefix)[1]; 345 + ip->ip6[2] &= ip_set_netmask6(prefix)[2]; 346 + ip->ip6[3] &= ip_set_netmask6(prefix)[3]; 347 + } 348 + 349 + static inline void 350 + hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr) 351 + { 352 + ip6_netmask(&elem->ip2, cidr); 353 + elem->cidr = cidr; 354 + } 355 + 356 + static bool 357 + hash_ipportnet6_data_list(struct sk_buff *skb, 358 + const struct hash_ipportnet6_elem *data) 359 + { 360 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); 361 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2); 362 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 363 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr); 364 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 365 + return 0; 366 + 367 + nla_put_failure: 368 + return 1; 369 + } 370 + 371 + static bool 372 + hash_ipportnet6_data_tlist(struct sk_buff *skb, 373 + const struct hash_ipportnet6_elem *data) 374 + { 375 + const struct hash_ipportnet6_telem *e = 376 + (const struct hash_ipportnet6_telem *)data; 377 + 378 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); 379 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2); 380 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 381 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr); 382 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 383 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 384 + htonl(ip_set_timeout_get(e->timeout))); 385 + return 0; 386 + 387 + nla_put_failure: 388 + return 1; 389 + } 390 + 391 + #undef PF 392 + #undef HOST_MASK 393 + 394 + #define PF 6 395 + #define HOST_MASK 128 396 + #include <linux/netfilter/ipset/ip_set_ahash.h> 397 + 398 + static int 399 + hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb, 400 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 401 + { 402 + const struct ip_set_hash *h = set->data; 403 + ipset_adtfn adtfn = set->variant->adt[adt]; 404 + struct hash_ipportnet6_elem data = 405 + { .cidr = h->nets[0].cidr || HOST_MASK }; 406 + 407 + if (data.cidr == 0) 408 + return -EINVAL; 409 + if (adt == IPSET_TEST) 410 + data.cidr = HOST_MASK; 411 + 412 + if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC, 413 + &data.port, &data.proto)) 414 + return -EINVAL; 415 + 416 + ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); 417 + ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6); 418 + ip6_netmask(&data.ip2, data.cidr); 419 + 420 + return adtfn(set, &data, h->timeout); 421 + } 422 + 423 + static int 424 + hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], 425 + enum ipset_adt adt, u32 *lineno, u32 flags) 426 + { 427 + const struct ip_set_hash *h = set->data; 428 + ipset_adtfn adtfn = set->variant->adt[adt]; 429 + struct hash_ipportnet6_elem data = { .cidr = HOST_MASK }; 430 + u32 port, port_to; 431 + u32 timeout = h->timeout; 432 + int ret; 433 + 434 + if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 435 + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 436 + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 437 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 438 + tb[IPSET_ATTR_IP_TO] || 439 + tb[IPSET_ATTR_CIDR])) 440 + return -IPSET_ERR_PROTOCOL; 441 + 442 + if (tb[IPSET_ATTR_LINENO]) 443 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 444 + 445 + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); 446 + if (ret) 447 + return ret; 448 + 449 + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2); 450 + if (ret) 451 + return ret; 452 + 453 + if (tb[IPSET_ATTR_CIDR2]) 454 + data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 455 + 456 + if (!data.cidr) 457 + return -IPSET_ERR_INVALID_CIDR; 458 + 459 + ip6_netmask(&data.ip2, data.cidr); 460 + 461 + if (tb[IPSET_ATTR_PORT]) 462 + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 463 + else 464 + return -IPSET_ERR_PROTOCOL; 465 + 466 + if (tb[IPSET_ATTR_PROTO]) { 467 + data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 468 + 469 + if (data.proto == 0) 470 + return -IPSET_ERR_INVALID_PROTO; 471 + } else 472 + return -IPSET_ERR_MISSING_PROTO; 473 + 474 + switch (data.proto) { 475 + case IPPROTO_UDP: 476 + case IPPROTO_TCP: 477 + case IPPROTO_ICMPV6: 478 + break; 479 + default: 480 + data.port = 0; 481 + break; 482 + } 483 + 484 + if (tb[IPSET_ATTR_TIMEOUT]) { 485 + if (!with_timeout(h->timeout)) 486 + return -IPSET_ERR_TIMEOUT; 487 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 488 + } 489 + 490 + if (adt == IPSET_TEST || 491 + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 492 + !tb[IPSET_ATTR_PORT_TO]) { 493 + ret = adtfn(set, &data, timeout); 494 + return ip_set_eexist(ret, flags) ? 0 : ret; 495 + } 496 + 497 + port = ntohs(data.port); 498 + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 499 + if (port > port_to) 500 + swap(port, port_to); 501 + 502 + for (; port <= port_to; port++) { 503 + data.port = htons(port); 504 + ret = adtfn(set, &data, timeout); 505 + 506 + if (ret && !ip_set_eexist(ret, flags)) 507 + return ret; 508 + else 509 + ret = 0; 510 + } 511 + return ret; 512 + } 513 + 514 + /* Create hash:ip type of sets */ 515 + 516 + static int 517 + hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags) 518 + { 519 + struct ip_set_hash *h; 520 + u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; 521 + u8 hbits; 522 + 523 + if (!(set->family == AF_INET || set->family == AF_INET6)) 524 + return -IPSET_ERR_INVALID_FAMILY; 525 + 526 + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || 527 + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || 528 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 529 + return -IPSET_ERR_PROTOCOL; 530 + 531 + if (tb[IPSET_ATTR_HASHSIZE]) { 532 + hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); 533 + if (hashsize < IPSET_MIMINAL_HASHSIZE) 534 + hashsize = IPSET_MIMINAL_HASHSIZE; 535 + } 536 + 537 + if (tb[IPSET_ATTR_MAXELEM]) 538 + maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]); 539 + 540 + h = kzalloc(sizeof(*h) 541 + + sizeof(struct ip_set_hash_nets) 542 + * (set->family == AF_INET ? 32 : 128), GFP_KERNEL); 543 + if (!h) 544 + return -ENOMEM; 545 + 546 + h->maxelem = maxelem; 547 + get_random_bytes(&h->initval, sizeof(h->initval)); 548 + h->timeout = IPSET_NO_TIMEOUT; 549 + 550 + hbits = htable_bits(hashsize); 551 + h->table = ip_set_alloc( 552 + sizeof(struct htable) 553 + + jhash_size(hbits) * sizeof(struct hbucket)); 554 + if (!h->table) { 555 + kfree(h); 556 + return -ENOMEM; 557 + } 558 + h->table->htable_bits = hbits; 559 + 560 + set->data = h; 561 + 562 + if (tb[IPSET_ATTR_TIMEOUT]) { 563 + h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 564 + 565 + set->variant = set->family == AF_INET 566 + ? &hash_ipportnet4_tvariant 567 + : &hash_ipportnet6_tvariant; 568 + 569 + if (set->family == AF_INET) 570 + hash_ipportnet4_gc_init(set); 571 + else 572 + hash_ipportnet6_gc_init(set); 573 + } else { 574 + set->variant = set->family == AF_INET 575 + ? &hash_ipportnet4_variant : &hash_ipportnet6_variant; 576 + } 577 + 578 + pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", 579 + set->name, jhash_size(h->table->htable_bits), 580 + h->table->htable_bits, h->maxelem, set->data, h->table); 581 + 582 + return 0; 583 + } 584 + 585 + static struct ip_set_type hash_ipportnet_type __read_mostly = { 586 + .name = "hash:ip,port,net", 587 + .protocol = IPSET_PROTOCOL, 588 + .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, 589 + .dimension = IPSET_DIM_THREE, 590 + .family = AF_UNSPEC, 591 + .revision = 0, 592 + .create = hash_ipportnet_create, 593 + .create_policy = { 594 + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 595 + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 596 + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 597 + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 598 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 599 + }, 600 + .adt_policy = { 601 + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 602 + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 603 + [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, 604 + [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 605 + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 606 + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 607 + [IPSET_ATTR_CIDR2] = { .type = NLA_U8 }, 608 + [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 609 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 610 + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 611 + }, 612 + .me = THIS_MODULE, 613 + }; 614 + 615 + static int __init 616 + hash_ipportnet_init(void) 617 + { 618 + return ip_set_type_register(&hash_ipportnet_type); 619 + } 620 + 621 + static void __exit 622 + hash_ipportnet_fini(void) 623 + { 624 + ip_set_type_unregister(&hash_ipportnet_type); 625 + } 626 + 627 + module_init(hash_ipportnet_init); 628 + module_exit(hash_ipportnet_fini);
+458
net/netfilter/ipset/ip_set_hash_net.c
··· 1 + /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 2 + * 3 + * This program is free software; you can redistribute it and/or modify 4 + * it under the terms of the GNU General Public License version 2 as 5 + * published by the Free Software Foundation. 6 + */ 7 + 8 + /* Kernel module implementing an IP set type: the hash:net type */ 9 + 10 + #include <linux/jhash.h> 11 + #include <linux/module.h> 12 + #include <linux/ip.h> 13 + #include <linux/skbuff.h> 14 + #include <linux/errno.h> 15 + #include <linux/random.h> 16 + #include <net/ip.h> 17 + #include <net/ipv6.h> 18 + #include <net/netlink.h> 19 + 20 + #include <linux/netfilter.h> 21 + #include <linux/netfilter/ipset/pfxlen.h> 22 + #include <linux/netfilter/ipset/ip_set.h> 23 + #include <linux/netfilter/ipset/ip_set_timeout.h> 24 + #include <linux/netfilter/ipset/ip_set_hash.h> 25 + 26 + MODULE_LICENSE("GPL"); 27 + MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 28 + MODULE_DESCRIPTION("hash:net type of IP sets"); 29 + MODULE_ALIAS("ip_set_hash:net"); 30 + 31 + /* Type specific function prefix */ 32 + #define TYPE hash_net 33 + 34 + static bool 35 + hash_net_same_set(const struct ip_set *a, const struct ip_set *b); 36 + 37 + #define hash_net4_same_set hash_net_same_set 38 + #define hash_net6_same_set hash_net_same_set 39 + 40 + /* The type variant functions: IPv4 */ 41 + 42 + /* Member elements without timeout */ 43 + struct hash_net4_elem { 44 + __be32 ip; 45 + u16 padding0; 46 + u8 padding1; 47 + u8 cidr; 48 + }; 49 + 50 + /* Member elements with timeout support */ 51 + struct hash_net4_telem { 52 + __be32 ip; 53 + u16 padding0; 54 + u8 padding1; 55 + u8 cidr; 56 + unsigned long timeout; 57 + }; 58 + 59 + static inline bool 60 + hash_net4_data_equal(const struct hash_net4_elem *ip1, 61 + const struct hash_net4_elem *ip2) 62 + { 63 + return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr; 64 + } 65 + 66 + static inline bool 67 + hash_net4_data_isnull(const struct hash_net4_elem *elem) 68 + { 69 + return elem->cidr == 0; 70 + } 71 + 72 + static inline void 73 + hash_net4_data_copy(struct hash_net4_elem *dst, 74 + const struct hash_net4_elem *src) 75 + { 76 + dst->ip = src->ip; 77 + dst->cidr = src->cidr; 78 + } 79 + 80 + static inline void 81 + hash_net4_data_netmask(struct hash_net4_elem *elem, u8 cidr) 82 + { 83 + elem->ip &= ip_set_netmask(cidr); 84 + elem->cidr = cidr; 85 + } 86 + 87 + /* Zero CIDR values cannot be stored */ 88 + static inline void 89 + hash_net4_data_zero_out(struct hash_net4_elem *elem) 90 + { 91 + elem->cidr = 0; 92 + } 93 + 94 + static bool 95 + hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data) 96 + { 97 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); 98 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 99 + return 0; 100 + 101 + nla_put_failure: 102 + return 1; 103 + } 104 + 105 + static bool 106 + hash_net4_data_tlist(struct sk_buff *skb, const struct hash_net4_elem *data) 107 + { 108 + const struct hash_net4_telem *tdata = 109 + (const struct hash_net4_telem *)data; 110 + 111 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); 112 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR, tdata->cidr); 113 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 114 + htonl(ip_set_timeout_get(tdata->timeout))); 115 + 116 + return 0; 117 + 118 + nla_put_failure: 119 + return 1; 120 + } 121 + 122 + #define IP_SET_HASH_WITH_NETS 123 + 124 + #define PF 4 125 + #define HOST_MASK 32 126 + #include <linux/netfilter/ipset/ip_set_ahash.h> 127 + 128 + static int 129 + hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb, 130 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 131 + { 132 + const struct ip_set_hash *h = set->data; 133 + ipset_adtfn adtfn = set->variant->adt[adt]; 134 + struct hash_net4_elem data = { .cidr = h->nets[0].cidr || HOST_MASK }; 135 + 136 + if (data.cidr == 0) 137 + return -EINVAL; 138 + if (adt == IPSET_TEST) 139 + data.cidr = HOST_MASK; 140 + 141 + ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); 142 + data.ip &= ip_set_netmask(data.cidr); 143 + 144 + return adtfn(set, &data, h->timeout); 145 + } 146 + 147 + static int 148 + hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], 149 + enum ipset_adt adt, u32 *lineno, u32 flags) 150 + { 151 + const struct ip_set_hash *h = set->data; 152 + ipset_adtfn adtfn = set->variant->adt[adt]; 153 + struct hash_net4_elem data = { .cidr = HOST_MASK }; 154 + u32 timeout = h->timeout; 155 + int ret; 156 + 157 + if (unlikely(!tb[IPSET_ATTR_IP] || 158 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 159 + return -IPSET_ERR_PROTOCOL; 160 + 161 + if (tb[IPSET_ATTR_LINENO]) 162 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 163 + 164 + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); 165 + if (ret) 166 + return ret; 167 + 168 + if (tb[IPSET_ATTR_CIDR]) 169 + data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 170 + 171 + if (!data.cidr) 172 + return -IPSET_ERR_INVALID_CIDR; 173 + 174 + data.ip &= ip_set_netmask(data.cidr); 175 + 176 + if (tb[IPSET_ATTR_TIMEOUT]) { 177 + if (!with_timeout(h->timeout)) 178 + return -IPSET_ERR_TIMEOUT; 179 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 180 + } 181 + 182 + ret = adtfn(set, &data, timeout); 183 + 184 + return ip_set_eexist(ret, flags) ? 0 : ret; 185 + } 186 + 187 + static bool 188 + hash_net_same_set(const struct ip_set *a, const struct ip_set *b) 189 + { 190 + const struct ip_set_hash *x = a->data; 191 + const struct ip_set_hash *y = b->data; 192 + 193 + /* Resizing changes htable_bits, so we ignore it */ 194 + return x->maxelem == y->maxelem && 195 + x->timeout == y->timeout; 196 + } 197 + 198 + /* The type variant functions: IPv6 */ 199 + 200 + struct hash_net6_elem { 201 + union nf_inet_addr ip; 202 + u16 padding0; 203 + u8 padding1; 204 + u8 cidr; 205 + }; 206 + 207 + struct hash_net6_telem { 208 + union nf_inet_addr ip; 209 + u16 padding0; 210 + u8 padding1; 211 + u8 cidr; 212 + unsigned long timeout; 213 + }; 214 + 215 + static inline bool 216 + hash_net6_data_equal(const struct hash_net6_elem *ip1, 217 + const struct hash_net6_elem *ip2) 218 + { 219 + return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 220 + ip1->cidr == ip2->cidr; 221 + } 222 + 223 + static inline bool 224 + hash_net6_data_isnull(const struct hash_net6_elem *elem) 225 + { 226 + return elem->cidr == 0; 227 + } 228 + 229 + static inline void 230 + hash_net6_data_copy(struct hash_net6_elem *dst, 231 + const struct hash_net6_elem *src) 232 + { 233 + ipv6_addr_copy(&dst->ip.in6, &src->ip.in6); 234 + dst->cidr = src->cidr; 235 + } 236 + 237 + static inline void 238 + hash_net6_data_zero_out(struct hash_net6_elem *elem) 239 + { 240 + elem->cidr = 0; 241 + } 242 + 243 + static inline void 244 + ip6_netmask(union nf_inet_addr *ip, u8 prefix) 245 + { 246 + ip->ip6[0] &= ip_set_netmask6(prefix)[0]; 247 + ip->ip6[1] &= ip_set_netmask6(prefix)[1]; 248 + ip->ip6[2] &= ip_set_netmask6(prefix)[2]; 249 + ip->ip6[3] &= ip_set_netmask6(prefix)[3]; 250 + } 251 + 252 + static inline void 253 + hash_net6_data_netmask(struct hash_net6_elem *elem, u8 cidr) 254 + { 255 + ip6_netmask(&elem->ip, cidr); 256 + elem->cidr = cidr; 257 + } 258 + 259 + static bool 260 + hash_net6_data_list(struct sk_buff *skb, const struct hash_net6_elem *data) 261 + { 262 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); 263 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 264 + return 0; 265 + 266 + nla_put_failure: 267 + return 1; 268 + } 269 + 270 + static bool 271 + hash_net6_data_tlist(struct sk_buff *skb, const struct hash_net6_elem *data) 272 + { 273 + const struct hash_net6_telem *e = 274 + (const struct hash_net6_telem *)data; 275 + 276 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); 277 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR, e->cidr); 278 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 279 + htonl(ip_set_timeout_get(e->timeout))); 280 + return 0; 281 + 282 + nla_put_failure: 283 + return 1; 284 + } 285 + 286 + #undef PF 287 + #undef HOST_MASK 288 + 289 + #define PF 6 290 + #define HOST_MASK 128 291 + #include <linux/netfilter/ipset/ip_set_ahash.h> 292 + 293 + static int 294 + hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb, 295 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 296 + { 297 + const struct ip_set_hash *h = set->data; 298 + ipset_adtfn adtfn = set->variant->adt[adt]; 299 + struct hash_net6_elem data = { .cidr = h->nets[0].cidr || HOST_MASK }; 300 + 301 + if (data.cidr == 0) 302 + return -EINVAL; 303 + if (adt == IPSET_TEST) 304 + data.cidr = HOST_MASK; 305 + 306 + ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); 307 + ip6_netmask(&data.ip, data.cidr); 308 + 309 + return adtfn(set, &data, h->timeout); 310 + } 311 + 312 + static int 313 + hash_net6_uadt(struct ip_set *set, struct nlattr *tb[], 314 + enum ipset_adt adt, u32 *lineno, u32 flags) 315 + { 316 + const struct ip_set_hash *h = set->data; 317 + ipset_adtfn adtfn = set->variant->adt[adt]; 318 + struct hash_net6_elem data = { .cidr = HOST_MASK }; 319 + u32 timeout = h->timeout; 320 + int ret; 321 + 322 + if (unlikely(!tb[IPSET_ATTR_IP] || 323 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 324 + return -IPSET_ERR_PROTOCOL; 325 + 326 + if (tb[IPSET_ATTR_LINENO]) 327 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 328 + 329 + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); 330 + if (ret) 331 + return ret; 332 + 333 + if (tb[IPSET_ATTR_CIDR]) 334 + data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 335 + 336 + if (!data.cidr) 337 + return -IPSET_ERR_INVALID_CIDR; 338 + 339 + ip6_netmask(&data.ip, data.cidr); 340 + 341 + if (tb[IPSET_ATTR_TIMEOUT]) { 342 + if (!with_timeout(h->timeout)) 343 + return -IPSET_ERR_TIMEOUT; 344 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 345 + } 346 + 347 + ret = adtfn(set, &data, timeout); 348 + 349 + return ip_set_eexist(ret, flags) ? 0 : ret; 350 + } 351 + 352 + /* Create hash:ip type of sets */ 353 + 354 + static int 355 + hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags) 356 + { 357 + u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; 358 + struct ip_set_hash *h; 359 + u8 hbits; 360 + 361 + if (!(set->family == AF_INET || set->family == AF_INET6)) 362 + return -IPSET_ERR_INVALID_FAMILY; 363 + 364 + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || 365 + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || 366 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 367 + return -IPSET_ERR_PROTOCOL; 368 + 369 + if (tb[IPSET_ATTR_HASHSIZE]) { 370 + hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); 371 + if (hashsize < IPSET_MIMINAL_HASHSIZE) 372 + hashsize = IPSET_MIMINAL_HASHSIZE; 373 + } 374 + 375 + if (tb[IPSET_ATTR_MAXELEM]) 376 + maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]); 377 + 378 + h = kzalloc(sizeof(*h) 379 + + sizeof(struct ip_set_hash_nets) 380 + * (set->family == AF_INET ? 32 : 128), GFP_KERNEL); 381 + if (!h) 382 + return -ENOMEM; 383 + 384 + h->maxelem = maxelem; 385 + get_random_bytes(&h->initval, sizeof(h->initval)); 386 + h->timeout = IPSET_NO_TIMEOUT; 387 + 388 + hbits = htable_bits(hashsize); 389 + h->table = ip_set_alloc( 390 + sizeof(struct htable) 391 + + jhash_size(hbits) * sizeof(struct hbucket)); 392 + if (!h->table) { 393 + kfree(h); 394 + return -ENOMEM; 395 + } 396 + h->table->htable_bits = hbits; 397 + 398 + set->data = h; 399 + 400 + if (tb[IPSET_ATTR_TIMEOUT]) { 401 + h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 402 + 403 + set->variant = set->family == AF_INET 404 + ? &hash_net4_tvariant : &hash_net6_tvariant; 405 + 406 + if (set->family == AF_INET) 407 + hash_net4_gc_init(set); 408 + else 409 + hash_net6_gc_init(set); 410 + } else { 411 + set->variant = set->family == AF_INET 412 + ? &hash_net4_variant : &hash_net6_variant; 413 + } 414 + 415 + pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", 416 + set->name, jhash_size(h->table->htable_bits), 417 + h->table->htable_bits, h->maxelem, set->data, h->table); 418 + 419 + return 0; 420 + } 421 + 422 + static struct ip_set_type hash_net_type __read_mostly = { 423 + .name = "hash:net", 424 + .protocol = IPSET_PROTOCOL, 425 + .features = IPSET_TYPE_IP, 426 + .dimension = IPSET_DIM_ONE, 427 + .family = AF_UNSPEC, 428 + .revision = 0, 429 + .create = hash_net_create, 430 + .create_policy = { 431 + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 432 + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 433 + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 434 + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 435 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 436 + }, 437 + .adt_policy = { 438 + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 439 + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 440 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 441 + }, 442 + .me = THIS_MODULE, 443 + }; 444 + 445 + static int __init 446 + hash_net_init(void) 447 + { 448 + return ip_set_type_register(&hash_net_type); 449 + } 450 + 451 + static void __exit 452 + hash_net_fini(void) 453 + { 454 + ip_set_type_unregister(&hash_net_type); 455 + } 456 + 457 + module_init(hash_net_init); 458 + module_exit(hash_net_fini);
+578
net/netfilter/ipset/ip_set_hash_netport.c
··· 1 + /* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 2 + * 3 + * This program is free software; you can redistribute it and/or modify 4 + * it under the terms of the GNU General Public License version 2 as 5 + * published by the Free Software Foundation. 6 + */ 7 + 8 + /* Kernel module implementing an IP set type: the hash:net,port type */ 9 + 10 + #include <linux/jhash.h> 11 + #include <linux/module.h> 12 + #include <linux/ip.h> 13 + #include <linux/skbuff.h> 14 + #include <linux/errno.h> 15 + #include <linux/random.h> 16 + #include <net/ip.h> 17 + #include <net/ipv6.h> 18 + #include <net/netlink.h> 19 + 20 + #include <linux/netfilter.h> 21 + #include <linux/netfilter/ipset/pfxlen.h> 22 + #include <linux/netfilter/ipset/ip_set.h> 23 + #include <linux/netfilter/ipset/ip_set_timeout.h> 24 + #include <linux/netfilter/ipset/ip_set_getport.h> 25 + #include <linux/netfilter/ipset/ip_set_hash.h> 26 + 27 + MODULE_LICENSE("GPL"); 28 + MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 29 + MODULE_DESCRIPTION("hash:net,port type of IP sets"); 30 + MODULE_ALIAS("ip_set_hash:net,port"); 31 + 32 + /* Type specific function prefix */ 33 + #define TYPE hash_netport 34 + 35 + static bool 36 + hash_netport_same_set(const struct ip_set *a, const struct ip_set *b); 37 + 38 + #define hash_netport4_same_set hash_netport_same_set 39 + #define hash_netport6_same_set hash_netport_same_set 40 + 41 + /* The type variant functions: IPv4 */ 42 + 43 + /* Member elements without timeout */ 44 + struct hash_netport4_elem { 45 + __be32 ip; 46 + __be16 port; 47 + u8 proto; 48 + u8 cidr; 49 + }; 50 + 51 + /* Member elements with timeout support */ 52 + struct hash_netport4_telem { 53 + __be32 ip; 54 + __be16 port; 55 + u8 proto; 56 + u8 cidr; 57 + unsigned long timeout; 58 + }; 59 + 60 + static inline bool 61 + hash_netport4_data_equal(const struct hash_netport4_elem *ip1, 62 + const struct hash_netport4_elem *ip2) 63 + { 64 + return ip1->ip == ip2->ip && 65 + ip1->port == ip2->port && 66 + ip1->proto == ip2->proto && 67 + ip1->cidr == ip2->cidr; 68 + } 69 + 70 + static inline bool 71 + hash_netport4_data_isnull(const struct hash_netport4_elem *elem) 72 + { 73 + return elem->proto == 0; 74 + } 75 + 76 + static inline void 77 + hash_netport4_data_copy(struct hash_netport4_elem *dst, 78 + const struct hash_netport4_elem *src) 79 + { 80 + dst->ip = src->ip; 81 + dst->port = src->port; 82 + dst->proto = src->proto; 83 + dst->cidr = src->cidr; 84 + } 85 + 86 + static inline void 87 + hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr) 88 + { 89 + elem->ip &= ip_set_netmask(cidr); 90 + elem->cidr = cidr; 91 + } 92 + 93 + static inline void 94 + hash_netport4_data_zero_out(struct hash_netport4_elem *elem) 95 + { 96 + elem->proto = 0; 97 + } 98 + 99 + static bool 100 + hash_netport4_data_list(struct sk_buff *skb, 101 + const struct hash_netport4_elem *data) 102 + { 103 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip); 104 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 105 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 106 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 107 + return 0; 108 + 109 + nla_put_failure: 110 + return 1; 111 + } 112 + 113 + static bool 114 + hash_netport4_data_tlist(struct sk_buff *skb, 115 + const struct hash_netport4_elem *data) 116 + { 117 + const struct hash_netport4_telem *tdata = 118 + (const struct hash_netport4_telem *)data; 119 + 120 + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip); 121 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port); 122 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 123 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 124 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 125 + htonl(ip_set_timeout_get(tdata->timeout))); 126 + 127 + return 0; 128 + 129 + nla_put_failure: 130 + return 1; 131 + } 132 + 133 + #define IP_SET_HASH_WITH_PROTO 134 + #define IP_SET_HASH_WITH_NETS 135 + 136 + #define PF 4 137 + #define HOST_MASK 32 138 + #include <linux/netfilter/ipset/ip_set_ahash.h> 139 + 140 + static int 141 + hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb, 142 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 143 + { 144 + const struct ip_set_hash *h = set->data; 145 + ipset_adtfn adtfn = set->variant->adt[adt]; 146 + struct hash_netport4_elem data = { 147 + .cidr = h->nets[0].cidr || HOST_MASK }; 148 + 149 + if (data.cidr == 0) 150 + return -EINVAL; 151 + if (adt == IPSET_TEST) 152 + data.cidr = HOST_MASK; 153 + 154 + if (!ip_set_get_ip4_port(skb, flags & IPSET_DIM_TWO_SRC, 155 + &data.port, &data.proto)) 156 + return -EINVAL; 157 + 158 + ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); 159 + data.ip &= ip_set_netmask(data.cidr); 160 + 161 + return adtfn(set, &data, h->timeout); 162 + } 163 + 164 + static int 165 + hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], 166 + enum ipset_adt adt, u32 *lineno, u32 flags) 167 + { 168 + const struct ip_set_hash *h = set->data; 169 + ipset_adtfn adtfn = set->variant->adt[adt]; 170 + struct hash_netport4_elem data = { .cidr = HOST_MASK }; 171 + u32 port, port_to; 172 + u32 timeout = h->timeout; 173 + int ret; 174 + 175 + if (unlikely(!tb[IPSET_ATTR_IP] || 176 + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 177 + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 178 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 179 + return -IPSET_ERR_PROTOCOL; 180 + 181 + if (tb[IPSET_ATTR_LINENO]) 182 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 183 + 184 + ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip); 185 + if (ret) 186 + return ret; 187 + 188 + if (tb[IPSET_ATTR_CIDR]) 189 + data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 190 + if (!data.cidr) 191 + return -IPSET_ERR_INVALID_CIDR; 192 + data.ip &= ip_set_netmask(data.cidr); 193 + 194 + if (tb[IPSET_ATTR_PORT]) 195 + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 196 + else 197 + return -IPSET_ERR_PROTOCOL; 198 + 199 + if (tb[IPSET_ATTR_PROTO]) { 200 + data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 201 + 202 + if (data.proto == 0) 203 + return -IPSET_ERR_INVALID_PROTO; 204 + } else 205 + return -IPSET_ERR_MISSING_PROTO; 206 + 207 + switch (data.proto) { 208 + case IPPROTO_UDP: 209 + case IPPROTO_TCP: 210 + case IPPROTO_ICMP: 211 + break; 212 + default: 213 + data.port = 0; 214 + break; 215 + } 216 + 217 + if (tb[IPSET_ATTR_TIMEOUT]) { 218 + if (!with_timeout(h->timeout)) 219 + return -IPSET_ERR_TIMEOUT; 220 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 221 + } 222 + 223 + if (adt == IPSET_TEST || 224 + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 225 + !tb[IPSET_ATTR_PORT_TO]) { 226 + ret = adtfn(set, &data, timeout); 227 + return ip_set_eexist(ret, flags) ? 0 : ret; 228 + } 229 + 230 + port = ntohs(data.port); 231 + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 232 + if (port > port_to) 233 + swap(port, port_to); 234 + 235 + for (; port <= port_to; port++) { 236 + data.port = htons(port); 237 + ret = adtfn(set, &data, timeout); 238 + 239 + if (ret && !ip_set_eexist(ret, flags)) 240 + return ret; 241 + else 242 + ret = 0; 243 + } 244 + return ret; 245 + } 246 + 247 + static bool 248 + hash_netport_same_set(const struct ip_set *a, const struct ip_set *b) 249 + { 250 + const struct ip_set_hash *x = a->data; 251 + const struct ip_set_hash *y = b->data; 252 + 253 + /* Resizing changes htable_bits, so we ignore it */ 254 + return x->maxelem == y->maxelem && 255 + x->timeout == y->timeout; 256 + } 257 + 258 + /* The type variant functions: IPv6 */ 259 + 260 + struct hash_netport6_elem { 261 + union nf_inet_addr ip; 262 + __be16 port; 263 + u8 proto; 264 + u8 cidr; 265 + }; 266 + 267 + struct hash_netport6_telem { 268 + union nf_inet_addr ip; 269 + __be16 port; 270 + u8 proto; 271 + u8 cidr; 272 + unsigned long timeout; 273 + }; 274 + 275 + static inline bool 276 + hash_netport6_data_equal(const struct hash_netport6_elem *ip1, 277 + const struct hash_netport6_elem *ip2) 278 + { 279 + return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 && 280 + ip1->port == ip2->port && 281 + ip1->proto == ip2->proto && 282 + ip1->cidr == ip2->cidr; 283 + } 284 + 285 + static inline bool 286 + hash_netport6_data_isnull(const struct hash_netport6_elem *elem) 287 + { 288 + return elem->proto == 0; 289 + } 290 + 291 + static inline void 292 + hash_netport6_data_copy(struct hash_netport6_elem *dst, 293 + const struct hash_netport6_elem *src) 294 + { 295 + memcpy(dst, src, sizeof(*dst)); 296 + } 297 + 298 + static inline void 299 + hash_netport6_data_zero_out(struct hash_netport6_elem *elem) 300 + { 301 + elem->proto = 0; 302 + } 303 + 304 + static inline void 305 + ip6_netmask(union nf_inet_addr *ip, u8 prefix) 306 + { 307 + ip->ip6[0] &= ip_set_netmask6(prefix)[0]; 308 + ip->ip6[1] &= ip_set_netmask6(prefix)[1]; 309 + ip->ip6[2] &= ip_set_netmask6(prefix)[2]; 310 + ip->ip6[3] &= ip_set_netmask6(prefix)[3]; 311 + } 312 + 313 + static inline void 314 + hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr) 315 + { 316 + ip6_netmask(&elem->ip, cidr); 317 + elem->cidr = cidr; 318 + } 319 + 320 + static bool 321 + hash_netport6_data_list(struct sk_buff *skb, 322 + const struct hash_netport6_elem *data) 323 + { 324 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip); 325 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 326 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 327 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 328 + return 0; 329 + 330 + nla_put_failure: 331 + return 1; 332 + } 333 + 334 + static bool 335 + hash_netport6_data_tlist(struct sk_buff *skb, 336 + const struct hash_netport6_elem *data) 337 + { 338 + const struct hash_netport6_telem *e = 339 + (const struct hash_netport6_telem *)data; 340 + 341 + NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip); 342 + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port); 343 + NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr); 344 + NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto); 345 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 346 + htonl(ip_set_timeout_get(e->timeout))); 347 + return 0; 348 + 349 + nla_put_failure: 350 + return 1; 351 + } 352 + 353 + #undef PF 354 + #undef HOST_MASK 355 + 356 + #define PF 6 357 + #define HOST_MASK 128 358 + #include <linux/netfilter/ipset/ip_set_ahash.h> 359 + 360 + static int 361 + hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb, 362 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 363 + { 364 + const struct ip_set_hash *h = set->data; 365 + ipset_adtfn adtfn = set->variant->adt[adt]; 366 + struct hash_netport6_elem data = { 367 + .cidr = h->nets[0].cidr || HOST_MASK }; 368 + 369 + if (data.cidr == 0) 370 + return -EINVAL; 371 + if (adt == IPSET_TEST) 372 + data.cidr = HOST_MASK; 373 + 374 + if (!ip_set_get_ip6_port(skb, flags & IPSET_DIM_TWO_SRC, 375 + &data.port, &data.proto)) 376 + return -EINVAL; 377 + 378 + ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); 379 + ip6_netmask(&data.ip, data.cidr); 380 + 381 + return adtfn(set, &data, h->timeout); 382 + } 383 + 384 + static int 385 + hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], 386 + enum ipset_adt adt, u32 *lineno, u32 flags) 387 + { 388 + const struct ip_set_hash *h = set->data; 389 + ipset_adtfn adtfn = set->variant->adt[adt]; 390 + struct hash_netport6_elem data = { .cidr = HOST_MASK }; 391 + u32 port, port_to; 392 + u32 timeout = h->timeout; 393 + int ret; 394 + 395 + if (unlikely(!tb[IPSET_ATTR_IP] || 396 + !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 397 + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 398 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 399 + return -IPSET_ERR_PROTOCOL; 400 + 401 + if (tb[IPSET_ATTR_LINENO]) 402 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 403 + 404 + ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip); 405 + if (ret) 406 + return ret; 407 + 408 + if (tb[IPSET_ATTR_CIDR]) 409 + data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 410 + if (!data.cidr) 411 + return -IPSET_ERR_INVALID_CIDR; 412 + ip6_netmask(&data.ip, data.cidr); 413 + 414 + if (tb[IPSET_ATTR_PORT]) 415 + data.port = nla_get_be16(tb[IPSET_ATTR_PORT]); 416 + else 417 + return -IPSET_ERR_PROTOCOL; 418 + 419 + if (tb[IPSET_ATTR_PROTO]) { 420 + data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); 421 + 422 + if (data.proto == 0) 423 + return -IPSET_ERR_INVALID_PROTO; 424 + } else 425 + return -IPSET_ERR_MISSING_PROTO; 426 + 427 + switch (data.proto) { 428 + case IPPROTO_UDP: 429 + case IPPROTO_TCP: 430 + case IPPROTO_ICMPV6: 431 + break; 432 + default: 433 + data.port = 0; 434 + break; 435 + } 436 + 437 + if (tb[IPSET_ATTR_TIMEOUT]) { 438 + if (!with_timeout(h->timeout)) 439 + return -IPSET_ERR_TIMEOUT; 440 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 441 + } 442 + 443 + if (adt == IPSET_TEST || 444 + !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || 445 + !tb[IPSET_ATTR_PORT_TO]) { 446 + ret = adtfn(set, &data, timeout); 447 + return ip_set_eexist(ret, flags) ? 0 : ret; 448 + } 449 + 450 + port = ntohs(data.port); 451 + port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); 452 + if (port > port_to) 453 + swap(port, port_to); 454 + 455 + for (; port <= port_to; port++) { 456 + data.port = htons(port); 457 + ret = adtfn(set, &data, timeout); 458 + 459 + if (ret && !ip_set_eexist(ret, flags)) 460 + return ret; 461 + else 462 + ret = 0; 463 + } 464 + return ret; 465 + } 466 + 467 + /* Create hash:ip type of sets */ 468 + 469 + static int 470 + hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) 471 + { 472 + struct ip_set_hash *h; 473 + u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; 474 + u8 hbits; 475 + 476 + if (!(set->family == AF_INET || set->family == AF_INET6)) 477 + return -IPSET_ERR_INVALID_FAMILY; 478 + 479 + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || 480 + !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || 481 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 482 + return -IPSET_ERR_PROTOCOL; 483 + 484 + if (tb[IPSET_ATTR_HASHSIZE]) { 485 + hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]); 486 + if (hashsize < IPSET_MIMINAL_HASHSIZE) 487 + hashsize = IPSET_MIMINAL_HASHSIZE; 488 + } 489 + 490 + if (tb[IPSET_ATTR_MAXELEM]) 491 + maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]); 492 + 493 + h = kzalloc(sizeof(*h) 494 + + sizeof(struct ip_set_hash_nets) 495 + * (set->family == AF_INET ? 32 : 128), GFP_KERNEL); 496 + if (!h) 497 + return -ENOMEM; 498 + 499 + h->maxelem = maxelem; 500 + get_random_bytes(&h->initval, sizeof(h->initval)); 501 + h->timeout = IPSET_NO_TIMEOUT; 502 + 503 + hbits = htable_bits(hashsize); 504 + h->table = ip_set_alloc( 505 + sizeof(struct htable) 506 + + jhash_size(hbits) * sizeof(struct hbucket)); 507 + if (!h->table) { 508 + kfree(h); 509 + return -ENOMEM; 510 + } 511 + h->table->htable_bits = hbits; 512 + 513 + set->data = h; 514 + 515 + if (tb[IPSET_ATTR_TIMEOUT]) { 516 + h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 517 + 518 + set->variant = set->family == AF_INET 519 + ? &hash_netport4_tvariant : &hash_netport6_tvariant; 520 + 521 + if (set->family == AF_INET) 522 + hash_netport4_gc_init(set); 523 + else 524 + hash_netport6_gc_init(set); 525 + } else { 526 + set->variant = set->family == AF_INET 527 + ? &hash_netport4_variant : &hash_netport6_variant; 528 + } 529 + 530 + pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", 531 + set->name, jhash_size(h->table->htable_bits), 532 + h->table->htable_bits, h->maxelem, set->data, h->table); 533 + 534 + return 0; 535 + } 536 + 537 + static struct ip_set_type hash_netport_type __read_mostly = { 538 + .name = "hash:net,port", 539 + .protocol = IPSET_PROTOCOL, 540 + .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, 541 + .dimension = IPSET_DIM_TWO, 542 + .family = AF_UNSPEC, 543 + .revision = 0, 544 + .create = hash_netport_create, 545 + .create_policy = { 546 + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 547 + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 548 + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 549 + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 550 + [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 551 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 552 + }, 553 + .adt_policy = { 554 + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 555 + [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 556 + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 557 + [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, 558 + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 559 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 560 + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 561 + }, 562 + .me = THIS_MODULE, 563 + }; 564 + 565 + static int __init 566 + hash_netport_init(void) 567 + { 568 + return ip_set_type_register(&hash_netport_type); 569 + } 570 + 571 + static void __exit 572 + hash_netport_fini(void) 573 + { 574 + ip_set_type_unregister(&hash_netport_type); 575 + } 576 + 577 + module_init(hash_netport_init); 578 + module_exit(hash_netport_fini);
+584
net/netfilter/ipset/ip_set_list_set.c
··· 1 + /* Copyright (C) 2008-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 2 + * 3 + * This program is free software; you can redistribute it and/or modify 4 + * it under the terms of the GNU General Public License version 2 as 5 + * published by the Free Software Foundation. 6 + */ 7 + 8 + /* Kernel module implementing an IP set type: the list:set type */ 9 + 10 + #include <linux/module.h> 11 + #include <linux/ip.h> 12 + #include <linux/skbuff.h> 13 + #include <linux/errno.h> 14 + 15 + #include <linux/netfilter/ipset/ip_set.h> 16 + #include <linux/netfilter/ipset/ip_set_timeout.h> 17 + #include <linux/netfilter/ipset/ip_set_list.h> 18 + 19 + MODULE_LICENSE("GPL"); 20 + MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 21 + MODULE_DESCRIPTION("list:set type of IP sets"); 22 + MODULE_ALIAS("ip_set_list:set"); 23 + 24 + /* Member elements without and with timeout */ 25 + struct set_elem { 26 + ip_set_id_t id; 27 + }; 28 + 29 + struct set_telem { 30 + ip_set_id_t id; 31 + unsigned long timeout; 32 + }; 33 + 34 + /* Type structure */ 35 + struct list_set { 36 + size_t dsize; /* element size */ 37 + u32 size; /* size of set list array */ 38 + u32 timeout; /* timeout value */ 39 + struct timer_list gc; /* garbage collection */ 40 + struct set_elem members[0]; /* the set members */ 41 + }; 42 + 43 + static inline struct set_elem * 44 + list_set_elem(const struct list_set *map, u32 id) 45 + { 46 + return (struct set_elem *)((char *)map->members + id * map->dsize); 47 + } 48 + 49 + static inline bool 50 + list_set_timeout(const struct list_set *map, u32 id) 51 + { 52 + const struct set_telem *elem = 53 + (const struct set_telem *) list_set_elem(map, id); 54 + 55 + return ip_set_timeout_test(elem->timeout); 56 + } 57 + 58 + static inline bool 59 + list_set_expired(const struct list_set *map, u32 id) 60 + { 61 + const struct set_telem *elem = 62 + (const struct set_telem *) list_set_elem(map, id); 63 + 64 + return ip_set_timeout_expired(elem->timeout); 65 + } 66 + 67 + static inline int 68 + list_set_exist(const struct set_telem *elem) 69 + { 70 + return elem->id != IPSET_INVALID_ID && 71 + !ip_set_timeout_expired(elem->timeout); 72 + } 73 + 74 + /* Set list without and with timeout */ 75 + 76 + static int 77 + list_set_kadt(struct ip_set *set, const struct sk_buff *skb, 78 + enum ipset_adt adt, u8 pf, u8 dim, u8 flags) 79 + { 80 + struct list_set *map = set->data; 81 + struct set_elem *elem; 82 + u32 i; 83 + int ret; 84 + 85 + for (i = 0; i < map->size; i++) { 86 + elem = list_set_elem(map, i); 87 + if (elem->id == IPSET_INVALID_ID) 88 + return 0; 89 + if (with_timeout(map->timeout) && list_set_expired(map, i)) 90 + continue; 91 + switch (adt) { 92 + case IPSET_TEST: 93 + ret = ip_set_test(elem->id, skb, pf, dim, flags); 94 + if (ret > 0) 95 + return ret; 96 + break; 97 + case IPSET_ADD: 98 + ret = ip_set_add(elem->id, skb, pf, dim, flags); 99 + if (ret == 0) 100 + return ret; 101 + break; 102 + case IPSET_DEL: 103 + ret = ip_set_del(elem->id, skb, pf, dim, flags); 104 + if (ret == 0) 105 + return ret; 106 + break; 107 + default: 108 + break; 109 + } 110 + } 111 + return -EINVAL; 112 + } 113 + 114 + static bool 115 + next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id) 116 + { 117 + const struct set_elem *elem; 118 + 119 + if (i + 1 < map->size) { 120 + elem = list_set_elem(map, i + 1); 121 + return !!(elem->id == id && 122 + !(with_timeout(map->timeout) && 123 + list_set_expired(map, i + 1))); 124 + } 125 + 126 + return 0; 127 + } 128 + 129 + static void 130 + list_elem_add(struct list_set *map, u32 i, ip_set_id_t id) 131 + { 132 + struct set_elem *e; 133 + 134 + for (; i < map->size; i++) { 135 + e = list_set_elem(map, i); 136 + swap(e->id, id); 137 + if (e->id == IPSET_INVALID_ID) 138 + break; 139 + } 140 + } 141 + 142 + static void 143 + list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id, 144 + unsigned long timeout) 145 + { 146 + struct set_telem *e; 147 + 148 + for (; i < map->size; i++) { 149 + e = (struct set_telem *)list_set_elem(map, i); 150 + swap(e->id, id); 151 + if (e->id == IPSET_INVALID_ID) 152 + break; 153 + swap(e->timeout, timeout); 154 + } 155 + } 156 + 157 + static int 158 + list_set_add(struct list_set *map, u32 i, ip_set_id_t id, 159 + unsigned long timeout) 160 + { 161 + const struct set_elem *e = list_set_elem(map, i); 162 + 163 + if (i == map->size - 1 && e->id != IPSET_INVALID_ID) 164 + /* Last element replaced: e.g. add new,before,last */ 165 + ip_set_put_byindex(e->id); 166 + if (with_timeout(map->timeout)) 167 + list_elem_tadd(map, i, id, timeout); 168 + else 169 + list_elem_add(map, i, id); 170 + 171 + return 0; 172 + } 173 + 174 + static int 175 + list_set_del(struct list_set *map, ip_set_id_t id, u32 i) 176 + { 177 + struct set_elem *a = list_set_elem(map, i), *b; 178 + 179 + ip_set_put_byindex(id); 180 + 181 + for (; i < map->size - 1; i++) { 182 + b = list_set_elem(map, i + 1); 183 + a->id = b->id; 184 + if (with_timeout(map->timeout)) 185 + ((struct set_telem *)a)->timeout = 186 + ((struct set_telem *)b)->timeout; 187 + a = b; 188 + if (a->id == IPSET_INVALID_ID) 189 + break; 190 + } 191 + /* Last element */ 192 + a->id = IPSET_INVALID_ID; 193 + return 0; 194 + } 195 + 196 + static int 197 + list_set_uadt(struct ip_set *set, struct nlattr *tb[], 198 + enum ipset_adt adt, u32 *lineno, u32 flags) 199 + { 200 + struct list_set *map = set->data; 201 + bool with_timeout = with_timeout(map->timeout); 202 + int before = 0; 203 + u32 timeout = map->timeout; 204 + ip_set_id_t id, refid = IPSET_INVALID_ID; 205 + const struct set_elem *elem; 206 + struct ip_set *s; 207 + u32 i; 208 + int ret = 0; 209 + 210 + if (unlikely(!tb[IPSET_ATTR_NAME] || 211 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 212 + !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 213 + return -IPSET_ERR_PROTOCOL; 214 + 215 + if (tb[IPSET_ATTR_LINENO]) 216 + *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 217 + 218 + id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s); 219 + if (id == IPSET_INVALID_ID) 220 + return -IPSET_ERR_NAME; 221 + /* "Loop detection" */ 222 + if (s->type->features & IPSET_TYPE_NAME) { 223 + ret = -IPSET_ERR_LOOP; 224 + goto finish; 225 + } 226 + 227 + if (tb[IPSET_ATTR_CADT_FLAGS]) { 228 + u32 f = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 229 + before = f & IPSET_FLAG_BEFORE; 230 + } 231 + 232 + if (before && !tb[IPSET_ATTR_NAMEREF]) { 233 + ret = -IPSET_ERR_BEFORE; 234 + goto finish; 235 + } 236 + 237 + if (tb[IPSET_ATTR_NAMEREF]) { 238 + refid = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAMEREF]), 239 + &s); 240 + if (refid == IPSET_INVALID_ID) { 241 + ret = -IPSET_ERR_NAMEREF; 242 + goto finish; 243 + } 244 + if (!before) 245 + before = -1; 246 + } 247 + if (tb[IPSET_ATTR_TIMEOUT]) { 248 + if (!with_timeout) { 249 + ret = -IPSET_ERR_TIMEOUT; 250 + goto finish; 251 + } 252 + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 253 + } 254 + 255 + switch (adt) { 256 + case IPSET_TEST: 257 + for (i = 0; i < map->size && !ret; i++) { 258 + elem = list_set_elem(map, i); 259 + if (elem->id == IPSET_INVALID_ID || 260 + (before != 0 && i + 1 >= map->size)) 261 + break; 262 + else if (with_timeout && list_set_expired(map, i)) 263 + continue; 264 + else if (before > 0 && elem->id == id) 265 + ret = next_id_eq(map, i, refid); 266 + else if (before < 0 && elem->id == refid) 267 + ret = next_id_eq(map, i, id); 268 + else if (before == 0 && elem->id == id) 269 + ret = 1; 270 + } 271 + break; 272 + case IPSET_ADD: 273 + for (i = 0; i < map->size && !ret; i++) { 274 + elem = list_set_elem(map, i); 275 + if (elem->id == id && 276 + !(with_timeout && list_set_expired(map, i))) 277 + ret = -IPSET_ERR_EXIST; 278 + } 279 + if (ret == -IPSET_ERR_EXIST) 280 + break; 281 + ret = -IPSET_ERR_LIST_FULL; 282 + for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) { 283 + elem = list_set_elem(map, i); 284 + if (elem->id == IPSET_INVALID_ID) 285 + ret = before != 0 ? -IPSET_ERR_REF_EXIST 286 + : list_set_add(map, i, id, timeout); 287 + else if (elem->id != refid) 288 + continue; 289 + else if (with_timeout && list_set_expired(map, i)) 290 + ret = -IPSET_ERR_REF_EXIST; 291 + else if (before) 292 + ret = list_set_add(map, i, id, timeout); 293 + else if (i + 1 < map->size) 294 + ret = list_set_add(map, i + 1, id, timeout); 295 + } 296 + break; 297 + case IPSET_DEL: 298 + ret = -IPSET_ERR_EXIST; 299 + for (i = 0; i < map->size && ret == -IPSET_ERR_EXIST; i++) { 300 + elem = list_set_elem(map, i); 301 + if (elem->id == IPSET_INVALID_ID) { 302 + ret = before != 0 ? -IPSET_ERR_REF_EXIST 303 + : -IPSET_ERR_EXIST; 304 + break; 305 + } else if (with_timeout && list_set_expired(map, i)) 306 + continue; 307 + else if (elem->id == id && 308 + (before == 0 || 309 + (before > 0 && 310 + next_id_eq(map, i, refid)))) 311 + ret = list_set_del(map, id, i); 312 + else if (before < 0 && 313 + elem->id == refid && 314 + next_id_eq(map, i, id)) 315 + ret = list_set_del(map, id, i + 1); 316 + } 317 + break; 318 + default: 319 + break; 320 + } 321 + 322 + finish: 323 + if (refid != IPSET_INVALID_ID) 324 + ip_set_put_byindex(refid); 325 + if (adt != IPSET_ADD || ret) 326 + ip_set_put_byindex(id); 327 + 328 + return ip_set_eexist(ret, flags) ? 0 : ret; 329 + } 330 + 331 + static void 332 + list_set_flush(struct ip_set *set) 333 + { 334 + struct list_set *map = set->data; 335 + struct set_elem *elem; 336 + u32 i; 337 + 338 + for (i = 0; i < map->size; i++) { 339 + elem = list_set_elem(map, i); 340 + if (elem->id != IPSET_INVALID_ID) { 341 + ip_set_put_byindex(elem->id); 342 + elem->id = IPSET_INVALID_ID; 343 + } 344 + } 345 + } 346 + 347 + static void 348 + list_set_destroy(struct ip_set *set) 349 + { 350 + struct list_set *map = set->data; 351 + 352 + if (with_timeout(map->timeout)) 353 + del_timer_sync(&map->gc); 354 + list_set_flush(set); 355 + kfree(map); 356 + 357 + set->data = NULL; 358 + } 359 + 360 + static int 361 + list_set_head(struct ip_set *set, struct sk_buff *skb) 362 + { 363 + const struct list_set *map = set->data; 364 + struct nlattr *nested; 365 + 366 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 367 + if (!nested) 368 + goto nla_put_failure; 369 + NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size)); 370 + if (with_timeout(map->timeout)) 371 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); 372 + NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, 373 + htonl(atomic_read(&set->ref) - 1)); 374 + NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, 375 + htonl(sizeof(*map) + map->size * map->dsize)); 376 + ipset_nest_end(skb, nested); 377 + 378 + return 0; 379 + nla_put_failure: 380 + return -EMSGSIZE; 381 + } 382 + 383 + static int 384 + list_set_list(const struct ip_set *set, 385 + struct sk_buff *skb, struct netlink_callback *cb) 386 + { 387 + const struct list_set *map = set->data; 388 + struct nlattr *atd, *nested; 389 + u32 i, first = cb->args[2]; 390 + const struct set_elem *e; 391 + 392 + atd = ipset_nest_start(skb, IPSET_ATTR_ADT); 393 + if (!atd) 394 + return -EMSGSIZE; 395 + for (; cb->args[2] < map->size; cb->args[2]++) { 396 + i = cb->args[2]; 397 + e = list_set_elem(map, i); 398 + if (e->id == IPSET_INVALID_ID) 399 + goto finish; 400 + if (with_timeout(map->timeout) && list_set_expired(map, i)) 401 + continue; 402 + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); 403 + if (!nested) { 404 + if (i == first) { 405 + nla_nest_cancel(skb, atd); 406 + return -EMSGSIZE; 407 + } else 408 + goto nla_put_failure; 409 + } 410 + NLA_PUT_STRING(skb, IPSET_ATTR_NAME, 411 + ip_set_name_byindex(e->id)); 412 + if (with_timeout(map->timeout)) { 413 + const struct set_telem *te = 414 + (const struct set_telem *) e; 415 + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, 416 + htonl(ip_set_timeout_get(te->timeout))); 417 + } 418 + ipset_nest_end(skb, nested); 419 + } 420 + finish: 421 + ipset_nest_end(skb, atd); 422 + /* Set listing finished */ 423 + cb->args[2] = 0; 424 + return 0; 425 + 426 + nla_put_failure: 427 + nla_nest_cancel(skb, nested); 428 + ipset_nest_end(skb, atd); 429 + if (unlikely(i == first)) { 430 + cb->args[2] = 0; 431 + return -EMSGSIZE; 432 + } 433 + return 0; 434 + } 435 + 436 + static bool 437 + list_set_same_set(const struct ip_set *a, const struct ip_set *b) 438 + { 439 + const struct list_set *x = a->data; 440 + const struct list_set *y = b->data; 441 + 442 + return x->size == y->size && 443 + x->timeout == y->timeout; 444 + } 445 + 446 + static const struct ip_set_type_variant list_set = { 447 + .kadt = list_set_kadt, 448 + .uadt = list_set_uadt, 449 + .destroy = list_set_destroy, 450 + .flush = list_set_flush, 451 + .head = list_set_head, 452 + .list = list_set_list, 453 + .same_set = list_set_same_set, 454 + }; 455 + 456 + static void 457 + list_set_gc(unsigned long ul_set) 458 + { 459 + struct ip_set *set = (struct ip_set *) ul_set; 460 + struct list_set *map = set->data; 461 + struct set_telem *e; 462 + u32 i; 463 + 464 + /* We run parallel with other readers (test element) 465 + * but adding/deleting new entries is locked out */ 466 + read_lock_bh(&set->lock); 467 + for (i = map->size - 1; i >= 0; i--) { 468 + e = (struct set_telem *) list_set_elem(map, i); 469 + if (e->id != IPSET_INVALID_ID && 470 + list_set_expired(map, i)) 471 + list_set_del(map, e->id, i); 472 + } 473 + read_unlock_bh(&set->lock); 474 + 475 + map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 476 + add_timer(&map->gc); 477 + } 478 + 479 + static void 480 + list_set_gc_init(struct ip_set *set) 481 + { 482 + struct list_set *map = set->data; 483 + 484 + init_timer(&map->gc); 485 + map->gc.data = (unsigned long) set; 486 + map->gc.function = list_set_gc; 487 + map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; 488 + add_timer(&map->gc); 489 + } 490 + 491 + /* Create list:set type of sets */ 492 + 493 + static bool 494 + init_list_set(struct ip_set *set, u32 size, size_t dsize, 495 + unsigned long timeout) 496 + { 497 + struct list_set *map; 498 + struct set_elem *e; 499 + u32 i; 500 + 501 + map = kzalloc(sizeof(*map) + size * dsize, GFP_KERNEL); 502 + if (!map) 503 + return false; 504 + 505 + map->size = size; 506 + map->dsize = dsize; 507 + map->timeout = timeout; 508 + set->data = map; 509 + 510 + for (i = 0; i < size; i++) { 511 + e = list_set_elem(map, i); 512 + e->id = IPSET_INVALID_ID; 513 + } 514 + 515 + return true; 516 + } 517 + 518 + static int 519 + list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags) 520 + { 521 + u32 size = IP_SET_LIST_DEFAULT_SIZE; 522 + 523 + if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) || 524 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 525 + return -IPSET_ERR_PROTOCOL; 526 + 527 + if (tb[IPSET_ATTR_SIZE]) 528 + size = ip_set_get_h32(tb[IPSET_ATTR_SIZE]); 529 + if (size < IP_SET_LIST_MIN_SIZE) 530 + size = IP_SET_LIST_MIN_SIZE; 531 + 532 + if (tb[IPSET_ATTR_TIMEOUT]) { 533 + if (!init_list_set(set, size, sizeof(struct set_telem), 534 + ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]))) 535 + return -ENOMEM; 536 + 537 + list_set_gc_init(set); 538 + } else { 539 + if (!init_list_set(set, size, sizeof(struct set_elem), 540 + IPSET_NO_TIMEOUT)) 541 + return -ENOMEM; 542 + } 543 + set->variant = &list_set; 544 + return 0; 545 + } 546 + 547 + static struct ip_set_type list_set_type __read_mostly = { 548 + .name = "list:set", 549 + .protocol = IPSET_PROTOCOL, 550 + .features = IPSET_TYPE_NAME | IPSET_DUMP_LAST, 551 + .dimension = IPSET_DIM_ONE, 552 + .family = AF_UNSPEC, 553 + .revision = 0, 554 + .create = list_set_create, 555 + .create_policy = { 556 + [IPSET_ATTR_SIZE] = { .type = NLA_U32 }, 557 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 558 + }, 559 + .adt_policy = { 560 + [IPSET_ATTR_NAME] = { .type = NLA_STRING, 561 + .len = IPSET_MAXNAMELEN }, 562 + [IPSET_ATTR_NAMEREF] = { .type = NLA_STRING, 563 + .len = IPSET_MAXNAMELEN }, 564 + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 565 + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 566 + [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 567 + }, 568 + .me = THIS_MODULE, 569 + }; 570 + 571 + static int __init 572 + list_set_init(void) 573 + { 574 + return ip_set_type_register(&list_set_type); 575 + } 576 + 577 + static void __exit 578 + list_set_fini(void) 579 + { 580 + ip_set_type_unregister(&list_set_type); 581 + } 582 + 583 + module_init(list_set_init); 584 + module_exit(list_set_fini);
+291
net/netfilter/ipset/pfxlen.c
··· 1 + #include <linux/netfilter/ipset/pfxlen.h> 2 + 3 + /* 4 + * Prefixlen maps for fast conversions, by Jan Engelhardt. 5 + */ 6 + 7 + #define E(a, b, c, d) \ 8 + {.ip6 = { \ 9 + __constant_htonl(a), __constant_htonl(b), \ 10 + __constant_htonl(c), __constant_htonl(d), \ 11 + } } 12 + 13 + /* 14 + * This table works for both IPv4 and IPv6; 15 + * just use prefixlen_netmask_map[prefixlength].ip. 16 + */ 17 + const union nf_inet_addr ip_set_netmask_map[] = { 18 + E(0x00000000, 0x00000000, 0x00000000, 0x00000000), 19 + E(0x80000000, 0x00000000, 0x00000000, 0x00000000), 20 + E(0xC0000000, 0x00000000, 0x00000000, 0x00000000), 21 + E(0xE0000000, 0x00000000, 0x00000000, 0x00000000), 22 + E(0xF0000000, 0x00000000, 0x00000000, 0x00000000), 23 + E(0xF8000000, 0x00000000, 0x00000000, 0x00000000), 24 + E(0xFC000000, 0x00000000, 0x00000000, 0x00000000), 25 + E(0xFE000000, 0x00000000, 0x00000000, 0x00000000), 26 + E(0xFF000000, 0x00000000, 0x00000000, 0x00000000), 27 + E(0xFF800000, 0x00000000, 0x00000000, 0x00000000), 28 + E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000), 29 + E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000), 30 + E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000), 31 + E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000), 32 + E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000), 33 + E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000), 34 + E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000), 35 + E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000), 36 + E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000), 37 + E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000), 38 + E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000), 39 + E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000), 40 + E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000), 41 + E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000), 42 + E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000), 43 + E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000), 44 + E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000), 45 + E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000), 46 + E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000), 47 + E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000), 48 + E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000), 49 + E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000), 50 + E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000), 51 + E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000), 52 + E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000), 53 + E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000), 54 + E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000), 55 + E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000), 56 + E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000), 57 + E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000), 58 + E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000), 59 + E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000), 60 + E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000), 61 + E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000), 62 + E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000), 63 + E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000), 64 + E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000), 65 + E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000), 66 + E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000), 67 + E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000), 68 + E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000), 69 + E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000), 70 + E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000), 71 + E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000), 72 + E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000), 73 + E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000), 74 + E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000), 75 + E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000), 76 + E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000), 77 + E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000), 78 + E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000), 79 + E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000), 80 + E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000), 81 + E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000), 82 + E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000), 83 + E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000), 84 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000), 85 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000), 86 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000), 87 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000), 88 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000), 89 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000), 90 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000), 91 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000), 92 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000), 93 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000), 94 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000), 95 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000), 96 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000), 97 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000), 98 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000), 99 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000), 100 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000), 101 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000), 102 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000), 103 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000), 104 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000), 105 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000), 106 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000), 107 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000), 108 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000), 109 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000), 110 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000), 111 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000), 112 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000), 113 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000), 114 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000), 115 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000), 116 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000), 117 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000), 118 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000), 119 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000), 120 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000), 121 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000), 122 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000), 123 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000), 124 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000), 125 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000), 126 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000), 127 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000), 128 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000), 129 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000), 130 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000), 131 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000), 132 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000), 133 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000), 134 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000), 135 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800), 136 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00), 137 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00), 138 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00), 139 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80), 140 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0), 141 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0), 142 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0), 143 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8), 144 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC), 145 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE), 146 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF), 147 + }; 148 + EXPORT_SYMBOL_GPL(ip_set_netmask_map); 149 + 150 + #undef E 151 + #define E(a, b, c, d) \ 152 + {.ip6 = { (__force __be32) a, (__force __be32) b, \ 153 + (__force __be32) c, (__force __be32) d, \ 154 + } } 155 + 156 + /* 157 + * This table works for both IPv4 and IPv6; 158 + * just use prefixlen_hostmask_map[prefixlength].ip. 159 + */ 160 + const union nf_inet_addr ip_set_hostmask_map[] = { 161 + E(0x00000000, 0x00000000, 0x00000000, 0x00000000), 162 + E(0x80000000, 0x00000000, 0x00000000, 0x00000000), 163 + E(0xC0000000, 0x00000000, 0x00000000, 0x00000000), 164 + E(0xE0000000, 0x00000000, 0x00000000, 0x00000000), 165 + E(0xF0000000, 0x00000000, 0x00000000, 0x00000000), 166 + E(0xF8000000, 0x00000000, 0x00000000, 0x00000000), 167 + E(0xFC000000, 0x00000000, 0x00000000, 0x00000000), 168 + E(0xFE000000, 0x00000000, 0x00000000, 0x00000000), 169 + E(0xFF000000, 0x00000000, 0x00000000, 0x00000000), 170 + E(0xFF800000, 0x00000000, 0x00000000, 0x00000000), 171 + E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000), 172 + E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000), 173 + E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000), 174 + E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000), 175 + E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000), 176 + E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000), 177 + E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000), 178 + E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000), 179 + E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000), 180 + E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000), 181 + E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000), 182 + E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000), 183 + E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000), 184 + E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000), 185 + E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000), 186 + E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000), 187 + E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000), 188 + E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000), 189 + E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000), 190 + E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000), 191 + E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000), 192 + E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000), 193 + E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000), 194 + E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000), 195 + E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000), 196 + E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000), 197 + E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000), 198 + E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000), 199 + E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000), 200 + E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000), 201 + E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000), 202 + E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000), 203 + E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000), 204 + E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000), 205 + E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000), 206 + E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000), 207 + E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000), 208 + E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000), 209 + E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000), 210 + E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000), 211 + E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000), 212 + E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000), 213 + E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000), 214 + E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000), 215 + E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000), 216 + E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000), 217 + E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000), 218 + E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000), 219 + E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000), 220 + E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000), 221 + E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000), 222 + E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000), 223 + E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000), 224 + E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000), 225 + E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000), 226 + E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000), 227 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000), 228 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000), 229 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000), 230 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000), 231 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000), 232 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000), 233 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000), 234 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000), 235 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000), 236 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000), 237 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000), 238 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000), 239 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000), 240 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000), 241 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000), 242 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000), 243 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000), 244 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000), 245 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000), 246 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000), 247 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000), 248 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000), 249 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000), 250 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000), 251 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000), 252 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000), 253 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000), 254 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000), 255 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000), 256 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000), 257 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000), 258 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000), 259 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000), 260 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000), 261 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000), 262 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000), 263 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000), 264 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000), 265 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000), 266 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000), 267 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000), 268 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000), 269 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000), 270 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000), 271 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000), 272 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000), 273 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000), 274 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000), 275 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000), 276 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000), 277 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000), 278 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800), 279 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00), 280 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00), 281 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00), 282 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80), 283 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0), 284 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0), 285 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0), 286 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8), 287 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC), 288 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE), 289 + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF), 290 + }; 291 + EXPORT_SYMBOL_GPL(ip_set_hostmask_map);
+1 -1
net/netfilter/ipvs/ip_vs_core.c
··· 1887 1887 ipvs->gen = atomic_read(&ipvs_netns_cnt); 1888 1888 atomic_inc(&ipvs_netns_cnt); 1889 1889 net->ipvs = ipvs; 1890 - printk(KERN_INFO "IPVS: Creating netns size=%lu id=%d\n", 1890 + printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n", 1891 1891 sizeof(struct netns_ipvs), ipvs->gen); 1892 1892 return 0; 1893 1893 }
+9 -8
net/netfilter/ipvs/ip_vs_ctl.c
··· 3515 3515 } 3516 3516 spin_lock_init(&ipvs->tot_stats->lock); 3517 3517 3518 - for (idx = 0; idx < IP_VS_RTAB_SIZE; idx++) 3519 - INIT_LIST_HEAD(&ipvs->rs_table[idx]); 3520 - 3521 3518 proc_net_fops_create(net, "ip_vs", 0, &ip_vs_info_fops); 3522 3519 proc_net_fops_create(net, "ip_vs_stats", 0, &ip_vs_stats_fops); 3523 3520 proc_net_fops_create(net, "ip_vs_stats_percpu", 0, ··· 3552 3555 tbl[idx++].data = &ipvs->sysctl_nat_icmp_send; 3553 3556 3554 3557 3558 + #ifdef CONFIG_SYSCTL 3555 3559 ipvs->sysctl_hdr = register_net_sysctl_table(net, net_vs_ctl_path, 3556 3560 tbl); 3557 - if (ipvs->sysctl_hdr == NULL) 3558 - goto err_reg; 3561 + if (ipvs->sysctl_hdr == NULL) { 3562 + if (!net_eq(net, &init_net)) 3563 + kfree(tbl); 3564 + goto err_dup; 3565 + } 3566 + #endif 3559 3567 ip_vs_new_estimator(net, ipvs->tot_stats); 3560 3568 ipvs->sysctl_tbl = tbl; 3561 3569 /* Schedule defense work */ ··· 3568 3566 schedule_delayed_work(&ipvs->defense_work, DEFENSE_TIMER_PERIOD); 3569 3567 return 0; 3570 3568 3571 - err_reg: 3572 - if (!net_eq(net, &init_net)) 3573 - kfree(tbl); 3574 3569 err_dup: 3575 3570 free_percpu(ipvs->cpustats); 3576 3571 err_alloc: ··· 3583 3584 ip_vs_kill_estimator(net, ipvs->tot_stats); 3584 3585 cancel_delayed_work_sync(&ipvs->defense_work); 3585 3586 cancel_work_sync(&ipvs->defense_work.work); 3587 + #ifdef CONFIG_SYSCTL 3586 3588 unregister_net_sysctl_table(ipvs->sysctl_hdr); 3589 + #endif 3587 3590 proc_net_remove(net, "ip_vs_stats_percpu"); 3588 3591 proc_net_remove(net, "ip_vs_stats"); 3589 3592 proc_net_remove(net, "ip_vs");
+10 -10
net/netfilter/ipvs/ip_vs_lblc.c
··· 554 554 sizeof(vs_vars_table), 555 555 GFP_KERNEL); 556 556 if (ipvs->lblc_ctl_table == NULL) 557 - goto err_dup; 557 + return -ENOMEM; 558 558 } else 559 559 ipvs->lblc_ctl_table = vs_vars_table; 560 560 ipvs->sysctl_lblc_expiration = 24*60*60*HZ; 561 561 ipvs->lblc_ctl_table[0].data = &ipvs->sysctl_lblc_expiration; 562 562 563 + #ifdef CONFIG_SYSCTL 563 564 ipvs->lblc_ctl_header = 564 565 register_net_sysctl_table(net, net_vs_ctl_path, 565 566 ipvs->lblc_ctl_table); 566 - if (!ipvs->lblc_ctl_header) 567 - goto err_reg; 567 + if (!ipvs->lblc_ctl_header) { 568 + if (!net_eq(net, &init_net)) 569 + kfree(ipvs->lblc_ctl_table); 570 + return -ENOMEM; 571 + } 572 + #endif 568 573 569 574 return 0; 570 - 571 - err_reg: 572 - if (!net_eq(net, &init_net)) 573 - kfree(ipvs->lblc_ctl_table); 574 - 575 - err_dup: 576 - return -ENOMEM; 577 575 } 578 576 579 577 static void __net_exit __ip_vs_lblc_exit(struct net *net) 580 578 { 581 579 struct netns_ipvs *ipvs = net_ipvs(net); 582 580 581 + #ifdef CONFIG_SYSCTL 583 582 unregister_net_sysctl_table(ipvs->lblc_ctl_header); 583 + #endif 584 584 585 585 if (!net_eq(net, &init_net)) 586 586 kfree(ipvs->lblc_ctl_table);
+10 -10
net/netfilter/ipvs/ip_vs_lblcr.c
··· 754 754 sizeof(vs_vars_table), 755 755 GFP_KERNEL); 756 756 if (ipvs->lblcr_ctl_table == NULL) 757 - goto err_dup; 757 + return -ENOMEM; 758 758 } else 759 759 ipvs->lblcr_ctl_table = vs_vars_table; 760 760 ipvs->sysctl_lblcr_expiration = 24*60*60*HZ; 761 761 ipvs->lblcr_ctl_table[0].data = &ipvs->sysctl_lblcr_expiration; 762 762 763 + #ifdef CONFIG_SYSCTL 763 764 ipvs->lblcr_ctl_header = 764 765 register_net_sysctl_table(net, net_vs_ctl_path, 765 766 ipvs->lblcr_ctl_table); 766 - if (!ipvs->lblcr_ctl_header) 767 - goto err_reg; 767 + if (!ipvs->lblcr_ctl_header) { 768 + if (!net_eq(net, &init_net)) 769 + kfree(ipvs->lblcr_ctl_table); 770 + return -ENOMEM; 771 + } 772 + #endif 768 773 769 774 return 0; 770 - 771 - err_reg: 772 - if (!net_eq(net, &init_net)) 773 - kfree(ipvs->lblcr_ctl_table); 774 - 775 - err_dup: 776 - return -ENOMEM; 777 775 } 778 776 779 777 static void __net_exit __ip_vs_lblcr_exit(struct net *net) 780 778 { 781 779 struct netns_ipvs *ipvs = net_ipvs(net); 782 780 781 + #ifdef CONFIG_SYSCTL 783 782 unregister_net_sysctl_table(ipvs->lblcr_ctl_header); 783 + #endif 784 784 785 785 if (!net_eq(net, &init_net)) 786 786 kfree(ipvs->lblcr_ctl_table);
+1 -1
net/netfilter/ipvs/ip_vs_sync.c
··· 1686 1686 return register_pernet_subsys(&ipvs_sync_ops); 1687 1687 } 1688 1688 1689 - void __exit ip_vs_sync_cleanup(void) 1689 + void ip_vs_sync_cleanup(void) 1690 1690 { 1691 1691 unregister_pernet_subsys(&ipvs_sync_ops); 1692 1692 }
+1 -1
net/netfilter/nf_conntrack_netlink.c
··· 803 803 static int 804 804 ctnetlink_parse_tuple(const struct nlattr * const cda[], 805 805 struct nf_conntrack_tuple *tuple, 806 - enum ctattr_tuple type, u_int8_t l3num) 806 + enum ctattr_type type, u_int8_t l3num) 807 807 { 808 808 struct nlattr *tb[CTA_TUPLE_MAX+1]; 809 809 int err;
+82
net/netfilter/xt_devgroup.c
··· 1 + /* 2 + * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + */ 8 + 9 + #include <linux/module.h> 10 + #include <linux/skbuff.h> 11 + #include <linux/netdevice.h> 12 + 13 + #include <linux/netfilter/xt_devgroup.h> 14 + #include <linux/netfilter/x_tables.h> 15 + 16 + MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); 17 + MODULE_LICENSE("GPL"); 18 + MODULE_DESCRIPTION("Xtables: Device group match"); 19 + MODULE_ALIAS("ipt_devgroup"); 20 + MODULE_ALIAS("ip6t_devgroup"); 21 + 22 + static bool devgroup_mt(const struct sk_buff *skb, struct xt_action_param *par) 23 + { 24 + const struct xt_devgroup_info *info = par->matchinfo; 25 + 26 + if (info->flags & XT_DEVGROUP_MATCH_SRC && 27 + (((info->src_group ^ par->in->group) & info->src_mask ? 1 : 0) ^ 28 + ((info->flags & XT_DEVGROUP_INVERT_SRC) ? 1 : 0))) 29 + return false; 30 + 31 + if (info->flags & XT_DEVGROUP_MATCH_DST && 32 + (((info->dst_group ^ par->out->group) & info->dst_mask ? 1 : 0) ^ 33 + ((info->flags & XT_DEVGROUP_INVERT_DST) ? 1 : 0))) 34 + return false; 35 + 36 + return true; 37 + } 38 + 39 + static int devgroup_mt_checkentry(const struct xt_mtchk_param *par) 40 + { 41 + const struct xt_devgroup_info *info = par->matchinfo; 42 + 43 + if (info->flags & ~(XT_DEVGROUP_MATCH_SRC | XT_DEVGROUP_INVERT_SRC | 44 + XT_DEVGROUP_MATCH_DST | XT_DEVGROUP_INVERT_DST)) 45 + return -EINVAL; 46 + 47 + if (info->flags & XT_DEVGROUP_MATCH_SRC && 48 + par->hook_mask & ~((1 << NF_INET_PRE_ROUTING) | 49 + (1 << NF_INET_LOCAL_IN) | 50 + (1 << NF_INET_FORWARD))) 51 + return -EINVAL; 52 + 53 + if (info->flags & XT_DEVGROUP_MATCH_DST && 54 + par->hook_mask & ~((1 << NF_INET_FORWARD) | 55 + (1 << NF_INET_LOCAL_OUT) | 56 + (1 << NF_INET_POST_ROUTING))) 57 + return -EINVAL; 58 + 59 + return 0; 60 + } 61 + 62 + static struct xt_match devgroup_mt_reg __read_mostly = { 63 + .name = "devgroup", 64 + .match = devgroup_mt, 65 + .checkentry = devgroup_mt_checkentry, 66 + .matchsize = sizeof(struct xt_devgroup_info), 67 + .family = NFPROTO_UNSPEC, 68 + .me = THIS_MODULE 69 + }; 70 + 71 + static int __init devgroup_mt_init(void) 72 + { 73 + return xt_register_match(&devgroup_mt_reg); 74 + } 75 + 76 + static void __exit devgroup_mt_exit(void) 77 + { 78 + xt_unregister_match(&devgroup_mt_reg); 79 + } 80 + 81 + module_init(devgroup_mt_init); 82 + module_exit(devgroup_mt_exit);
+359
net/netfilter/xt_set.c
··· 1 + /* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu> 2 + * Patrick Schaaf <bof@bof.de> 3 + * Martin Josefsson <gandalf@wlug.westbo.se> 4 + * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License version 2 as 8 + * published by the Free Software Foundation. 9 + */ 10 + 11 + /* Kernel module which implements the set match and SET target 12 + * for netfilter/iptables. */ 13 + 14 + #include <linux/module.h> 15 + #include <linux/skbuff.h> 16 + #include <linux/version.h> 17 + 18 + #include <linux/netfilter/x_tables.h> 19 + #include <linux/netfilter/xt_set.h> 20 + 21 + MODULE_LICENSE("GPL"); 22 + MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 23 + MODULE_DESCRIPTION("Xtables: IP set match and target module"); 24 + MODULE_ALIAS("xt_SET"); 25 + MODULE_ALIAS("ipt_set"); 26 + MODULE_ALIAS("ip6t_set"); 27 + MODULE_ALIAS("ipt_SET"); 28 + MODULE_ALIAS("ip6t_SET"); 29 + 30 + static inline int 31 + match_set(ip_set_id_t index, const struct sk_buff *skb, 32 + u8 pf, u8 dim, u8 flags, int inv) 33 + { 34 + if (ip_set_test(index, skb, pf, dim, flags)) 35 + inv = !inv; 36 + return inv; 37 + } 38 + 39 + /* Revision 0 interface: backward compatible with netfilter/iptables */ 40 + 41 + static bool 42 + set_match_v0(const struct sk_buff *skb, struct xt_action_param *par) 43 + { 44 + const struct xt_set_info_match_v0 *info = par->matchinfo; 45 + 46 + return match_set(info->match_set.index, skb, par->family, 47 + info->match_set.u.compat.dim, 48 + info->match_set.u.compat.flags, 49 + info->match_set.u.compat.flags & IPSET_INV_MATCH); 50 + } 51 + 52 + static void 53 + compat_flags(struct xt_set_info_v0 *info) 54 + { 55 + u_int8_t i; 56 + 57 + /* Fill out compatibility data according to enum ip_set_kopt */ 58 + info->u.compat.dim = IPSET_DIM_ZERO; 59 + if (info->u.flags[0] & IPSET_MATCH_INV) 60 + info->u.compat.flags |= IPSET_INV_MATCH; 61 + for (i = 0; i < IPSET_DIM_MAX-1 && info->u.flags[i]; i++) { 62 + info->u.compat.dim++; 63 + if (info->u.flags[i] & IPSET_SRC) 64 + info->u.compat.flags |= (1<<info->u.compat.dim); 65 + } 66 + } 67 + 68 + static int 69 + set_match_v0_checkentry(const struct xt_mtchk_param *par) 70 + { 71 + struct xt_set_info_match_v0 *info = par->matchinfo; 72 + ip_set_id_t index; 73 + 74 + index = ip_set_nfnl_get_byindex(info->match_set.index); 75 + 76 + if (index == IPSET_INVALID_ID) { 77 + pr_warning("Cannot find set indentified by id %u to match\n", 78 + info->match_set.index); 79 + return -ENOENT; 80 + } 81 + if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) { 82 + pr_warning("Protocol error: set match dimension " 83 + "is over the limit!\n"); 84 + return -ERANGE; 85 + } 86 + 87 + /* Fill out compatibility data */ 88 + compat_flags(&info->match_set); 89 + 90 + return 0; 91 + } 92 + 93 + static void 94 + set_match_v0_destroy(const struct xt_mtdtor_param *par) 95 + { 96 + struct xt_set_info_match_v0 *info = par->matchinfo; 97 + 98 + ip_set_nfnl_put(info->match_set.index); 99 + } 100 + 101 + static unsigned int 102 + set_target_v0(struct sk_buff *skb, const struct xt_action_param *par) 103 + { 104 + const struct xt_set_info_target_v0 *info = par->targinfo; 105 + 106 + if (info->add_set.index != IPSET_INVALID_ID) 107 + ip_set_add(info->add_set.index, skb, par->family, 108 + info->add_set.u.compat.dim, 109 + info->add_set.u.compat.flags); 110 + if (info->del_set.index != IPSET_INVALID_ID) 111 + ip_set_del(info->del_set.index, skb, par->family, 112 + info->del_set.u.compat.dim, 113 + info->del_set.u.compat.flags); 114 + 115 + return XT_CONTINUE; 116 + } 117 + 118 + static int 119 + set_target_v0_checkentry(const struct xt_tgchk_param *par) 120 + { 121 + struct xt_set_info_target_v0 *info = par->targinfo; 122 + ip_set_id_t index; 123 + 124 + if (info->add_set.index != IPSET_INVALID_ID) { 125 + index = ip_set_nfnl_get_byindex(info->add_set.index); 126 + if (index == IPSET_INVALID_ID) { 127 + pr_warning("Cannot find add_set index %u as target\n", 128 + info->add_set.index); 129 + return -ENOENT; 130 + } 131 + } 132 + 133 + if (info->del_set.index != IPSET_INVALID_ID) { 134 + index = ip_set_nfnl_get_byindex(info->del_set.index); 135 + if (index == IPSET_INVALID_ID) { 136 + pr_warning("Cannot find del_set index %u as target\n", 137 + info->del_set.index); 138 + return -ENOENT; 139 + } 140 + } 141 + if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0 || 142 + info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) { 143 + pr_warning("Protocol error: SET target dimension " 144 + "is over the limit!\n"); 145 + return -ERANGE; 146 + } 147 + 148 + /* Fill out compatibility data */ 149 + compat_flags(&info->add_set); 150 + compat_flags(&info->del_set); 151 + 152 + return 0; 153 + } 154 + 155 + static void 156 + set_target_v0_destroy(const struct xt_tgdtor_param *par) 157 + { 158 + const struct xt_set_info_target_v0 *info = par->targinfo; 159 + 160 + if (info->add_set.index != IPSET_INVALID_ID) 161 + ip_set_nfnl_put(info->add_set.index); 162 + if (info->del_set.index != IPSET_INVALID_ID) 163 + ip_set_nfnl_put(info->del_set.index); 164 + } 165 + 166 + /* Revision 1: current interface to netfilter/iptables */ 167 + 168 + static bool 169 + set_match(const struct sk_buff *skb, struct xt_action_param *par) 170 + { 171 + const struct xt_set_info_match *info = par->matchinfo; 172 + 173 + return match_set(info->match_set.index, skb, par->family, 174 + info->match_set.dim, 175 + info->match_set.flags, 176 + info->match_set.flags & IPSET_INV_MATCH); 177 + } 178 + 179 + static int 180 + set_match_checkentry(const struct xt_mtchk_param *par) 181 + { 182 + struct xt_set_info_match *info = par->matchinfo; 183 + ip_set_id_t index; 184 + 185 + index = ip_set_nfnl_get_byindex(info->match_set.index); 186 + 187 + if (index == IPSET_INVALID_ID) { 188 + pr_warning("Cannot find set indentified by id %u to match\n", 189 + info->match_set.index); 190 + return -ENOENT; 191 + } 192 + if (info->match_set.dim > IPSET_DIM_MAX) { 193 + pr_warning("Protocol error: set match dimension " 194 + "is over the limit!\n"); 195 + return -ERANGE; 196 + } 197 + 198 + return 0; 199 + } 200 + 201 + static void 202 + set_match_destroy(const struct xt_mtdtor_param *par) 203 + { 204 + struct xt_set_info_match *info = par->matchinfo; 205 + 206 + ip_set_nfnl_put(info->match_set.index); 207 + } 208 + 209 + static unsigned int 210 + set_target(struct sk_buff *skb, const struct xt_action_param *par) 211 + { 212 + const struct xt_set_info_target *info = par->targinfo; 213 + 214 + if (info->add_set.index != IPSET_INVALID_ID) 215 + ip_set_add(info->add_set.index, 216 + skb, par->family, 217 + info->add_set.dim, 218 + info->add_set.flags); 219 + if (info->del_set.index != IPSET_INVALID_ID) 220 + ip_set_del(info->del_set.index, 221 + skb, par->family, 222 + info->add_set.dim, 223 + info->del_set.flags); 224 + 225 + return XT_CONTINUE; 226 + } 227 + 228 + static int 229 + set_target_checkentry(const struct xt_tgchk_param *par) 230 + { 231 + const struct xt_set_info_target *info = par->targinfo; 232 + ip_set_id_t index; 233 + 234 + if (info->add_set.index != IPSET_INVALID_ID) { 235 + index = ip_set_nfnl_get_byindex(info->add_set.index); 236 + if (index == IPSET_INVALID_ID) { 237 + pr_warning("Cannot find add_set index %u as target\n", 238 + info->add_set.index); 239 + return -ENOENT; 240 + } 241 + } 242 + 243 + if (info->del_set.index != IPSET_INVALID_ID) { 244 + index = ip_set_nfnl_get_byindex(info->del_set.index); 245 + if (index == IPSET_INVALID_ID) { 246 + pr_warning("Cannot find del_set index %u as target\n", 247 + info->del_set.index); 248 + return -ENOENT; 249 + } 250 + } 251 + if (info->add_set.dim > IPSET_DIM_MAX || 252 + info->del_set.flags > IPSET_DIM_MAX) { 253 + pr_warning("Protocol error: SET target dimension " 254 + "is over the limit!\n"); 255 + return -ERANGE; 256 + } 257 + 258 + return 0; 259 + } 260 + 261 + static void 262 + set_target_destroy(const struct xt_tgdtor_param *par) 263 + { 264 + const struct xt_set_info_target *info = par->targinfo; 265 + 266 + if (info->add_set.index != IPSET_INVALID_ID) 267 + ip_set_nfnl_put(info->add_set.index); 268 + if (info->del_set.index != IPSET_INVALID_ID) 269 + ip_set_nfnl_put(info->del_set.index); 270 + } 271 + 272 + static struct xt_match set_matches[] __read_mostly = { 273 + { 274 + .name = "set", 275 + .family = NFPROTO_IPV4, 276 + .revision = 0, 277 + .match = set_match_v0, 278 + .matchsize = sizeof(struct xt_set_info_match_v0), 279 + .checkentry = set_match_v0_checkentry, 280 + .destroy = set_match_v0_destroy, 281 + .me = THIS_MODULE 282 + }, 283 + { 284 + .name = "set", 285 + .family = NFPROTO_IPV4, 286 + .revision = 1, 287 + .match = set_match, 288 + .matchsize = sizeof(struct xt_set_info_match), 289 + .checkentry = set_match_checkentry, 290 + .destroy = set_match_destroy, 291 + .me = THIS_MODULE 292 + }, 293 + { 294 + .name = "set", 295 + .family = NFPROTO_IPV6, 296 + .revision = 1, 297 + .match = set_match, 298 + .matchsize = sizeof(struct xt_set_info_match), 299 + .checkentry = set_match_checkentry, 300 + .destroy = set_match_destroy, 301 + .me = THIS_MODULE 302 + }, 303 + }; 304 + 305 + static struct xt_target set_targets[] __read_mostly = { 306 + { 307 + .name = "SET", 308 + .revision = 0, 309 + .family = NFPROTO_IPV4, 310 + .target = set_target_v0, 311 + .targetsize = sizeof(struct xt_set_info_target_v0), 312 + .checkentry = set_target_v0_checkentry, 313 + .destroy = set_target_v0_destroy, 314 + .me = THIS_MODULE 315 + }, 316 + { 317 + .name = "SET", 318 + .revision = 1, 319 + .family = NFPROTO_IPV4, 320 + .target = set_target, 321 + .targetsize = sizeof(struct xt_set_info_target), 322 + .checkentry = set_target_checkentry, 323 + .destroy = set_target_destroy, 324 + .me = THIS_MODULE 325 + }, 326 + { 327 + .name = "SET", 328 + .revision = 1, 329 + .family = NFPROTO_IPV6, 330 + .target = set_target, 331 + .targetsize = sizeof(struct xt_set_info_target), 332 + .checkentry = set_target_checkentry, 333 + .destroy = set_target_destroy, 334 + .me = THIS_MODULE 335 + }, 336 + }; 337 + 338 + static int __init xt_set_init(void) 339 + { 340 + int ret = xt_register_matches(set_matches, ARRAY_SIZE(set_matches)); 341 + 342 + if (!ret) { 343 + ret = xt_register_targets(set_targets, 344 + ARRAY_SIZE(set_targets)); 345 + if (ret) 346 + xt_unregister_matches(set_matches, 347 + ARRAY_SIZE(set_matches)); 348 + } 349 + return ret; 350 + } 351 + 352 + static void __exit xt_set_fini(void) 353 + { 354 + xt_unregister_matches(set_matches, ARRAY_SIZE(set_matches)); 355 + xt_unregister_targets(set_targets, ARRAY_SIZE(set_targets)); 356 + } 357 + 358 + module_init(xt_set_init); 359 + module_exit(xt_set_fini);