mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-07 13:15:12 +02:00
ipset; update to ipset-6.3 (genl)
* Handle EAGAIN from autoloading code. * Turn one nfgenmsg site into genlmsg to avoid protocol mismatch
This commit is contained in:
@@ -21,6 +21,10 @@ Enhancements:
|
||||
* revision reporting fixes
|
||||
- update to ipset 6.2
|
||||
* list:set timeout variant fixes
|
||||
- update to ipset 6.3
|
||||
* bitmap:ip,mac type requires "src" for MAC, enforce it
|
||||
- ipset-genl: handle EAGAIN return value emitted from autoloader
|
||||
- ipset-genl: resolve nfgenmsg remains and fix spurious protocol abort
|
||||
|
||||
|
||||
v1.33 (2011-02-02)
|
||||
|
@@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
/* The protocol version */
|
||||
#define IPSET_PROTOCOL 60
|
||||
#define IPSET_PROTOCOL 6
|
||||
|
||||
/* The max length of strings including NUL: set and type identifiers */
|
||||
#define IPSET_MAXNAMELEN 32
|
||||
|
@@ -14,7 +14,7 @@
|
||||
#include <linux/netlink.h>
|
||||
|
||||
/* The protocol version */
|
||||
#define IPSET_PROTOCOL 60
|
||||
#define IPSET_PROTOCOL 6
|
||||
|
||||
/* The max length of strings including NUL: set and type identifiers */
|
||||
#define IPSET_MAXNAMELEN 32
|
||||
|
@@ -344,6 +344,10 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
|
||||
ipset_adtfn adtfn = set->variant->adt[adt];
|
||||
struct ipmac data;
|
||||
|
||||
/* MAC can be src only */
|
||||
if (!(flags & IPSET_DIM_TWO_SRC))
|
||||
return 0;
|
||||
|
||||
data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
|
||||
if (data.id < map->first_ip || data.id > map->last_ip)
|
||||
return -IPSET_ERR_BITMAP_RANGE;
|
||||
|
@@ -26,6 +26,8 @@
|
||||
#include <net/genetlink.h>
|
||||
#define GENLMSG_DEFAULT_SIZE (NLMSG_DEFAULT_SIZE - GENL_HDRLEN)
|
||||
|
||||
struct genlmsg_buf;
|
||||
|
||||
static LIST_HEAD(ip_set_type_list); /* all registered set types */
|
||||
static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */
|
||||
static DEFINE_RWLOCK(ip_set_ref_lock); /* protects the set refs */
|
||||
@@ -82,14 +84,14 @@ find_set_type(const char *name, u8 family, u8 revision)
|
||||
static int
|
||||
try_to_load_type(const char *name)
|
||||
{
|
||||
nfnl_unlock();
|
||||
genl_unlock();
|
||||
pr_debug("try to load ip_set_%s\n", name);
|
||||
if (request_module("ip_set_%s", name) < 0) {
|
||||
pr_warning("Can't find ip_set type %s\n", name);
|
||||
nfnl_lock();
|
||||
genl_lock();
|
||||
return -IPSET_ERR_FIND_TYPE;
|
||||
}
|
||||
nfnl_lock();
|
||||
genl_lock();
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
@@ -99,8 +101,10 @@ find_set_type_get(const char *name, u8 family, u8 revision,
|
||||
struct ip_set_type **found)
|
||||
{
|
||||
struct ip_set_type *type;
|
||||
unsigned int retry = 0;
|
||||
int err;
|
||||
|
||||
retry:
|
||||
rcu_read_lock();
|
||||
*found = find_set_type(name, family, revision);
|
||||
if (*found) {
|
||||
@@ -115,7 +119,10 @@ find_set_type_get(const char *name, u8 family, u8 revision,
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return try_to_load_type(name);
|
||||
err = try_to_load_type(name);
|
||||
if (err == -EAGAIN && retry++ == 0)
|
||||
goto retry;
|
||||
return err;
|
||||
|
||||
unlock:
|
||||
rcu_read_unlock();
|
||||
@@ -131,7 +138,10 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
|
||||
{
|
||||
struct ip_set_type *type;
|
||||
bool found = false;
|
||||
unsigned int retry = 0;
|
||||
int err;
|
||||
|
||||
retry:
|
||||
*min = 255; *max = 0;
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(type, &ip_set_type_list, list)
|
||||
@@ -147,7 +157,10 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max)
|
||||
if (found)
|
||||
return 0;
|
||||
|
||||
return try_to_load_type(name);
|
||||
err = try_to_load_type(name);
|
||||
if (err == -EAGAIN && retry++ == 0)
|
||||
goto retry;
|
||||
return err;
|
||||
}
|
||||
|
||||
#define family_name(f) ((f) == AF_INET ? "inet" : \
|
||||
@@ -482,9 +495,9 @@ ip_set_nfnl_get(const char *name)
|
||||
struct ip_set *s;
|
||||
ip_set_id_t index;
|
||||
|
||||
nfnl_lock();
|
||||
genl_lock();
|
||||
index = ip_set_get_byname(name, &s);
|
||||
nfnl_unlock();
|
||||
genl_unlock();
|
||||
|
||||
return index;
|
||||
}
|
||||
@@ -502,12 +515,12 @@ ip_set_nfnl_get_byindex(ip_set_id_t index)
|
||||
if (index > ip_set_max)
|
||||
return IPSET_INVALID_ID;
|
||||
|
||||
nfnl_lock();
|
||||
genl_lock();
|
||||
if (ip_set_list[index])
|
||||
__ip_set_get(index);
|
||||
else
|
||||
index = IPSET_INVALID_ID;
|
||||
nfnl_unlock();
|
||||
genl_unlock();
|
||||
|
||||
return index;
|
||||
}
|
||||
@@ -523,9 +536,9 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_get_byindex);
|
||||
void
|
||||
ip_set_nfnl_put(ip_set_id_t index)
|
||||
{
|
||||
nfnl_lock();
|
||||
genl_lock();
|
||||
ip_set_put_byindex(index);
|
||||
nfnl_unlock();
|
||||
genl_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
|
||||
|
||||
@@ -548,11 +561,11 @@ flag_exist(const struct genlmsghdr *ghdr)
|
||||
return ghdr->reserved & NLM_F_EXCL ? 0 : IPSET_FLAG_EXIST;
|
||||
}
|
||||
|
||||
static struct nlmsghdr *
|
||||
static struct genlmsg_buf *
|
||||
start_msg(struct sk_buff *skb, u32 pid, u32 seq, unsigned int flags,
|
||||
enum ipset_cmd cmd)
|
||||
{
|
||||
void *nlh;
|
||||
struct genlmsg_buf *nlh;
|
||||
|
||||
nlh = genlmsg_put(skb, pid, seq, &ip_set_netlink_subsys, flags, cmd);
|
||||
if (nlh == NULL)
|
||||
@@ -950,10 +963,11 @@ ip_set_dump_done(struct netlink_callback *cb)
|
||||
}
|
||||
|
||||
static inline void
|
||||
dump_attrs(void *phdr)
|
||||
dump_attrs(struct genlmsg_buf *phdr)
|
||||
{
|
||||
const struct nlattr *attr;
|
||||
const struct nlmsghdr *nlh = phdr - GENL_HDRLEN - NLMSG_HDRLEN;
|
||||
const struct nlmsghdr *nlh =
|
||||
(const void *)phdr - GENL_HDRLEN - NLMSG_HDRLEN;
|
||||
int rem;
|
||||
|
||||
pr_debug("dump nlmsg\n");
|
||||
@@ -999,14 +1013,14 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
ip_set_id_t index = IPSET_INVALID_ID, max;
|
||||
struct ip_set *set = NULL;
|
||||
struct nlmsghdr *nlh = NULL;
|
||||
struct genlmsg_buf *nlh = NULL;
|
||||
unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0;
|
||||
int ret = 0;
|
||||
|
||||
if (cb->args[0] == DUMP_INIT) {
|
||||
ret = dump_init(cb);
|
||||
if (ret < 0) {
|
||||
nlh = nlmsg_hdr(cb->skb);
|
||||
struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
|
||||
/* We have to create and send the error message
|
||||
* manually :-( */
|
||||
if (nlh->nlmsg_flags & NLM_F_ACK)
|
||||
@@ -1159,7 +1173,7 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
|
||||
struct sk_buff *skb2;
|
||||
struct nlmsgerr *errmsg;
|
||||
size_t payload = sizeof(*errmsg) + nlmsg_len(nlh);
|
||||
int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg));
|
||||
int min_len = NLMSG_SPACE(sizeof(struct genlmsghdr));
|
||||
struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
|
||||
struct nlattr *cmdattr;
|
||||
u32 *errline;
|
||||
@@ -1342,7 +1356,7 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info)
|
||||
struct nlattr *const *attr = info->attrs;
|
||||
const struct nlmsghdr *nlh = info->nlhdr;
|
||||
struct sk_buff *skb2;
|
||||
struct nlmsghdr *nlh2;
|
||||
struct genlmsg_buf *nlh2;
|
||||
ip_set_id_t index;
|
||||
int ret = 0;
|
||||
|
||||
@@ -1355,7 +1369,7 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info)
|
||||
return -ENOENT;
|
||||
set = ip_set_list[index];
|
||||
|
||||
skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
skb2 = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
||||
if (skb2 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1377,7 +1391,7 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info)
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
nlmsg_cancel(skb2, nlh2);
|
||||
genlmsg_cancel(skb2, nlh2);
|
||||
nlmsg_failure:
|
||||
kfree_skb(skb2);
|
||||
return -EMSGSIZE;
|
||||
@@ -1399,7 +1413,7 @@ ip_set_type(struct sk_buff *skb, struct genl_info *info)
|
||||
const struct nlmsghdr *nlh = info->nlhdr;
|
||||
|
||||
struct sk_buff *skb2;
|
||||
void *nlh2;
|
||||
struct genlmsg_buf *nlh2;
|
||||
u8 family, min, max;
|
||||
const char *typename;
|
||||
int ret = 0;
|
||||
@@ -1458,7 +1472,7 @@ ip_set_protocol(struct sk_buff *skb, struct genl_info *info)
|
||||
const struct nlmsghdr *nlh = info->nlhdr;
|
||||
|
||||
struct sk_buff *skb2;
|
||||
void *nlh2;
|
||||
struct genlmsg_buf *nlh2;
|
||||
int ret = 0;
|
||||
|
||||
if (unlikely(attr[IPSET_ATTR_PROTOCOL] == NULL))
|
||||
@@ -1633,9 +1647,9 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
|
||||
goto done;
|
||||
}
|
||||
req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0';
|
||||
nfnl_lock();
|
||||
genl_lock();
|
||||
req_get->set.index = find_set_id(req_get->set.name);
|
||||
nfnl_unlock();
|
||||
genl_unlock();
|
||||
goto copy;
|
||||
}
|
||||
case IP_SET_OP_GET_BYINDEX: {
|
||||
@@ -1646,12 +1660,12 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
nfnl_lock();
|
||||
genl_lock();
|
||||
strncpy(req_get->set.name,
|
||||
ip_set_list[req_get->set.index]
|
||||
? ip_set_list[req_get->set.index]->name : "",
|
||||
IPSET_MAXNAMELEN);
|
||||
nfnl_unlock();
|
||||
genl_unlock();
|
||||
goto copy;
|
||||
}
|
||||
default:
|
||||
|
@@ -310,8 +310,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
|
||||
!id_eq(map, i + 1, refid)) ||
|
||||
(before < 0 &&
|
||||
(i == 0 || !id_eq(map, i - 1, refid)))) {
|
||||
ret = -IPSET_ERR_EXIST;
|
||||
goto finish;
|
||||
ret = -IPSET_ERR_EXIST;
|
||||
goto finish;
|
||||
}
|
||||
e->timeout = ip_set_timeout_set(timeout);
|
||||
ip_set_put_byindex(id);
|
||||
|
@@ -302,9 +302,10 @@ matched by the kernel, it will automatically fill out the missing MAC address wi
|
||||
source MAC address from the packet. If the entry was specified with a timeout value,
|
||||
the timer starts off when the IP and MAC address pair is complete.
|
||||
.PP
|
||||
Please note, the \fBset\fR match and \fBSET\fR target netfilter kernel modules
|
||||
\fBalways\fR use the source MAC address from the packet to match, add or delete
|
||||
entries from a \fBbitmap:ip,mac\fR type of set.
|
||||
The \fBbitmap:ip,mac\fR type of sets require two \fBsrc/dst\fR parameters of
|
||||
the \fBset\fR match and \fBSET\fR target netfilter kernel modules and the second
|
||||
one must be \fBsrc\fR to match, add or delete entries because the \fBset\fR match
|
||||
and \fBSET\fR target have access to the source MAC address only.
|
||||
.PP
|
||||
Examples:
|
||||
.IP
|
||||
|
@@ -115,6 +115,7 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par)
|
||||
if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) {
|
||||
pr_warning("Protocol error: set match dimension "
|
||||
"is over the limit!\n");
|
||||
ip_set_nfnl_put(info->match_set.index);
|
||||
return CHECK_FAIL(-ERANGE); /* error */
|
||||
}
|
||||
|
||||
@@ -179,6 +180,8 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
|
||||
if (index == IPSET_INVALID_ID) {
|
||||
pr_warning("Cannot find del_set index %u as target\n",
|
||||
info->del_set.index);
|
||||
if (info->add_set.index != IPSET_INVALID_ID)
|
||||
ip_set_nfnl_put(info->add_set.index);
|
||||
return CHECK_FAIL(-ENOENT); /* error */
|
||||
}
|
||||
}
|
||||
@@ -186,6 +189,10 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
|
||||
info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) {
|
||||
pr_warning("Protocol error: SET target dimension "
|
||||
"is over the limit!\n");
|
||||
if (info->add_set.index != IPSET_INVALID_ID)
|
||||
ip_set_nfnl_put(info->add_set.index);
|
||||
if (info->del_set.index != IPSET_INVALID_ID)
|
||||
ip_set_nfnl_put(info->del_set.index);
|
||||
return CHECK_FAIL(-ERANGE); /* error */
|
||||
}
|
||||
|
||||
@@ -246,6 +253,7 @@ set_match_checkentry(const struct xt_mtchk_param *par)
|
||||
if (info->match_set.dim > IPSET_DIM_MAX) {
|
||||
pr_warning("Protocol error: set match dimension "
|
||||
"is over the limit!\n");
|
||||
ip_set_nfnl_put(info->match_set.index);
|
||||
return CHECK_FAIL(-ERANGE); /* error */
|
||||
}
|
||||
|
||||
@@ -278,7 +286,7 @@ set_target(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
if (info->del_set.index != IPSET_INVALID_ID)
|
||||
ip_set_del(info->del_set.index,
|
||||
skb, par->family,
|
||||
info->add_set.dim,
|
||||
info->del_set.dim,
|
||||
info->del_set.flags);
|
||||
|
||||
return XT_CONTINUE;
|
||||
@@ -309,13 +317,19 @@ set_target_checkentry(const struct xt_tgchk_param *par)
|
||||
if (index == IPSET_INVALID_ID) {
|
||||
pr_warning("Cannot find del_set index %u as target\n",
|
||||
info->del_set.index);
|
||||
if (info->add_set.index != IPSET_INVALID_ID)
|
||||
ip_set_nfnl_put(info->add_set.index);
|
||||
return CHECK_FAIL(-ENOENT); /* error */
|
||||
}
|
||||
}
|
||||
if (info->add_set.dim > IPSET_DIM_MAX ||
|
||||
info->del_set.flags > IPSET_DIM_MAX) {
|
||||
info->del_set.dim > IPSET_DIM_MAX) {
|
||||
pr_warning("Protocol error: SET target dimension "
|
||||
"is over the limit!\n");
|
||||
if (info->add_set.index != IPSET_INVALID_ID)
|
||||
ip_set_nfnl_put(info->add_set.index);
|
||||
if (info->del_set.index != IPSET_INVALID_ID)
|
||||
ip_set_nfnl_put(info->del_set.index);
|
||||
return CHECK_FAIL(-ERANGE); /* error */
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user