1ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith/* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> 2ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith * Copyright (C) 2013 Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa> 3ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith * 4ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith * This program is free software; you can redistribute it and/or modify 5ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith * it under the terms of the GNU General Public License version 2 as 6ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith * published by the Free Software Foundation. 7ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith */ 8ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 9ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith/* Kernel module implementing an IP set type: the hash:net type */ 10ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 11ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include <linux/jhash.h> 12ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include <linux/module.h> 13ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include <linux/ip.h> 14ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include <linux/skbuff.h> 15ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include <linux/errno.h> 16ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include <linux/random.h> 17ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include <net/ip.h> 18ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include <net/ipv6.h> 19ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include <net/netlink.h> 20ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 21ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include <linux/netfilter.h> 22ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include <linux/netfilter/ipset/pfxlen.h> 23ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include <linux/netfilter/ipset/ip_set.h> 24ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include <linux/netfilter/ipset/ip_set_hash.h> 25ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 26ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#define IPSET_TYPE_REV_MIN 0 27af331419d34e2fc0e2d0c629734f8d160f95a3ecAnton Danilov/* 1 Forceadd support added */ 28af331419d34e2fc0e2d0c629734f8d160f95a3ecAnton Danilov#define IPSET_TYPE_REV_MAX 2 /* skbinfo support added */ 29ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 30ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver SmithMODULE_LICENSE("GPL"); 31ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver SmithMODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>"); 32ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver SmithIP_SET_MODULE_DESC("hash:net,net", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX); 33ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver SmithMODULE_ALIAS("ip_set_hash:net,net"); 34ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 35ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith/* Type specific function prefix */ 36ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#define HTYPE hash_netnet 37ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#define IP_SET_HASH_WITH_NETS 38ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#define IPSET_NET_COUNT 2 39ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 40ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith/* IPv4 variants */ 41ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 42ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith/* Member elements */ 43ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstruct hash_netnet4_elem { 44ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith union { 45ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith __be32 ip[2]; 46ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith __be64 ipcmp; 47ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith }; 48ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u8 nomatch; 49ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith union { 50ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u8 cidr[2]; 51ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u16 ccmp; 52ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith }; 53ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith}; 54ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 55ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith/* Common functions */ 56ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 57ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline bool 58ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet4_data_equal(const struct hash_netnet4_elem *ip1, 59ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith const struct hash_netnet4_elem *ip2, 60ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u32 *multi) 61ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 62ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return ip1->ipcmp == ip2->ipcmp && 63b49faea7655ec10ade15d7d007e4218ca578a513Dave Jones ip1->ccmp == ip2->ccmp; 64ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 65ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 66ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline int 67ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet4_do_data_match(const struct hash_netnet4_elem *elem) 68ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 69ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return elem->nomatch ? -ENOTEMPTY : 1; 70ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 71ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 72ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline void 73ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet4_data_set_flags(struct hash_netnet4_elem *elem, u32 flags) 74ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 75ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 76ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 77ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 78ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline void 79ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet4_data_reset_flags(struct hash_netnet4_elem *elem, u8 *flags) 80ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 81ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith swap(*flags, elem->nomatch); 82ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 83ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 84ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline void 85ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet4_data_reset_elem(struct hash_netnet4_elem *elem, 86ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith struct hash_netnet4_elem *orig) 87ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 88ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith elem->ip[1] = orig->ip[1]; 89ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 90ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 91ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline void 92ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet4_data_netmask(struct hash_netnet4_elem *elem, u8 cidr, bool inner) 93ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 94ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (inner) { 95ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith elem->ip[1] &= ip_set_netmask(cidr); 96ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith elem->cidr[1] = cidr; 97ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith } else { 98ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith elem->ip[0] &= ip_set_netmask(cidr); 99ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith elem->cidr[0] = cidr; 100ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith } 101ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 102ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 103ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic bool 104ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet4_data_list(struct sk_buff *skb, 105ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith const struct hash_netnet4_elem *data) 106ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 107ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 108ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 109ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip[0]) || 110ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith nla_put_ipaddr4(skb, IPSET_ATTR_IP2, data->ip[1]) || 111ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr[0]) || 112ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr[1]) || 113ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith (flags && 114ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 115ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith goto nla_put_failure; 1169562cf28d1b48d0545d7b5dd2995d00b45e1cb53Fengguang Wu return false; 117ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 118ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithnla_put_failure: 1199562cf28d1b48d0545d7b5dd2995d00b45e1cb53Fengguang Wu return true; 120ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 121ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 122ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline void 123ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet4_data_next(struct hash_netnet4_elem *next, 124ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith const struct hash_netnet4_elem *d) 125ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 126ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith next->ipcmp = d->ipcmp; 127ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 128ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 129ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#define MTYPE hash_netnet4 130ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#define PF 4 131ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#define HOST_MASK 32 132ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include "ip_set_hash_gen.h" 133ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 134ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic int 135ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet4_kadt(struct ip_set *set, const struct sk_buff *skb, 136ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith const struct xt_action_param *par, 137ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith enum ipset_adt adt, struct ip_set_adt_opt *opt) 138ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 139ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith const struct hash_netnet *h = set->data; 140ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ipset_adtfn adtfn = set->variant->adt[adt]; 1411a869205c75cb222263fa04f200485ffbe9eaadfJozsef Kadlecsik struct hash_netnet4_elem e = { }; 142ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 143ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 1441a869205c75cb222263fa04f200485ffbe9eaadfJozsef Kadlecsik e.cidr[0] = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK); 1451a869205c75cb222263fa04f200485ffbe9eaadfJozsef Kadlecsik e.cidr[1] = IP_SET_INIT_CIDR(h->nets[0].cidr[1], HOST_MASK); 146ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (adt == IPSET_TEST) 147ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.ccmp = (HOST_MASK << (sizeof(e.cidr[0]) * 8)) | HOST_MASK; 148ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 149ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip[0]); 150ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip4addrptr(skb, opt->flags & IPSET_DIM_TWO_SRC, &e.ip[1]); 151ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.ip[0] &= ip_set_netmask(e.cidr[0]); 152ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.ip[1] &= ip_set_netmask(e.cidr[1]); 153ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 154ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 155ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 156ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 157ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic int 158ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], 159ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 160ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 161ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith const struct hash_netnet *h = set->data; 162ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ipset_adtfn adtfn = set->variant->adt[adt]; 1631a869205c75cb222263fa04f200485ffbe9eaadfJozsef Kadlecsik struct hash_netnet4_elem e = { }; 164ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 165ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u32 ip = 0, ip_to = 0, last; 166ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u32 ip2 = 0, ip2_from = 0, ip2_to = 0, last2; 167ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u8 cidr, cidr2; 168ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith int ret; 169ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 1701a869205c75cb222263fa04f200485ffbe9eaadfJozsef Kadlecsik e.cidr[0] = e.cidr[1] = HOST_MASK; 171ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 172ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 173ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 174ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 175af331419d34e2fc0e2d0c629734f8d160f95a3ecAnton Danilov !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || 176af331419d34e2fc0e2d0c629734f8d160f95a3ecAnton Danilov !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) || 177af331419d34e2fc0e2d0c629734f8d160f95a3ecAnton Danilov !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) || 178af331419d34e2fc0e2d0c629734f8d160f95a3ecAnton Danilov !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE))) 179ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return -IPSET_ERR_PROTOCOL; 180ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 181ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (tb[IPSET_ATTR_LINENO]) 182ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 183ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 184ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip) || 185ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from) || 186ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip_set_get_extensions(set, tb, &ext); 187ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (ret) 188ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return ret; 189ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 190ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (tb[IPSET_ATTR_CIDR]) { 191ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); 192ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (!cidr || cidr > HOST_MASK) 193ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return -IPSET_ERR_INVALID_CIDR; 194ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.cidr[0] = cidr; 195ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith } 196ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 197ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (tb[IPSET_ATTR_CIDR2]) { 198ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith cidr2 = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 199ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (!cidr2 || cidr2 > HOST_MASK) 200ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return -IPSET_ERR_INVALID_CIDR; 201ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.cidr[1] = cidr2; 202ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith } 203ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 204ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (tb[IPSET_ATTR_CADT_FLAGS]) { 205ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 206ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (cadt_flags & IPSET_FLAG_NOMATCH) 207ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith flags |= (IPSET_FLAG_NOMATCH << 16); 208ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith } 209ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 2106e41ee684ea0c338e7d83fc88725581027856595Sergey Popovich if (adt == IPSET_TEST || !(tb[IPSET_ATTR_IP_TO] || 211ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith tb[IPSET_ATTR_IP2_TO])) { 212ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.ip[0] = htonl(ip & ip_set_hostmask(e.cidr[0])); 213ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.ip[1] = htonl(ip2_from & ip_set_hostmask(e.cidr[1])); 214ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ret = adtfn(set, &e, &ext, &ext, flags); 215ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return ip_set_enomatch(ret, flags, adt, set) ? -ret : 216ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip_set_eexist(ret, flags) ? 0 : ret; 217ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith } 218ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 219ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip_to = ip; 220ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (tb[IPSET_ATTR_IP_TO]) { 221ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); 222ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (ret) 223ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return ret; 224ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (ip_to < ip) 225ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith swap(ip, ip_to); 2266e41ee684ea0c338e7d83fc88725581027856595Sergey Popovich if (unlikely(ip + UINT_MAX == ip_to)) 227ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return -IPSET_ERR_HASH_RANGE; 2286e41ee684ea0c338e7d83fc88725581027856595Sergey Popovich } else 2296e41ee684ea0c338e7d83fc88725581027856595Sergey Popovich ip_set_mask_from_to(ip, ip_to, e.cidr[0]); 230ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 231ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip2_to = ip2_from; 232ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (tb[IPSET_ATTR_IP2_TO]) { 233ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to); 234ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (ret) 235ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return ret; 236ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (ip2_to < ip2_from) 237ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith swap(ip2_from, ip2_to); 2386e41ee684ea0c338e7d83fc88725581027856595Sergey Popovich if (unlikely(ip2_from + UINT_MAX == ip2_to)) 239ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return -IPSET_ERR_HASH_RANGE; 2406e41ee684ea0c338e7d83fc88725581027856595Sergey Popovich } else 2416e41ee684ea0c338e7d83fc88725581027856595Sergey Popovich ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]); 242ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 243ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (retried) 244ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip = ntohl(h->next.ip[0]); 245ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 246ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith while (!after(ip, ip_to)) { 247ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.ip[0] = htonl(ip); 248ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith last = ip_set_range_to_cidr(ip, ip_to, &cidr); 249ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.cidr[0] = cidr; 250ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip2 = (retried && 251ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip == ntohl(h->next.ip[0])) ? ntohl(h->next.ip[1]) 252ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith : ip2_from; 253ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith while (!after(ip2, ip2_to)) { 254ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.ip[1] = htonl(ip2); 255ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith last2 = ip_set_range_to_cidr(ip2, ip2_to, &cidr2); 256ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.cidr[1] = cidr2; 257ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ret = adtfn(set, &e, &ext, &ext, flags); 258ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (ret && !ip_set_eexist(ret, flags)) 259ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return ret; 260ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith else 261ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ret = 0; 262ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip2 = last2 + 1; 263ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith } 264ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip = last + 1; 265ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith } 266ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return ret; 267ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 268ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 269ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith/* IPv6 variants */ 270ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 271ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstruct hash_netnet6_elem { 272ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith union nf_inet_addr ip[2]; 273ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u8 nomatch; 274ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith union { 275ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u8 cidr[2]; 276ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u16 ccmp; 277ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith }; 278ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith}; 279ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 280ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith/* Common functions */ 281ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 282ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline bool 283ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet6_data_equal(const struct hash_netnet6_elem *ip1, 284ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith const struct hash_netnet6_elem *ip2, 285ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u32 *multi) 286ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 287ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return ipv6_addr_equal(&ip1->ip[0].in6, &ip2->ip[0].in6) && 288ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ipv6_addr_equal(&ip1->ip[1].in6, &ip2->ip[1].in6) && 289ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip1->ccmp == ip2->ccmp; 290ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 291ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 292ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline int 293ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet6_do_data_match(const struct hash_netnet6_elem *elem) 294ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 295ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return elem->nomatch ? -ENOTEMPTY : 1; 296ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 297ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 298ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline void 299ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet6_data_set_flags(struct hash_netnet6_elem *elem, u32 flags) 300ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 301ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith elem->nomatch = (flags >> 16) & IPSET_FLAG_NOMATCH; 302ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 303ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 304ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline void 305ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet6_data_reset_flags(struct hash_netnet6_elem *elem, u8 *flags) 306ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 307ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith swap(*flags, elem->nomatch); 308ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 309ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 310ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline void 311ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet6_data_reset_elem(struct hash_netnet6_elem *elem, 312ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith struct hash_netnet6_elem *orig) 313ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 314ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith elem->ip[1] = orig->ip[1]; 315ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 316ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 317ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline void 318ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet6_data_netmask(struct hash_netnet6_elem *elem, u8 cidr, bool inner) 319ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 320ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (inner) { 321ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip6_netmask(&elem->ip[1], cidr); 322ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith elem->cidr[1] = cidr; 323ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith } else { 324ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip6_netmask(&elem->ip[0], cidr); 325ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith elem->cidr[0] = cidr; 326ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith } 327ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 328ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 329ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic bool 330ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet6_data_list(struct sk_buff *skb, 331ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith const struct hash_netnet6_elem *data) 332ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 333ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u32 flags = data->nomatch ? IPSET_FLAG_NOMATCH : 0; 334ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 335ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip[0].in6) || 336ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith nla_put_ipaddr6(skb, IPSET_ATTR_IP2, &data->ip[1].in6) || 337ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith nla_put_u8(skb, IPSET_ATTR_CIDR, data->cidr[0]) || 338ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith nla_put_u8(skb, IPSET_ATTR_CIDR2, data->cidr[1]) || 339ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith (flags && 340ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) 341ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith goto nla_put_failure; 3429562cf28d1b48d0545d7b5dd2995d00b45e1cb53Fengguang Wu return false; 343ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 344ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithnla_put_failure: 3459562cf28d1b48d0545d7b5dd2995d00b45e1cb53Fengguang Wu return true; 346ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 347ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 348ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic inline void 349ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet6_data_next(struct hash_netnet4_elem *next, 350ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith const struct hash_netnet6_elem *d) 351ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 352ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 353ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 354ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#undef MTYPE 355ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#undef PF 356ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#undef HOST_MASK 357ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 358ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#define MTYPE hash_netnet6 359ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#define PF 6 360ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#define HOST_MASK 128 361ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#define IP_SET_EMIT_CREATE 362ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith#include "ip_set_hash_gen.h" 363ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 364ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic int 365ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet6_kadt(struct ip_set *set, const struct sk_buff *skb, 366ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith const struct xt_action_param *par, 367ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith enum ipset_adt adt, struct ip_set_adt_opt *opt) 368ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 369ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith const struct hash_netnet *h = set->data; 370ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ipset_adtfn adtfn = set->variant->adt[adt]; 3711a869205c75cb222263fa04f200485ffbe9eaadfJozsef Kadlecsik struct hash_netnet6_elem e = { }; 372ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); 373ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 3741a869205c75cb222263fa04f200485ffbe9eaadfJozsef Kadlecsik e.cidr[0] = IP_SET_INIT_CIDR(h->nets[0].cidr[0], HOST_MASK); 3751a869205c75cb222263fa04f200485ffbe9eaadfJozsef Kadlecsik e.cidr[1] = IP_SET_INIT_CIDR(h->nets[0].cidr[1], HOST_MASK); 376ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (adt == IPSET_TEST) 377ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.ccmp = (HOST_MASK << (sizeof(u8)*8)) | HOST_MASK; 378ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 379ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip[0].in6); 380ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip6addrptr(skb, opt->flags & IPSET_DIM_TWO_SRC, &e.ip[1].in6); 381ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip6_netmask(&e.ip[0], e.cidr[0]); 382ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip6_netmask(&e.ip[1], e.cidr[1]); 383ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 384ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); 385ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 386ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 387ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic int 388ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet6_uadt(struct ip_set *set, struct nlattr *tb[], 389ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) 390ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 391ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ipset_adtfn adtfn = set->variant->adt[adt]; 3921a869205c75cb222263fa04f200485ffbe9eaadfJozsef Kadlecsik struct hash_netnet6_elem e = { }; 393ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith struct ip_set_ext ext = IP_SET_INIT_UEXT(set); 394ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith int ret; 395ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 3961a869205c75cb222263fa04f200485ffbe9eaadfJozsef Kadlecsik e.cidr[0] = e.cidr[1] = HOST_MASK; 397ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || 398ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 399ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 400ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 401af331419d34e2fc0e2d0c629734f8d160f95a3ecAnton Danilov !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || 402af331419d34e2fc0e2d0c629734f8d160f95a3ecAnton Danilov !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) || 403af331419d34e2fc0e2d0c629734f8d160f95a3ecAnton Danilov !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) || 404af331419d34e2fc0e2d0c629734f8d160f95a3ecAnton Danilov !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE))) 405ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return -IPSET_ERR_PROTOCOL; 406ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (unlikely(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_IP2_TO])) 407ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 408ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 409ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (tb[IPSET_ATTR_LINENO]) 410ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); 411ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 412ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip[0]) || 413ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &e.ip[1]) || 414ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip_set_get_extensions(set, tb, &ext); 415ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (ret) 416ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return ret; 417ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 418ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (tb[IPSET_ATTR_CIDR]) 419ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.cidr[0] = nla_get_u8(tb[IPSET_ATTR_CIDR]); 420ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 421ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (tb[IPSET_ATTR_CIDR2]) 422ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.cidr[1] = nla_get_u8(tb[IPSET_ATTR_CIDR2]); 423ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 424ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (!e.cidr[0] || e.cidr[0] > HOST_MASK || !e.cidr[1] || 425ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith e.cidr[1] > HOST_MASK) 426ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return -IPSET_ERR_INVALID_CIDR; 427ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 428ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip6_netmask(&e.ip[0], e.cidr[0]); 429ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip6_netmask(&e.ip[1], e.cidr[1]); 430ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 431ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (tb[IPSET_ATTR_CADT_FLAGS]) { 432ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 433ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith if (cadt_flags & IPSET_FLAG_NOMATCH) 434ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith flags |= (IPSET_FLAG_NOMATCH << 16); 435ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith } 436ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 437ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ret = adtfn(set, &e, &ext, &ext, flags); 438ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 439ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return ip_set_enomatch(ret, flags, adt, set) ? -ret : 440ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip_set_eexist(ret, flags) ? 0 : ret; 441ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 442ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 443ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic struct ip_set_type hash_netnet_type __read_mostly = { 444ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith .name = "hash:net,net", 445ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith .protocol = IPSET_PROTOCOL, 446ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith .features = IPSET_TYPE_IP | IPSET_TYPE_IP2 | IPSET_TYPE_NOMATCH, 447ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith .dimension = IPSET_DIM_TWO, 448ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith .family = NFPROTO_UNSPEC, 449ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith .revision_min = IPSET_TYPE_REV_MIN, 450ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith .revision_max = IPSET_TYPE_REV_MAX, 451ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith .create = hash_netnet_create, 452ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith .create_policy = { 453ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, 454ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, 455ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, 456ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, 457ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 458ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 459ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith }, 460ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith .adt_policy = { 461ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_IP] = { .type = NLA_NESTED }, 462ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 463ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, 464ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_IP2_TO] = { .type = NLA_NESTED }, 465ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 466ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_CIDR2] = { .type = NLA_U8 }, 467ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 468ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 469ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 470ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 471fda75c6d9e31a901e25b922e86c8fd505c899873Oliver Smith [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 472af331419d34e2fc0e2d0c629734f8d160f95a3ecAnton Danilov [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 }, 473af331419d34e2fc0e2d0c629734f8d160f95a3ecAnton Danilov [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 }, 474af331419d34e2fc0e2d0c629734f8d160f95a3ecAnton Danilov [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 }, 475ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith }, 476ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith .me = THIS_MODULE, 477ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith}; 478ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 479ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic int __init 480ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet_init(void) 481ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 482ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith return ip_set_type_register(&hash_netnet_type); 483ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 484ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 485ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithstatic void __exit 486ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithhash_netnet_fini(void) 487ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith{ 488ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith ip_set_type_unregister(&hash_netnet_type); 489ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith} 490ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smith 491ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithmodule_init(hash_netnet_init); 492ea53ac5b630e813aec20c7cdcfe511daca70dee4Oliver Smithmodule_exit(hash_netnet_fini); 493