1/* Copyright (C) 2003-2013 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_hash.h> 25 26#define REVISION_MIN 0 27#define REVISION_MAX 1 /* Counters support */ 28 29MODULE_LICENSE("GPL"); 30MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 31IP_SET_MODULE_DESC("hash:ip", REVISION_MIN, REVISION_MAX); 32MODULE_ALIAS("ip_set_hash:ip"); 33 34/* Type specific function prefix */ 35#define HTYPE hash_ip 36#define IP_SET_HASH_WITH_NETMASK 37 38/* IPv4 variants */ 39 40/* Member elements */ 41struct hash_ip4_elem { 42 /* Zero valued IP addresses cannot be stored */ 43 __be32 ip; 44}; 45 46struct hash_ip4t_elem { 47 __be32 ip; 48 unsigned long timeout; 49}; 50 51struct hash_ip4c_elem { 52 __be32 ip; 53 struct ip_set_counter counter; 54}; 55 56struct hash_ip4ct_elem { 57 __be32 ip; 58 struct ip_set_counter counter; 59 unsigned long timeout; 60}; 61 62/* Common functions */ 63 64static inline bool 65hash_ip4_data_equal(const struct hash_ip4_elem *e1, 66 const struct hash_ip4_elem *e2, 67 u32 *multi) 68{ 69 return e1->ip == e2->ip; 70} 71 72static inline bool 73hash_ip4_data_list(struct sk_buff *skb, const struct hash_ip4_elem *e) 74{ 75 if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, e->ip)) 76 goto nla_put_failure; 77 return 0; 78 79nla_put_failure: 80 return 1; 81} 82 83static inline void 84hash_ip4_data_next(struct hash_ip4_elem *next, const struct hash_ip4_elem *e) 85{ 86 next->ip = e->ip; 87} 88 89#define MTYPE hash_ip4 90#define PF 4 91#define HOST_MASK 32 92#include "ip_set_hash_gen.h" 93 94static int 95hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb, 96 const struct xt_action_param *par, 97 enum ipset_adt adt, struct ip_set_adt_opt *opt) 98{ 99 const struct hash_ip *h = set->data; 100 ipset_adtfn adtfn = set->variant->adt[adt]; 101 struct hash_ip4_elem e = {}; 102 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); 103 __be32 ip; 104 105 ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip); 106 ip &= ip_set_netmask(h->netmask); 107 if (ip == 0) 108 return -EINVAL; 109 110 e.ip = ip; 111 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 112} 113 114static int 115hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], 116 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 117{ 118 const struct hash_ip *h = set->data; 119 ipset_adtfn adtfn = set->variant->adt[adt]; 120 struct hash_ip4_elem e = {}; 121 struct ip_set_ext ext = IP_SET_INIT_UEXT(h); 122 u32 ip, ip_to, hosts; 123 int ret = 0; 124 125 if (unlikely(!tb[IPSET_ATTR_IP] || 126 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 127 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 128 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 129 return -IPSET_ERR_PROTOCOL; 130 131 if (tb[IPSET_ATTR_LINENO]) 132 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 133 134 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) || 135 ip_set_get_extensions(set, tb, &ext); 136 if (ret) 137 return ret; 138 139 ip &= ip_set_hostmask(h->netmask); 140 141 if (adt == IPSET_TEST) { 142 e.ip = htonl(ip); 143 if (e.ip == 0) 144 return -IPSET_ERR_HASH_ELEM; 145 return adtfn(set, &e, &ext, &ext, flags); 146 } 147 148 ip_to = ip; 149 if (tb[IPSET_ATTR_IP_TO]) { 150 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 151 if (ret) 152 return ret; 153 if (ip > ip_to) 154 swap(ip, ip_to); 155 } else if (tb[IPSET_ATTR_CIDR]) { 156 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 157 158 if (!cidr || cidr > 32) 159 return -IPSET_ERR_INVALID_CIDR; 160 ip_set_mask_from_to(ip, ip_to, cidr); 161 } 162 163 hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); 164 165 if (retried) 166 ip = ntohl(h->next.ip); 167 for (; !before(ip_to, ip); ip += hosts) { 168 e.ip = htonl(ip); 169 if (e.ip == 0) 170 return -IPSET_ERR_HASH_ELEM; 171 ret = adtfn(set, &e, &ext, &ext, flags); 172 173 if (ret && !ip_set_eexist(ret, flags)) 174 return ret; 175 else 176 ret = 0; 177 } 178 return ret; 179} 180 181/* IPv6 variants */ 182 183/* Member elements */ 184struct hash_ip6_elem { 185 union nf_inet_addr ip; 186}; 187 188struct hash_ip6t_elem { 189 union nf_inet_addr ip; 190 unsigned long timeout; 191}; 192 193struct hash_ip6c_elem { 194 union nf_inet_addr ip; 195 struct ip_set_counter counter; 196}; 197 198struct hash_ip6ct_elem { 199 union nf_inet_addr ip; 200 struct ip_set_counter counter; 201 unsigned long timeout; 202}; 203 204/* Common functions */ 205 206static inline bool 207hash_ip6_data_equal(const struct hash_ip6_elem *ip1, 208 const struct hash_ip6_elem *ip2, 209 u32 *multi) 210{ 211 return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6); 212} 213 214static inline void 215hash_ip6_netmask(union nf_inet_addr *ip, u8 prefix) 216{ 217 ip6_netmask(ip, prefix); 218} 219 220static bool 221hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *e) 222{ 223 if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &e->ip.in6)) 224 goto nla_put_failure; 225 return 0; 226 227nla_put_failure: 228 return 1; 229} 230 231static inline void 232hash_ip6_data_next(struct hash_ip4_elem *next, const struct hash_ip6_elem *e) 233{ 234} 235 236#undef MTYPE 237#undef PF 238#undef HOST_MASK 239#undef HKEY_DATALEN 240 241#define MTYPE hash_ip6 242#define PF 6 243#define HOST_MASK 128 244 245#define IP_SET_EMIT_CREATE 246#include "ip_set_hash_gen.h" 247 248static int 249hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb, 250 const struct xt_action_param *par, 251 enum ipset_adt adt, struct ip_set_adt_opt *opt) 252{ 253 const struct hash_ip *h = set->data; 254 ipset_adtfn adtfn = set->variant->adt[adt]; 255 struct hash_ip6_elem e = {}; 256 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h); 257 258 ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); 259 hash_ip6_netmask(&e.ip, h->netmask); 260 if (ipv6_addr_any(&e.ip.in6)) 261 return -EINVAL; 262 263 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 264} 265 266static int 267hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[], 268 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 269{ 270 const struct hash_ip *h = set->data; 271 ipset_adtfn adtfn = set->variant->adt[adt]; 272 struct hash_ip6_elem e = {}; 273 struct ip_set_ext ext = IP_SET_INIT_UEXT(h); 274 int ret; 275 276 if (unlikely(!tb[IPSET_ATTR_IP] || 277 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 278 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 279 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || 280 tb[IPSET_ATTR_IP_TO] || 281 tb[IPSET_ATTR_CIDR])) 282 return -IPSET_ERR_PROTOCOL; 283 284 if (tb[IPSET_ATTR_LINENO]) 285 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 286 287 ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) || 288 ip_set_get_extensions(set, tb, &ext); 289 if (ret) 290 return ret; 291 292 hash_ip6_netmask(&e.ip, h->netmask); 293 if (ipv6_addr_any(&e.ip.in6)) 294 return -IPSET_ERR_HASH_ELEM; 295 296 ret = adtfn(set, &e, &ext, &ext, flags); 297 298 return ip_set_eexist(ret, flags) ? 0 : ret; 299} 300 301static struct ip_set_type hash_ip_type __read_mostly = { 302 .name = "hash:ip", 303 .protocol = IPSET_PROTOCOL, 304 .features = IPSET_TYPE_IP, 305 .dimension = IPSET_DIM_ONE, 306 .family = NFPROTO_UNSPEC, 307 .revision_min = REVISION_MIN, 308 .revision_max = REVISION_MAX, 309 .create = hash_ip_create, 310 .create_policy = { 311 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 312 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 313 [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 314 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 315 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 316 [IPSET_ATTR_NETMASK] = { .type = NLA_U8 }, 317 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 318 }, 319 .adt_policy = { 320 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 321 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 322 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 323 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 324 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 325 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 326 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 327 }, 328 .me = THIS_MODULE, 329}; 330 331static int __init 332hash_ip_init(void) 333{ 334 return ip_set_type_register(&hash_ip_type); 335} 336 337static void __exit 338hash_ip_fini(void) 339{ 340 ip_set_type_unregister(&hash_ip_type); 341} 342 343module_init(hash_ip_init); 344module_exit(hash_ip_fini); 345