ipset: update to 6.7-genl

This commit is contained in:
Jan Engelhardt
2011-05-31 22:53:12 +02:00
parent cfb72bf468
commit b2fc85c589
54 changed files with 1823 additions and 655 deletions

2
README
View File

@@ -19,7 +19,7 @@ simplified, and sped up.
Included in this package
========================
- ipset 4.5
- ipset 6.6a-genl
- ipset 6.7-genl
- xt_ACCOUNT 1.16, libxt_ACCOUNT 1.3

View File

@@ -4,7 +4,7 @@ obj-m += xt_set.o
obj-m += ip_set.o ip_set_bitmap_ip.o ip_set_bitmap_ipmac.o
obj-m += ip_set_bitmap_port.o ip_set_hash_ip.o ip_set_hash_ipport.o
obj-m += ip_set_hash_ipportip.o ip_set_hash_ipportnet.o ip_set_hash_net.o
obj-m += ip_set_hash_netport.o ip_set_list_set.o
obj-m += ip_set_hash_netiface.o ip_set_hash_netport.o ip_set_list_set.o
ip_set-y := ip_set_core.o ip_set_getport.o pfxlen.o

View File

@@ -17,7 +17,8 @@ ipset_SOURCES = src/ipset.c src/errcode.c src/ui.c src/ipset_bitmap_ip.c \
src/ipset_bitmap_ipmac.c src/ipset_bitmap_port.c \
src/ipset_hash_ip.c src/ipset_hash_ipport.c \
src/ipset_hash_ipportip.c src/ipset_hash_ipportnet.c \
src/ipset_hash_net.c src/ipset_hash_netport.c \
src/ipset_hash_net.c src/ipset_hash_netiface.c \
src/ipset_hash_netport.c \
src/ipset_list_set.c
ipset_LDADD = libipset.la

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_DATA_H
@@ -46,11 +46,13 @@ enum ipset_opt {
IPSET_OPT_CIDR2,
IPSET_OPT_IP2_TO,
IPSET_OPT_PROTO,
IPSET_OPT_IFACE,
/* Swap/rename to */
IPSET_OPT_SETNAME2,
/* Flags */
IPSET_OPT_EXIST,
IPSET_OPT_BEFORE,
IPSET_OPT_PHYSDEV,
/* Internal options */
IPSET_OPT_FLAGS = 48, /* IPSET_FLAG_EXIST| */
IPSET_OPT_CADT_FLAGS, /* IPSET_FLAG_BEFORE| */
@@ -66,7 +68,7 @@ enum ipset_opt {
#define IPSET_FLAGS_ALL (~0LL)
#define IPSET_CREATE_FLAGS \
( IPSET_FLAG(IPSET_OPT_FAMILY) \
(IPSET_FLAG(IPSET_OPT_FAMILY) \
| IPSET_FLAG(IPSET_OPT_TYPENAME)\
| IPSET_FLAG(IPSET_OPT_TYPE) \
| IPSET_FLAG(IPSET_OPT_IP) \
@@ -84,7 +86,7 @@ enum ipset_opt {
| IPSET_FLAG(IPSET_OPT_SIZE))
#define IPSET_ADT_FLAGS \
( IPSET_FLAG(IPSET_OPT_IP) \
(IPSET_FLAG(IPSET_OPT_IP) \
| IPSET_FLAG(IPSET_OPT_IP_TO) \
| IPSET_FLAG(IPSET_OPT_CIDR) \
| IPSET_FLAG(IPSET_OPT_PORT) \
@@ -96,8 +98,10 @@ enum ipset_opt {
| IPSET_FLAG(IPSET_OPT_IP2) \
| IPSET_FLAG(IPSET_OPT_CIDR2) \
| IPSET_FLAG(IPSET_OPT_PROTO) \
| IPSET_FLAG(IPSET_OPT_IFACE) \
| IPSET_FLAG(IPSET_OPT_CADT_FLAGS)\
| IPSET_FLAG(IPSET_OPT_BEFORE))
| IPSET_FLAG(IPSET_OPT_BEFORE) \
| IPSET_FLAG(IPSET_OPT_PHYSDEV))
struct ipset_data;
@@ -110,8 +114,8 @@ extern bool ipset_data_ignored(struct ipset_data *data, enum ipset_opt opt);
extern int ipset_data_set(struct ipset_data *data, enum ipset_opt opt,
const void *value);
extern const void * ipset_data_get(const struct ipset_data *data,
enum ipset_opt opt);
extern const void *ipset_data_get(const struct ipset_data *data,
enum ipset_opt opt);
static inline bool
ipset_data_test(const struct ipset_data *data, enum ipset_opt opt)
@@ -120,13 +124,13 @@ ipset_data_test(const struct ipset_data *data, enum ipset_opt opt)
}
/* Shortcuts */
extern const char * ipset_data_setname(const struct ipset_data *data);
extern const char *ipset_data_setname(const struct ipset_data *data);
extern uint8_t ipset_data_family(const struct ipset_data *data);
extern uint8_t ipset_data_cidr(const struct ipset_data *data);
extern uint64_t ipset_data_flags(const struct ipset_data *data);
extern void ipset_data_reset(struct ipset_data *data);
extern struct ipset_data * ipset_data_init(void);
extern struct ipset_data *ipset_data_init(void);
extern void ipset_data_fini(struct ipset_data *data);
extern size_t ipset_data_sizeof(enum ipset_opt opt, uint8_t family);

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_DEBUG_H
@@ -12,7 +12,7 @@
#include <sys/socket.h>
#include <linux/netlink.h>
#define D(fmt, args...) \
fprintf(stderr, "%s: %s: " fmt "\n", __FILE__, __FUNCTION__ , ## args)
fprintf(stderr, "%s: %s: " fmt "\n", __FILE__, __func__ , ## args)
#define IF_D(test, fmt, args...) \
if (test) \
D(fmt , ## args)

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_ERRCODE_H
@@ -13,9 +13,9 @@ struct ipset_session;
/* Kernel error code to message table */
struct ipset_errcode_table {
int errcode; /* error code returned by the kernel */
enum ipset_cmd cmd; /* issued command */
const char *message; /* error message the code translated to */
int errcode; /* error code returned by the kernel */
enum ipset_cmd cmd; /* issued command */
const char *message; /* error message the code translated to */
};
extern int ipset_errcode(struct ipset_session *session, enum ipset_cmd cmd,

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_ICMP_H
@@ -9,8 +9,8 @@
#include <stdint.h> /* uintxx_t */
extern const char * id_to_icmp(uint8_t id);
extern const char * icmp_to_name(uint8_t type, uint8_t code);
extern const char *id_to_icmp(uint8_t id);
extern const char *icmp_to_name(uint8_t type, uint8_t code);
extern int name_to_icmp(const char *str, uint16_t *typecode);
#endif /* LIBIPSET_ICMP_H */

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_ICMPV6_H
@@ -9,8 +9,8 @@
#include <stdint.h> /* uintxx_t */
extern const char * id_to_icmpv6(uint8_t id);
extern const char * icmpv6_to_name(uint8_t type, uint8_t code);
extern const char *id_to_icmpv6(uint8_t id);
extern const char *icmpv6_to_name(uint8_t type, uint8_t code);
extern int name_to_icmpv6(const char *str, uint16_t *typecode);
#endif /* LIBIPSET_ICMPV6_H */

View File

@@ -105,6 +105,7 @@ enum {
IPSET_ATTR_IP2,
IPSET_ATTR_CIDR2,
IPSET_ATTR_IP2_TO,
IPSET_ATTR_IFACE,
__IPSET_ATTR_ADT_MAX,
};
#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
@@ -153,6 +154,8 @@ enum ipset_cmd_flags {
enum ipset_cadt_flags {
IPSET_FLAG_BIT_BEFORE = 0,
IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE),
IPSET_FLAG_BIT_PHYSDEV = 1,
IPSET_FLAG_PHYSDEV = (1 << IPSET_FLAG_BIT_PHYSDEV),
};
/* Commands with settype-specific attributes */

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_MNL_H

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_NF_INET_ADDR_H

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_PARSE_H
@@ -23,7 +23,7 @@ typedef int (*ipset_parsefn)(struct ipset_session *s,
enum ipset_opt opt, const char *str);
extern int ipset_parse_ether(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_port(struct ipset_session *session,
enum ipset_opt opt, const char *str,
const char *proto);
@@ -35,23 +35,23 @@ extern int ipset_parse_tcp_port(struct ipset_session *session,
extern int ipset_parse_single_tcp_port(struct ipset_session *session,
enum ipset_opt opt, const char *str);
extern int ipset_parse_proto(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_icmp(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_icmpv6(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_proto_port(struct ipset_session *session,
enum ipset_opt opt, const char *str);
extern int ipset_parse_family(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_ip(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_single_ip(struct ipset_session *session,
enum ipset_opt opt, const char *str);
extern int ipset_parse_net(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_range(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_netrange(struct ipset_session *session,
enum ipset_opt opt, const char *str);
extern int ipset_parse_iprange(struct ipset_session *session,
@@ -63,32 +63,34 @@ extern int ipset_parse_ip4_single6(struct ipset_session *session,
extern int ipset_parse_ip4_net6(struct ipset_session *session,
enum ipset_opt opt, const char *str);
extern int ipset_parse_name(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_before(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_after(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_setname(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_uint32(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_uint8(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_netmask(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_flag(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_typename(struct ipset_session *session,
enum ipset_opt opt, const char *str);
extern int ipset_parse_iface(struct ipset_session *session,
enum ipset_opt opt, const char *str);
extern int ipset_parse_output(struct ipset_session *session,
int opt, const char *str);
int opt, const char *str);
extern int ipset_parse_ignored(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_parse_elem(struct ipset_session *session,
enum ipset_opt opt, const char *str);
enum ipset_opt opt, const char *str);
extern int ipset_call_parser(struct ipset_session *session,
const struct ipset_arg *arg,
const char *str);
const struct ipset_arg *arg,
const char *str);
/* Compatibility parser functions */
extern int ipset_parse_iptimeout(struct ipset_session *session,

View File

@@ -12,7 +12,7 @@
{.ip6 = { \
__constant_htonl(a), __constant_htonl(b), \
__constant_htonl(c), __constant_htonl(d), \
}}
} }
/*
* This table works for both IPv4 and IPv6;

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_PRINT_H
@@ -37,6 +37,9 @@ extern int ipset_print_name(char *buf, unsigned int len,
extern int ipset_print_port(char *buf, unsigned int len,
const struct ipset_data *data,
enum ipset_opt opt, uint8_t env);
extern int ipset_print_iface(char *buf, unsigned int len,
const struct ipset_data *data,
enum ipset_opt opt, uint8_t env);
extern int ipset_print_proto(char *buf, unsigned int len,
const struct ipset_data *data,
enum ipset_opt opt, uint8_t env);

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_SESSION_H
@@ -21,10 +21,14 @@ struct ipset_session;
struct ipset_data;
struct ipset_handle;
extern struct ipset_data * ipset_session_data(const struct ipset_session *session);
extern struct ipset_handle * ipset_session_handle(const struct ipset_session *session);
extern const struct ipset_type * ipset_saved_type(const struct ipset_session *session);
extern void ipset_session_lineno(struct ipset_session *session, uint32_t lineno);
extern struct ipset_data *
ipset_session_data(const struct ipset_session *session);
extern struct ipset_handle *
ipset_session_handle(const struct ipset_session *session);
extern const struct ipset_type *
ipset_saved_type(const struct ipset_session *session);
extern void ipset_session_lineno(struct ipset_session *session,
uint32_t lineno);
enum ipset_err_type {
IPSET_ERROR,
@@ -47,8 +51,8 @@ extern int ipset_session_report(struct ipset_session *session,
})
extern void ipset_session_report_reset(struct ipset_session *session);
extern const char * ipset_session_error(const struct ipset_session *session);
extern const char * ipset_session_warning(const struct ipset_session *session);
extern const char *ipset_session_error(const struct ipset_session *session);
extern const char *ipset_session_warning(const struct ipset_session *session);
#define ipset_session_data_set(session, opt, value) \
ipset_data_set(ipset_session_data(session), opt, value)
@@ -93,7 +97,7 @@ extern int ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd,
typedef int (*ipset_outfn)(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
extern struct ipset_session * ipset_session_init(ipset_outfn outfn);
extern struct ipset_session *ipset_session_init(ipset_outfn outfn);
extern int ipset_session_fini(struct ipset_session *session);
extern void ipset_debug_msg(const char *dir, void *buffer, int len);

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_TRANSPORT_H
@@ -12,7 +12,7 @@
#include <libmnl/libmnl.h> /* mnl_cb_t */
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
struct ipset_handle;

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_TYPES_H
@@ -97,13 +97,14 @@ extern int ipset_cache_swap(const char *from, const char *to);
extern int ipset_cache_init(void);
extern void ipset_cache_fini(void);
extern const struct ipset_type * ipset_type_get(struct ipset_session *session,
enum ipset_cmd cmd);
extern const struct ipset_type * ipset_type_check(struct ipset_session *session);
extern const struct ipset_type *
ipset_type_get(struct ipset_session *session, enum ipset_cmd cmd);
extern const struct ipset_type *
ipset_type_check(struct ipset_session *session);
extern int ipset_type_add(struct ipset_type *type);
extern const struct ipset_type * ipset_types(void);
extern const char * ipset_typename_resolve(const char *str);
extern const struct ipset_type *ipset_types(void);
extern const char *ipset_typename_resolve(const char *str);
extern bool ipset_match_typename(const char *str,
const struct ipset_type *t);

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_UI_H

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef LIBIPSET_UTILS_H
@@ -11,10 +11,10 @@
#include <netinet/in.h> /* struct in[6]_addr */
/* String equality tests */
#define STREQ(a,b) (strcmp(a,b) == 0)
#define STRNEQ(a,b,n) (strncmp(a,b,n) == 0)
#define STRCASEQ(a,b) (strcasecmp(a,b) == 0)
#define STRNCASEQ(a,b,n) (strncasecmp(a,b,n) == 0)
#define STREQ(a, b) (strcmp(a, b) == 0)
#define STRNEQ(a, b, n) (strncmp(a, b, n) == 0)
#define STRCASEQ(a, b) (strcasecmp(a, b) == 0)
#define STRNCASEQ(a, b, n) (strncasecmp(a, b, n) == 0)
/* Stringify tokens */
#define _STR(c) #c

View File

@@ -107,6 +107,7 @@ enum {
IPSET_ATTR_IP2,
IPSET_ATTR_CIDR2,
IPSET_ATTR_IP2_TO,
IPSET_ATTR_IFACE,
__IPSET_ATTR_ADT_MAX,
};
#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
@@ -155,6 +156,8 @@ enum ipset_cmd_flags {
enum ipset_cadt_flags {
IPSET_FLAG_BIT_BEFORE = 0,
IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE),
IPSET_FLAG_BIT_PHYSDEV = 1,
IPSET_FLAG_PHYSDEV = (1 << IPSET_FLAG_BIT_PHYSDEV),
};
/* Commands with settype-specific attributes */
@@ -214,6 +217,8 @@ enum ip_set_feature {
IPSET_TYPE_IP2 = (1 << IPSET_TYPE_IP2_FLAG),
IPSET_TYPE_NAME_FLAG = 4,
IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG),
IPSET_TYPE_IFACE_FLAG = 5,
IPSET_TYPE_IFACE = (1 << IPSET_TYPE_IFACE_FLAG),
/* Strictly speaking not a feature, but a flag for dumping:
* this settype must be dumped last */
IPSET_DUMP_LAST_FLAG = 7,
@@ -328,7 +333,7 @@ struct ip_set {
/* register and unregister set references */
extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);
extern void ip_set_put_byindex(ip_set_id_t index);
extern const char * ip_set_name_byindex(ip_set_id_t index);
extern const char *ip_set_name_byindex(ip_set_id_t index);
extern ip_set_id_t ip_set_nfnl_get(const char *name);
extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index);
extern void ip_set_nfnl_put(ip_set_id_t index);
@@ -346,7 +351,7 @@ extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
const struct ip_set_adt_opt *opt);
/* Utility functions */
extern void * ip_set_alloc(size_t size);
extern void *ip_set_alloc(size_t size);
extern void ip_set_free(void *members);
extern int ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr);
extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr);
@@ -356,7 +361,7 @@ ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)
{
__be32 ip;
int ret = ip_set_get_ipaddr4(nla, &ip);
if (ret)
return ret;
*ipaddr = ntohl(ip);

View File

@@ -43,7 +43,7 @@ struct htable {
struct hbucket bucket[0]; /* hashtable buckets */
};
#define hbucket(h, i) &((h)->bucket[i])
#define hbucket(h, i) (&((h)->bucket[i]))
/* Book-keeping of the prefixes added to the set */
struct ip_set_hash_nets {
@@ -63,6 +63,9 @@ struct ip_set_hash {
#ifdef IP_SET_HASH_WITH_NETMASK
u8 netmask; /* netmask value for subnets to store */
#endif
#ifdef IP_SET_HASH_WITH_RBTREE
struct rb_root rbtree;
#endif
#ifdef IP_SET_HASH_WITH_NETS
struct ip_set_hash_nets nets[0]; /* book-keeping of prefixes */
#endif
@@ -200,6 +203,9 @@ ip_set_hash_destroy(struct ip_set *set)
del_timer_sync(&h->gc);
ahash_destroy(h->table);
#ifdef IP_SET_HASH_WITH_RBTREE
rbtree_destroy(&h->rbtree);
#endif
kfree(h);
set->data = NULL;

View File

@@ -635,7 +635,8 @@ static struct ip_set_type bitmap_ipmac_type = {
},
.adt_policy = {
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
[IPSET_ATTR_ETHER] = { .type = NLA_BINARY, .len = ETH_ALEN },
[IPSET_ATTR_ETHER] = { .type = NLA_BINARY,
.len = ETH_ALEN },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
},

View File

@@ -695,8 +695,8 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info)
if (attr[IPSET_ATTR_DATA] &&
nla_parse_nested(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA],
set->type->create_policy)) {
ret = -IPSET_ERR_PROTOCOL;
goto put_out;
ret = -IPSET_ERR_PROTOCOL;
goto put_out;
}
ret = set->type->create(set, tb, flags);

View File

@@ -187,7 +187,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
return -IPSET_ERR_TIMEOUT;
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
data.ip = htonl(ip & ip_set_hostmask(data.cidr));
ret = adtfn(set, &data, timeout, flags);
@@ -205,7 +205,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
return -IPSET_ERR_HASH_RANGE;
}
if (retried)
ip = h->next.ip;
ip = h->next.ip;
while (!after(ip, ip_to)) {
data.ip = htonl(ip);
last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);

View File

@@ -0,0 +1,762 @@
/* Copyright (C) 2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/* Kernel module implementing an IP set type: the hash:net,iface type */
#include "jhash.h"
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/skbuff.h>
#include <linux/errno.h>
#include <linux/random.h>
#include <linux/rbtree.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <net/netlink.h>
#include <linux/netfilter.h>
#include "pfxlen.h"
#include "ip_set.h"
#include "ip_set_timeout.h"
#include "ip_set_hash.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
MODULE_DESCRIPTION("hash:net,iface type of IP sets");
MODULE_ALIAS("ip_set_hash:net,iface");
/* Interface name rbtree */
struct iface_node {
struct rb_node node;
char iface[IFNAMSIZ];
};
#define iface_data(n) (rb_entry(n, struct iface_node, node)->iface)
static inline long
ifname_compare(const char *_a, const char *_b)
{
const long *a = (const long *)_a;
const long *b = (const long *)_b;
BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
if (a[0] != b[0])
return a[0] - b[0];
if (IFNAMSIZ > sizeof(long)) {
if (a[1] != b[1])
return a[1] - b[1];
}
if (IFNAMSIZ > 2 * sizeof(long)) {
if (a[2] != b[2])
return a[2] - b[2];
}
if (IFNAMSIZ > 3 * sizeof(long)) {
if (a[3] != b[3])
return a[3] - b[3];
}
return 0;
}
static void
rbtree_destroy(struct rb_root *root)
{
struct rb_node *p, *n = root->rb_node;
struct iface_node *node;
/* Non-recursive destroy, like in ext3 */
while (n) {
if (n->rb_left) {
n = n->rb_left;
continue;
}
if (n->rb_right) {
n = n->rb_right;
continue;
}
p = rb_parent(n);
node = rb_entry(n, struct iface_node, node);
if (!p)
*root = RB_ROOT;
else if (p->rb_left == n)
p->rb_left = NULL;
else if (p->rb_right == n)
p->rb_right = NULL;
kfree(node);
n = p;
}
}
static int
iface_test(struct rb_root *root, const char **iface)
{
struct rb_node *n = root->rb_node;
while (n) {
const char *d = iface_data(n);
int res = ifname_compare(*iface, d);
if (res < 0)
n = n->rb_left;
else if (res > 0)
n = n->rb_right;
else {
*iface = d;
return 1;
}
}
return 0;
}
static int
iface_add(struct rb_root *root, const char **iface)
{
struct rb_node **n = &(root->rb_node), *p = NULL;
struct iface_node *d;
while (*n) {
char *ifname = iface_data(*n);
int res = ifname_compare(*iface, ifname);
p = *n;
if (res < 0)
n = &((*n)->rb_left);
else if (res > 0)
n = &((*n)->rb_right);
else {
*iface = ifname;
return 0;
}
}
d = kzalloc(sizeof(*d), GFP_ATOMIC);
if (!d)
return -ENOMEM;
strcpy(d->iface, *iface);
rb_link_node(&d->node, p, n);
rb_insert_color(&d->node, root);
*iface = d->iface;
return 0;
}
/* Type specific function prefix */
#define TYPE hash_netiface
static bool
hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b);
#define hash_netiface4_same_set hash_netiface_same_set
#define hash_netiface6_same_set hash_netiface_same_set
#define STREQ(a, b) (strcmp(a, b) == 0)
/* The type variant functions: IPv4 */
/* Member elements without timeout */
struct hash_netiface4_elem {
__be32 ip;
const char *iface;
u8 physdev;
u8 cidr;
u16 padding;
};
/* Member elements with timeout support */
struct hash_netiface4_telem {
__be32 ip;
const char *iface;
u8 physdev;
u8 cidr;
u16 padding;
unsigned long timeout;
};
static inline bool
hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
const struct hash_netiface4_elem *ip2)
{
return ip1->ip == ip2->ip &&
ip1->cidr == ip2->cidr &&
ip1->physdev == ip2->physdev &&
ip1->iface == ip2->iface;
}
static inline bool
hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem)
{
return elem->cidr == 0;
}
static inline void
hash_netiface4_data_copy(struct hash_netiface4_elem *dst,
const struct hash_netiface4_elem *src) {
dst->ip = src->ip;
dst->cidr = src->cidr;
dst->physdev = src->physdev;
dst->iface = src->iface;
}
static inline void
hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
{
elem->ip &= ip_set_netmask(cidr);
elem->cidr = cidr;
}
static inline void
hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem)
{
elem->cidr = 0;
}
static bool
hash_netiface4_data_list(struct sk_buff *skb,
const struct hash_netiface4_elem *data)
{
u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
if (flags)
NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
return 0;
nla_put_failure:
return 1;
}
static bool
hash_netiface4_data_tlist(struct sk_buff *skb,
const struct hash_netiface4_elem *data)
{
const struct hash_netiface4_telem *tdata =
(const struct hash_netiface4_telem *)data;
u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
if (flags)
NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
htonl(ip_set_timeout_get(tdata->timeout)));
return 0;
nla_put_failure:
return 1;
}
#define IP_SET_HASH_WITH_NETS
#define IP_SET_HASH_WITH_RBTREE
#define PF 4
#define HOST_MASK 32
#include "ip_set_ahash.h"
static inline void
hash_netiface4_data_next(struct ip_set_hash *h,
const struct hash_netiface4_elem *d)
{
h->next.ip = ntohl(d->ip);
}
static int
hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netiface4_elem data = {
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
};
int ret;
if (data.cidr == 0)
return -EINVAL;
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
data.ip &= ip_set_netmask(data.cidr);
#define IFACE(dir) (par->dir ? par->dir->name : NULL)
#define PHYSDEV(dir) (nf_bridge->dir ? nf_bridge->dir->name : NULL)
#define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC)
if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
#ifdef CONFIG_BRIDGE_NETFILTER
const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
if (!nf_bridge)
return -EINVAL;
data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
data.physdev = 1;
#else
data.iface = NULL;
#endif
} else
data.iface = SRCDIR ? IFACE(in) : IFACE(out);
if (!data.iface)
return -EINVAL;
ret = iface_test(&h->rbtree, &data.iface);
if (adt == IPSET_ADD) {
if (!ret) {
ret = iface_add(&h->rbtree, &data.iface);
if (ret)
return ret;
}
} else if (!ret)
return ret;
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}
static int
hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netiface4_elem data = { .cidr = HOST_MASK };
u32 ip = 0, ip_to, last;
u32 timeout = h->timeout;
char iface[IFNAMSIZ] = {};
int ret;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!tb[IPSET_ATTR_IFACE] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip);
if (ret)
return ret;
if (tb[IPSET_ATTR_CIDR]) {
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
if (!data.cidr)
return -IPSET_ERR_INVALID_CIDR;
}
if (tb[IPSET_ATTR_TIMEOUT]) {
if (!with_timeout(h->timeout))
return -IPSET_ERR_TIMEOUT;
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
data.iface = iface;
ret = iface_test(&h->rbtree, &data.iface);
if (adt == IPSET_ADD) {
if (!ret) {
ret = iface_add(&h->rbtree, &data.iface);
if (ret)
return ret;
}
} else if (!ret)
return ret;
if (tb[IPSET_ATTR_CADT_FLAGS]) {
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
if (cadt_flags & IPSET_FLAG_PHYSDEV)
data.physdev = 1;
}
if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
data.ip = htonl(ip & ip_set_hostmask(data.cidr));
ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
if (tb[IPSET_ATTR_IP_TO]) {
ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
if (ret)
return ret;
if (ip_to < ip)
swap(ip, ip_to);
if (ip + UINT_MAX == ip_to)
return -IPSET_ERR_HASH_RANGE;
} else {
ip_set_mask_from_to(ip, ip_to, data.cidr);
}
if (retried)
ip = h->next.ip;
while (!after(ip, ip_to)) {
data.ip = htonl(ip);
last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
ret = adtfn(set, &data, timeout, flags);
if (ret && !ip_set_eexist(ret, flags))
return ret;
else
ret = 0;
ip = last + 1;
}
return ret;
}
static bool
hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
{
const struct ip_set_hash *x = a->data;
const struct ip_set_hash *y = b->data;
/* Resizing changes htable_bits, so we ignore it */
return x->maxelem == y->maxelem &&
x->timeout == y->timeout;
}
/* The type variant functions: IPv6 */
struct hash_netiface6_elem {
union nf_inet_addr ip;
const char *iface;
u8 physdev;
u8 cidr;
u16 padding;
};
struct hash_netiface6_telem {
union nf_inet_addr ip;
const char *iface;
u8 physdev;
u8 cidr;
u16 padding;
unsigned long timeout;
};
static inline bool
hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
const struct hash_netiface6_elem *ip2)
{
return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
ip1->cidr == ip2->cidr &&
ip1->physdev == ip2->physdev &&
ip1->iface == ip2->iface;
}
static inline bool
hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem)
{
return elem->cidr == 0;
}
static inline void
hash_netiface6_data_copy(struct hash_netiface6_elem *dst,
const struct hash_netiface6_elem *src)
{
memcpy(dst, src, sizeof(*dst));
}
static inline void
hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
{
}
static inline void
ip6_netmask(union nf_inet_addr *ip, u8 prefix)
{
ip->ip6[0] &= ip_set_netmask6(prefix)[0];
ip->ip6[1] &= ip_set_netmask6(prefix)[1];
ip->ip6[2] &= ip_set_netmask6(prefix)[2];
ip->ip6[3] &= ip_set_netmask6(prefix)[3];
}
static inline void
hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
{
ip6_netmask(&elem->ip, cidr);
elem->cidr = cidr;
}
static bool
hash_netiface6_data_list(struct sk_buff *skb,
const struct hash_netiface6_elem *data)
{
u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
if (flags)
NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
return 0;
nla_put_failure:
return 1;
}
static bool
hash_netiface6_data_tlist(struct sk_buff *skb,
const struct hash_netiface6_elem *data)
{
const struct hash_netiface6_telem *e =
(const struct hash_netiface6_telem *)data;
u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
if (flags)
NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
htonl(ip_set_timeout_get(e->timeout)));
return 0;
nla_put_failure:
return 1;
}
#undef PF
#undef HOST_MASK
#define PF 6
#define HOST_MASK 128
#include "ip_set_ahash.h"
static inline void
hash_netiface6_data_next(struct ip_set_hash *h,
const struct hash_netiface6_elem *d)
{
}
static int
hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
const struct xt_action_param *par,
enum ipset_adt adt, const struct ip_set_adt_opt *opt)
{
struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netiface6_elem data = {
.cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
};
int ret;
if (data.cidr == 0)
return -EINVAL;
if (adt == IPSET_TEST)
data.cidr = HOST_MASK;
ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
ip6_netmask(&data.ip, data.cidr);
if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
#ifdef CONFIG_BRIDGE_NETFILTER
const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
if (!nf_bridge)
return -EINVAL;
data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
data.physdev = 1;
#else
data.iface = NULL;
#endif
} else
data.iface = SRCDIR ? IFACE(in) : IFACE(out);
if (!data.iface)
return -EINVAL;
ret = iface_test(&h->rbtree, &data.iface);
if (adt == IPSET_ADD) {
if (!ret) {
ret = iface_add(&h->rbtree, &data.iface);
if (ret)
return ret;
}
} else if (!ret)
return ret;
return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
}
static int
hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
{
struct ip_set_hash *h = set->data;
ipset_adtfn adtfn = set->variant->adt[adt];
struct hash_netiface6_elem data = { .cidr = HOST_MASK };
u32 timeout = h->timeout;
char iface[IFNAMSIZ] = {};
int ret;
if (unlikely(!tb[IPSET_ATTR_IP] ||
!tb[IPSET_ATTR_IFACE] ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
return -IPSET_ERR_PROTOCOL;
if (unlikely(tb[IPSET_ATTR_IP_TO]))
return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
if (tb[IPSET_ATTR_LINENO])
*lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
if (ret)
return ret;
if (tb[IPSET_ATTR_CIDR])
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
if (!data.cidr)
return -IPSET_ERR_INVALID_CIDR;
ip6_netmask(&data.ip, data.cidr);
if (tb[IPSET_ATTR_TIMEOUT]) {
if (!with_timeout(h->timeout))
return -IPSET_ERR_TIMEOUT;
timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
}
strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
data.iface = iface;
ret = iface_test(&h->rbtree, &data.iface);
if (adt == IPSET_ADD) {
if (!ret) {
ret = iface_add(&h->rbtree, &data.iface);
if (ret)
return ret;
}
} else if (!ret)
return ret;
if (tb[IPSET_ATTR_CADT_FLAGS]) {
u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
if (cadt_flags & IPSET_FLAG_PHYSDEV)
data.physdev = 1;
}
ret = adtfn(set, &data, timeout, flags);
return ip_set_eexist(ret, flags) ? 0 : ret;
}
/* Create hash:ip type of sets */
static int
hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
{
struct ip_set_hash *h;
u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
u8 hbits;
if (!(set->family == AF_INET || set->family == AF_INET6))
return -IPSET_ERR_INVALID_FAMILY;
if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) ||
!ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
return -IPSET_ERR_PROTOCOL;
if (tb[IPSET_ATTR_HASHSIZE]) {
hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
if (hashsize < IPSET_MIMINAL_HASHSIZE)
hashsize = IPSET_MIMINAL_HASHSIZE;
}
if (tb[IPSET_ATTR_MAXELEM])
maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
h = kzalloc(sizeof(*h)
+ sizeof(struct ip_set_hash_nets)
* (set->family == AF_INET ? 32 : 128), GFP_KERNEL);
if (!h)
return -ENOMEM;
h->maxelem = maxelem;
get_random_bytes(&h->initval, sizeof(h->initval));
h->timeout = IPSET_NO_TIMEOUT;
hbits = htable_bits(hashsize);
h->table = ip_set_alloc(
sizeof(struct htable)
+ jhash_size(hbits) * sizeof(struct hbucket));
if (!h->table) {
kfree(h);
return -ENOMEM;
}
h->table->htable_bits = hbits;
h->rbtree = RB_ROOT;
set->data = h;
if (tb[IPSET_ATTR_TIMEOUT]) {
h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
set->variant = set->family == AF_INET
? &hash_netiface4_tvariant : &hash_netiface6_tvariant;
if (set->family == AF_INET)
hash_netiface4_gc_init(set);
else
hash_netiface6_gc_init(set);
} else {
set->variant = set->family == AF_INET
? &hash_netiface4_variant : &hash_netiface6_variant;
}
pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
set->name, jhash_size(h->table->htable_bits),
h->table->htable_bits, h->maxelem, set->data, h->table);
return 0;
}
static struct ip_set_type hash_netiface_type __read_mostly = {
.name = "hash:net,iface",
.protocol = IPSET_PROTOCOL,
.features = IPSET_TYPE_IP | IPSET_TYPE_IFACE,
.dimension = IPSET_DIM_TWO,
.family = AF_UNSPEC,
.revision_min = 0,
.create = hash_netiface_create,
.create_policy = {
[IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
[IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
[IPSET_ATTR_PROBES] = { .type = NLA_U8 },
[IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
[IPSET_ATTR_PROTO] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
},
.adt_policy = {
[IPSET_ATTR_IP] = { .type = NLA_NESTED },
[IPSET_ATTR_IP_TO] = { .type = NLA_NESTED },
[IPSET_ATTR_IFACE] = { .type = NLA_NUL_STRING,
.len = IPSET_MAXNAMELEN - 1 },
[IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
[IPSET_ATTR_CIDR] = { .type = NLA_U8 },
[IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
[IPSET_ATTR_LINENO] = { .type = NLA_U32 },
},
.me = THIS_MODULE,
};
static int __init
hash_netiface_init(void)
{
return ip_set_type_register(&hash_netiface_type);
}
static void __exit
hash_netiface_fini(void)
{
ip_set_type_unregister(&hash_netiface_type);
}
module_init(hash_netiface_init);
module_exit(hash_netiface_fini);

View File

@@ -199,7 +199,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
if (tb[IPSET_ATTR_CIDR]) {
data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
if (!data.cidr)
return -IPSET_ERR_INVALID_CIDR;
return -IPSET_ERR_INVALID_CIDR;
}
if (tb[IPSET_ATTR_PORT])

View File

@@ -78,7 +78,7 @@ ip_set_timeout_set(u32 timeout)
static inline u32
ip_set_timeout_get(unsigned long timeout)
{
return timeout == IPSET_ELEM_PERMANENT ? 0 :
return timeout == IPSET_ELEM_PERMANENT ? 0 :
jiffies_to_msecs(timeout - jiffies)/1000;
}

View File

@@ -1,12 +1,13 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <assert.h> /* assert */
#include <arpa/inet.h> /* ntoh* */
#include <net/ethernet.h> /* ETH_ALEN */
#include <net/if.h> /* IFNAMSIZ */
#include <sys/socket.h> /* AF_ */
#include <stdlib.h> /* malloc, free */
#include <string.h> /* memset */
@@ -17,7 +18,7 @@
#include <libipset/utils.h> /* inXcpy */
#include <libipset/data.h> /* prototypes */
/* Internal data structure to hold
/* Internal data structure to hold
* a) input data entered by the user or
* b) data received from kernel
*
@@ -72,6 +73,7 @@ struct ipset_data {
char ether[ETH_ALEN];
char name[IPSET_MAXNAMELEN];
char nameref[IPSET_MAXNAMELEN];
char iface[IFNAMSIZ];
} adt;
};
};
@@ -172,7 +174,7 @@ ipset_data_ignored(struct ipset_data *data, enum ipset_opt opt)
{
bool ignored;
assert(data);
ignored = data->ignored & IPSET_FLAG(opt);
data->ignored |= IPSET_FLAG(opt);
@@ -301,6 +303,9 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
case IPSET_OPT_PROTO:
data->adt.proto = *(const uint8_t *) value;
break;
case IPSET_OPT_IFACE:
ipset_strlcpy(data->adt.iface, value, IFNAMSIZ);
break;
/* Swap/rename */
case IPSET_OPT_SETNAME2:
ipset_strlcpy(data->setname2, value, IPSET_MAXNAMELEN);
@@ -312,6 +317,9 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
case IPSET_OPT_BEFORE:
cadt_flag_type_attr(data, opt, IPSET_FLAG_BEFORE);
break;
case IPSET_OPT_PHYSDEV:
cadt_flag_type_attr(data, opt, IPSET_FLAG_PHYSDEV);
break;
case IPSET_OPT_FLAGS:
data->flags = *(const uint32_t *)value;
break;
@@ -321,7 +329,7 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
default:
return -1;
};
ipset_data_flags_set(data, IPSET_FLAG(opt));
return 0;
}
@@ -340,7 +348,7 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
{
assert(data);
assert(opt != IPSET_OPT_NONE);
if (!(opt == IPSET_OPT_TYPENAME || ipset_data_test(data, opt)))
return NULL;
@@ -413,6 +421,8 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
return &data->adt.cidr2;
case IPSET_OPT_PROTO:
return &data->adt.proto;
case IPSET_OPT_IFACE:
return &data->adt.iface;
/* Swap/rename */
case IPSET_OPT_SETNAME2:
return data->setname2;
@@ -422,6 +432,7 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
return &data->flags;
case IPSET_OPT_CADT_FLAGS:
case IPSET_OPT_BEFORE:
case IPSET_OPT_PHYSDEV:
return &data->cadt_flags;
default:
return NULL;
@@ -472,8 +483,9 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
return sizeof(uint8_t);
case IPSET_OPT_ETHER:
return ETH_ALEN;
/* Flags counted once */
/* Flags doesn't counted once :-( */
case IPSET_OPT_BEFORE:
case IPSET_OPT_PHYSDEV:
return sizeof(uint32_t);
default:
return 0;
@@ -521,8 +533,8 @@ uint8_t
ipset_data_cidr(const struct ipset_data *data)
{
assert(data);
return ipset_data_test(data, IPSET_OPT_CIDR) ? data->cidr :
data->family == AF_INET ? 32 :
return ipset_data_test(data, IPSET_OPT_CIDR) ? data->cidr :
data->family == AF_INET ? 32 :
data->family == AF_INET6 ? 128 : 0;
}

View File

@@ -1,12 +1,12 @@
/* Copyright 2011 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <arpa/inet.h> /* inet_ntop */
#include <libmnl/libmnl.h> /* libmnl backend */
#include <libmnl/libmnl.h> /* libmnl backend */
struct ipset_attrname {
const char *name;
@@ -63,6 +63,7 @@ static const struct ipset_attrname adtattr2name[] = {
[IPSET_ATTR_IP2] = { .name = "IP2" },
[IPSET_ATTR_CIDR2] = { .name = "CIDR2" },
[IPSET_ATTR_IP2_TO] = { .name = "IP2_TO" },
[IPSET_ATTR_IFACE] = { .name = "IFACE" },
};
static void
@@ -73,23 +74,24 @@ debug_cadt_attrs(int max, const struct ipset_attr_policy *policy,
uint32_t v;
int i;
fprintf(stderr,"\t\t%s attributes:\n", policy == create_attrs ? "CREATE" : "ADT");
fprintf(stderr, "\t\t%s attributes:\n",
policy == create_attrs ? "CREATE" : "ADT");
for (i = IPSET_ATTR_UNSPEC + 1; i <= max; i++) {
if (!nla[i])
continue;
switch (policy[i].type) {
case MNL_TYPE_U8:
v = * (uint8_t *) mnl_attr_get_payload(nla[i]);
v = *(uint8_t *) mnl_attr_get_payload(nla[i]);
fprintf(stderr, "\t\t%s: %u\n",
attr2name[i].name, v);
break;
case MNL_TYPE_U16:
v = * (uint16_t *) mnl_attr_get_payload(nla[i]);
v = *(uint16_t *) mnl_attr_get_payload(nla[i]);
fprintf(stderr, "\t\t%s: %u\n",
attr2name[i].name, ntohs(v));
break;
case MNL_TYPE_U32:
v = * (uint32_t *) mnl_attr_get_payload(nla[i]);
v = *(uint32_t *) mnl_attr_get_payload(nla[i]);
fprintf(stderr, "\t\t%s: %u\n",
attr2name[i].name, ntohl(v));
break;
@@ -103,18 +105,23 @@ debug_cadt_attrs(int max, const struct ipset_attr_policy *policy,
char addr[INET6_ADDRSTRLEN];
void *d;
if (mnl_attr_parse_nested(nla[i], ipaddr_attr_cb, ipattr) < 0) {
fprintf(stderr, "\t\tIPADDR: cannot validate and parse attributes\n");
if (mnl_attr_parse_nested(nla[i], ipaddr_attr_cb,
ipattr) < 0) {
fprintf(stderr,
"\t\tIPADDR: cannot validate "
"and parse attributes\n");
continue;
}
if (ipattr[IPSET_ATTR_IPADDR_IPV4]) {
d = mnl_attr_get_payload(ipattr[IPSET_ATTR_IPADDR_IPV4]);
d = mnl_attr_get_payload(
ipattr[IPSET_ATTR_IPADDR_IPV4]);
inet_ntop(AF_INET, d, addr, INET6_ADDRSTRLEN);
fprintf(stderr, "\t\t%s: %s\n",
attr2name[i].name, addr);
} else if (ipattr[IPSET_ATTR_IPADDR_IPV6]) {
d = mnl_attr_get_payload(ipattr[IPSET_ATTR_IPADDR_IPV6]);
d = mnl_attr_get_payload(
ipattr[IPSET_ATTR_IPADDR_IPV6]);
inet_ntop(AF_INET6, d, addr, INET6_ADDRSTRLEN);
fprintf(stderr, "\t\t%s: %s\n",
@@ -137,23 +144,23 @@ debug_cmd_attrs(int cmd, struct nlattr *nla[])
uint32_t v;
int i;
fprintf(stderr,"\tCommand attributes:\n");
fprintf(stderr, "\tCommand attributes:\n");
for (i = IPSET_ATTR_UNSPEC + 1; i <= IPSET_ATTR_CMD_MAX; i++) {
if (!nla[i])
continue;
switch (cmd_attrs[i].type) {
case MNL_TYPE_U8:
v = * (uint8_t *) mnl_attr_get_payload(nla[i]);
v = *(uint8_t *) mnl_attr_get_payload(nla[i]);
fprintf(stderr, "\t%s: %u\n",
cmdattr2name[i].name, v);
break;
case MNL_TYPE_U16:
v = * (uint16_t *) mnl_attr_get_payload(nla[i]);
v = *(uint16_t *) mnl_attr_get_payload(nla[i]);
fprintf(stderr, "\t%s: %u\n",
cmdattr2name[i].name, ntohs(v));
break;
case MNL_TYPE_U32:
v = * (uint32_t *) mnl_attr_get_payload(nla[i]);
v = *(uint32_t *) mnl_attr_get_payload(nla[i]);
fprintf(stderr, "\t%s: %u\n",
cmdattr2name[i].name, ntohl(v));
break;
@@ -168,8 +175,11 @@ debug_cmd_attrs(int cmd, struct nlattr *nla[])
case IPSET_CMD_ADD:
case IPSET_CMD_DEL:
case IPSET_CMD_TEST:
if (mnl_attr_parse_nested(nla[i], adt_attr_cb, adt) < 0) {
fprintf(stderr, "\tADT: cannot validate and parse attributes\n");
if (mnl_attr_parse_nested(nla[i],
adt_attr_cb, adt) < 0) {
fprintf(stderr,
"\tADT: cannot validate "
"and parse attributes\n");
continue;
}
debug_cadt_attrs(IPSET_ATTR_ADT_MAX,
@@ -178,8 +188,12 @@ debug_cmd_attrs(int cmd, struct nlattr *nla[])
adt);
break;
default:
if (mnl_attr_parse_nested(nla[i], create_attr_cb, cattr) < 0) {
fprintf(stderr, "\tCREATE: cannot validate and parse attributes\n");
if (mnl_attr_parse_nested(nla[i],
create_attr_cb,
cattr) < 0) {
fprintf(stderr,
"\tCREATE: cannot validate "
"and parse attributes\n");
continue;
}
debug_cadt_attrs(IPSET_ATTR_CREATE_MAX,
@@ -191,15 +205,18 @@ debug_cmd_attrs(int cmd, struct nlattr *nla[])
struct nlattr *tb;
mnl_attr_for_each_nested(tb, nla[i]) {
memset(adt, 0, sizeof(adt));
if (mnl_attr_parse_nested(tb, adt_attr_cb, adt) < 0) {
fprintf(stderr, "\tADT: cannot validate and parse attributes\n");
if (mnl_attr_parse_nested(tb,
adt_attr_cb, adt) < 0) {
fprintf(stderr,
"\tADT: cannot validate "
"and parse attributes\n");
continue;
}
debug_cadt_attrs(IPSET_ATTR_ADT_MAX,
adt_attrs,
adtattr2name,
adt);
}
}
}
break;
default:
@@ -226,8 +243,9 @@ ipset_debug_msg(const char *dir, void *buffer, int len)
"\tlen %d\n"
"\tseq %u\n",
dir,
nlh->nlmsg_type == NLMSG_NOOP ? "NOOP" :
nlh->nlmsg_type == NLMSG_DONE ? "DONE" : "OVERRUN",
nlh->nlmsg_type == NLMSG_NOOP ? "NOOP" :
nlh->nlmsg_type == NLMSG_DONE ? "DONE" :
"OVERRUN",
len, nlh->nlmsg_seq);
goto next_msg;
case NLMSG_ERROR: {
@@ -256,8 +274,10 @@ ipset_debug_msg(const char *dir, void *buffer, int len)
if (cmd <= IPSET_CMD_NONE || cmd >= IPSET_CMD_MAX)
goto next_msg;
memset(nla, 0, sizeof(nla));
if (mnl_attr_parse(nlh, nfmsglen, cmd_attr_cb, nla) < MNL_CB_STOP) {
fprintf(stderr, "\tcannot validate and parse attributes\n");
if (mnl_attr_parse(nlh, nfmsglen,
cmd_attr_cb, nla) < MNL_CB_STOP) {
fprintf(stderr, "\tcannot validate "
"and parse attributes\n");
goto next_msg;
}
debug_cmd_attrs(cmd, nla);

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <libipset/utils.h> /* STRNEQ */
@@ -49,19 +49,20 @@ static const struct icmp_names icmp_typecodes[] = {
{ "address-mask-reply", 18, 0 },
};
const char * id_to_icmp(uint8_t id)
const char *id_to_icmp(uint8_t id)
{
return id < ARRAY_SIZE(icmp_typecodes) ? icmp_typecodes[id].name : NULL;
}
const char * icmp_to_name(uint8_t type, uint8_t code)
const char *icmp_to_name(uint8_t type, uint8_t code)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(icmp_typecodes); i++)
if (icmp_typecodes[i].type == type && icmp_typecodes[i].code == code)
if (icmp_typecodes[i].type == type &&
icmp_typecodes[i].code == code)
return icmp_typecodes[i].name;
return NULL;
}
@@ -71,9 +72,10 @@ int name_to_icmp(const char *str, uint16_t *typecode)
for (i = 0; i < ARRAY_SIZE(icmp_typecodes); i++)
if (STRNCASEQ(icmp_typecodes[i].name, str, strlen(str))) {
*typecode = (icmp_typecodes[i].type << 8) | icmp_typecodes[i].code;
*typecode = (icmp_typecodes[i].type << 8) |
icmp_typecodes[i].code;
return 0;
}
return -1;
}

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <libipset/utils.h> /* STRNEQ */
@@ -36,19 +36,21 @@ static const struct icmpv6_names icmpv6_typecodes[] = {
{ "redirect", 137, 0 },
};
const char * id_to_icmpv6(uint8_t id)
const char *id_to_icmpv6(uint8_t id)
{
return id < ARRAY_SIZE(icmpv6_typecodes) ? icmpv6_typecodes[id].name : NULL;
return id < ARRAY_SIZE(icmpv6_typecodes) ?
icmpv6_typecodes[id].name : NULL;
}
const char * icmpv6_to_name(uint8_t type, uint8_t code)
const char *icmpv6_to_name(uint8_t type, uint8_t code)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(icmpv6_typecodes); i++)
if (icmpv6_typecodes[i].type == type && icmpv6_typecodes[i].code == code)
if (icmpv6_typecodes[i].type == type &&
icmpv6_typecodes[i].code == code)
return icmpv6_typecodes[i].name;
return NULL;
}
@@ -58,9 +60,10 @@ int name_to_icmpv6(const char *str, uint16_t *typecode)
for (i = 0; i < ARRAY_SIZE(icmpv6_typecodes); i++)
if (STRNCASEQ(icmpv6_typecodes[i].name, str, strlen(str))) {
*typecode = (icmpv6_typecodes[i].type << 8) | icmpv6_typecodes[i].code;
*typecode = (icmpv6_typecodes[i].type << 8) |
icmpv6_typecodes[i].code;
return 0;
}
return -1;
}

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <assert.h> /* assert */
@@ -38,7 +38,8 @@ struct ipset_handle {
/* Netlink flags of the commands */
static const uint16_t cmdflags[] = {
[IPSET_CMD_CREATE-1] = NLM_F_REQUEST|NLM_F_ACK|NLM_F_CREATE|NLM_F_EXCL,
[IPSET_CMD_CREATE-1] = NLM_F_REQUEST|NLM_F_ACK|
NLM_F_CREATE|NLM_F_EXCL,
[IPSET_CMD_DESTROY-1] = NLM_F_REQUEST|NLM_F_ACK,
[IPSET_CMD_FLUSH-1] = NLM_F_REQUEST|NLM_F_ACK,
[IPSET_CMD_RENAME-1] = NLM_F_REQUEST|NLM_F_ACK,
@@ -209,28 +210,28 @@ static int ipset_mnl_getid(struct ipset_handle *h, bool modprobe)
static struct ipset_handle *
ipset_mnl_init(mnl_cb_t *cb_ctl, void *data)
{
{
struct ipset_handle *handle;
assert(cb_ctl);
assert(data);
handle = calloc(1, sizeof(*handle));
if (!handle)
return NULL;
handle->h = mnl_socket_open(NETLINK_GENERIC);
if (!handle->h)
goto free_handle;
if (mnl_socket_bind(handle->h, 0, MNL_SOCKET_AUTOPID) < 0)
goto close_nl;
handle->portid = mnl_socket_get_portid(handle->h);
handle->cb_ctl = cb_ctl;
handle->data = data;
handle->seq = time(NULL);
if (ipset_mnl_getid(handle, false) < 0)
goto close_nl;
return handle;
@@ -240,7 +241,7 @@ close_nl:
free_handle:
free(handle);
return NULL;
return NULL;
}
static int

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <assert.h> /* assert */
@@ -12,6 +12,7 @@
#include <sys/types.h> /* getaddrinfo */
#include <sys/socket.h> /* getaddrinfo, AF_ */
#include <net/ethernet.h> /* ETH_ALEN */
#include <net/if.h> /* IFNAMSIZ */
#include <netinet/in.h> /* IPPROTO_ */
#include <libipset/debug.h> /* D() */
@@ -43,21 +44,23 @@ static char *
ipset_strchr(const char *str, const char *sep)
{
char *match;
assert(str);
assert(sep);
for (; *sep != '\0'; sep++)
if ((match = strchr(str, sep[0])) != NULL
&& str[0] != sep[0]
&& str[strlen(str)-1] != sep[0])
for (; *sep != '\0'; sep++) {
match = strchr(str, sep[0]);
if (match != NULL &&
str[0] != sep[0] &&
str[strlen(str)-1] != sep[0])
return match;
}
return NULL;
}
/*
* Parser functions, shamelessly taken from iptables.c, ip6tables.c
/*
* Parser functions, shamelessly taken from iptables.c, ip6tables.c
* and parser.c from libnetfilter_conntrack.
*/
@@ -66,7 +69,7 @@ ipset_strchr(const char *str, const char *sep)
*/
static int
string_to_number_ll(struct ipset_session *session,
const char *str,
const char *str,
unsigned long long min,
unsigned long long max,
unsigned long long *ret)
@@ -113,7 +116,7 @@ string_to_cidr(struct ipset_session *session,
const char *str, uint8_t min, uint8_t max, uint8_t *ret)
{
int err = string_to_u8(session, str, ret);
if (!err && (*ret < min || *ret > max))
return syntax_err("'%s' is out of range %u-%u",
str, min, max);
@@ -164,7 +167,7 @@ ipset_parse_ether(struct ipset_session *session,
{
unsigned int i = 0;
unsigned char ether[ETH_ALEN];
assert(session);
assert(opt == IPSET_OPT_ETHER);
assert(str);
@@ -178,9 +181,9 @@ ipset_parse_ether(struct ipset_session *session,
number = strtol(str + i * 3, &end, 16);
if (end == str + i * 3 + 2
&& (*end == ':' || *end == '\0')
&& number >= 0 && number <= 255)
if (end == str + i * 3 + 2 &&
(*end == ':' || *end == '\0') &&
number >= 0 && number <= 255)
ether[i] = number;
else
goto error;
@@ -198,13 +201,13 @@ static int
parse_portname(struct ipset_session *session, const char *str,
uint16_t *port, const char *proto)
{
struct servent *service;
struct servent *service = getservbyname(str, proto);
if ((service = getservbyname(str, proto)) != NULL) {
if (service != NULL) {
*port = ntohs((uint16_t) service->s_port);
return 0;
}
return syntax_err("cannot parse '%s' as a %s port", str, proto);
}
@@ -232,8 +235,8 @@ ipset_parse_port(struct ipset_session *session,
assert(opt == IPSET_OPT_PORT || opt == IPSET_OPT_PORT_TO);
assert(str);
if ((err = string_to_u16(session, str, &port)) == 0
|| (err = parse_portname(session, str, &port, proto)) == 0)
if ((err = string_to_u16(session, str, &port)) == 0 ||
(err = parse_portname(session, str, &port, proto)) == 0)
err = ipset_session_data_set(session, opt, &port);
if (!err)
@@ -351,7 +354,7 @@ ipset_parse_proto(struct ipset_session *session,
assert(session);
assert(opt == IPSET_OPT_PROTO);
assert(str);
protoent = getprotobyname(strcasecmp(str, "icmpv6") == 0
? "ipv6-icmp" : str);
if (protoent == NULL)
@@ -360,7 +363,7 @@ ipset_parse_proto(struct ipset_session *session,
proto = protoent->p_proto;
if (!proto)
return syntax_err("Unsupported protocol '%s'", str);
return ipset_session_data_set(session, opt, &proto);
}
@@ -374,7 +377,7 @@ parse_icmp_typecode(struct ipset_session *session,
uint8_t type, code;
char *a, *saved, *tmp;
int err;
saved = tmp = strdup(str);
if (tmp == NULL)
return ipset_err(session,
@@ -384,13 +387,14 @@ parse_icmp_typecode(struct ipset_session *session,
if (a == NULL) {
free(saved);
return ipset_err(session,
"Cannot parse %s as an %s type/code.", str, family);
"Cannot parse %s as an %s type/code.",
str, family);
}
*a++ = '\0';
if ((err = string_to_u8(session, a, &type)) != 0
|| (err = string_to_u8(session, tmp, &code)) != 0)
goto error;
if ((err = string_to_u8(session, a, &type)) != 0 ||
(err = string_to_u8(session, tmp, &code)) != 0)
goto error;
typecode = (type << 8) | code;
err = ipset_session_data_set(session, opt, &typecode);
@@ -496,7 +500,7 @@ ipset_parse_proto_port(struct ipset_session *session,
err = ipset_parse_proto(session, IPSET_OPT_PROTO, tmp);
if (err)
goto error;
p = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO);
switch (p) {
case IPPROTO_TCP:
@@ -508,28 +512,31 @@ ipset_parse_proto_port(struct ipset_session *session,
goto parse_port;
case IPPROTO_ICMP:
if (family != AF_INET) {
syntax_err("Protocol ICMP can be used with family INET only");
syntax_err("Protocol ICMP can be used "
"with family INET only");
goto error;
}
err = ipset_parse_icmp(session, opt, a);
break;
case IPPROTO_ICMPV6:
if (family != AF_INET6) {
syntax_err("Protocol ICMPv6 can be used with family INET6 only");
syntax_err("Protocol ICMPv6 can be used "
"with family INET6 only");
goto error;
}
err = ipset_parse_icmpv6(session, opt, a);
break;
default:
if (!STREQ(a, "0")) {
syntax_err("Protocol %s can be used with pseudo port value 0 only.");
syntax_err("Protocol %s can be used "
"with pseudo port value 0 only.");
goto error;
}
ipset_data_flags_set(data, IPSET_FLAG(opt));
}
goto error;
} else {
proto = "TCP";
proto = "TCP";
err = ipset_data_set(data, IPSET_OPT_PROTO, &p);
if (err)
goto error;
@@ -559,7 +566,7 @@ ipset_parse_family(struct ipset_session *session,
{
struct ipset_data *data;
uint8_t family;
assert(session);
assert(opt == IPSET_OPT_FAMILY);
assert(str);
@@ -577,7 +584,7 @@ ipset_parse_family(struct ipset_session *session,
family = AF_UNSPEC;
else
return syntax_err("unknown INET family %s", str);
return ipset_data_set(data, opt, &family);
}
@@ -585,27 +592,27 @@ ipset_parse_family(struct ipset_session *session,
* Parse IPv4/IPv6 addresses, networks and ranges.
* We resolve hostnames but just the first IP address is used.
*/
static struct addrinfo *
call_getaddrinfo(struct ipset_session *session, const char *str,
uint8_t family)
{
struct addrinfo hints;
struct addrinfo *res;
struct addrinfo *res;
int err;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = family;
hints.ai_socktype = SOCK_RAW;
hints.ai_protocol = 0;
hints.ai_next = NULL;
hints.ai_family = family;
hints.ai_socktype = SOCK_RAW;
hints.ai_protocol = 0;
hints.ai_next = NULL;
if ((err = getaddrinfo(str, NULL, &hints, &res)) != 0) {
syntax_err("cannot resolve '%s' to an %s address: %s",
str, family == AF_INET6 ? "IPv6" : "IPv4",
gai_strerror(err));
return NULL;
if ((err = getaddrinfo(str, NULL, &hints, &res)) != 0) {
syntax_err("cannot resolve '%s' to an %s address: %s",
str, family == AF_INET6 ? "IPv6" : "IPv4",
gai_strerror(err));
return NULL;
} else
return res;
}
@@ -617,10 +624,10 @@ get_addrinfo(struct ipset_session *session,
struct addrinfo **info,
uint8_t family)
{
struct addrinfo *i;
struct addrinfo *i;
size_t addrlen = family == AF_INET ? sizeof(struct sockaddr_in)
: sizeof(struct sockaddr_in6);
int found, err = 0;
int found, err = 0;
if ((*info = call_getaddrinfo(session, str, family)) == NULL) {
syntax_err("cannot parse %s: resolving to %s address failed",
@@ -633,13 +640,21 @@ get_addrinfo(struct ipset_session *session,
continue;
if (found == 0) {
if (family == AF_INET) {
/* Workaround: direct cast increases required alignment on Sparc */
const struct sockaddr_in *saddr = (void *)i->ai_addr;
err = ipset_session_data_set(session, opt, &saddr->sin_addr);
/* Workaround: direct cast increases
* required alignment on Sparc
*/
const struct sockaddr_in *saddr =
(void *)i->ai_addr;
err = ipset_session_data_set(session,
opt, &saddr->sin_addr);
} else {
/* Workaround: direct cast increases required alignment on Sparc */
const struct sockaddr_in6 *saddr = (void *)i->ai_addr;
err = ipset_session_data_set(session, opt, &saddr->sin6_addr);
/* Workaround: direct cast increases
* required alignment on Sparc
*/
const struct sockaddr_in6 *saddr =
(void *)i->ai_addr;
err = ipset_session_data_set(session,
opt, &saddr->sin6_addr);
}
} else if (found == 1) {
ipset_warn(session,
@@ -662,12 +677,12 @@ parse_ipaddr(struct ipset_session *session,
enum ipset_opt opt, const char *str,
uint8_t family)
{
uint8_t m = family == AF_INET ? 32 : 128;
int aerr = EINVAL, err = 0, range = 0;
char *saved = strdup(str);
char *a, *tmp = saved;
struct addrinfo *info;
enum ipset_opt copt, opt2;
uint8_t m = family == AF_INET ? 32 : 128;
int aerr = EINVAL, err = 0, range = 0;
char *saved = strdup(str);
char *a, *tmp = saved;
struct addrinfo *info;
enum ipset_opt copt, opt2;
if (opt == IPSET_OPT_IP) {
copt = IPSET_OPT_CIDR;
@@ -685,8 +700,8 @@ parse_ipaddr(struct ipset_session *session,
/* IP/mask */
*a++ = '\0';
if ((err = string_to_cidr(session, a, 0, m, &m)) != 0
|| (err = ipset_session_data_set(session, copt, &m)) != 0)
if ((err = string_to_cidr(session, a, 0, m, &m)) != 0 ||
(err = ipset_session_data_set(session, copt, &m)) != 0)
goto out;
} else if ((a = range_separator(tmp)) != NULL) {
/* IP-IP */
@@ -694,8 +709,8 @@ parse_ipaddr(struct ipset_session *session,
D("range %s", a);
range++;
}
if ((aerr = get_addrinfo(session, opt, tmp, &info, family)) != 0
|| !range)
if ((aerr = get_addrinfo(session, opt, tmp, &info, family)) != 0 ||
!range)
goto out;
freeaddrinfo(info);
aerr = get_addrinfo(session, opt2, a, &info, family);
@@ -708,7 +723,7 @@ out:
err = -1;
free(saved);
return err;
}
}
enum ipaddr_type {
IPADDR_ANY,
@@ -721,7 +736,7 @@ static inline bool
cidr_hostaddr(const char *str, uint8_t family)
{
char *a = cidr_separator(str);
return family == AF_INET ? STREQ(a, "/32") : STREQ(a, "/128");
}
@@ -739,10 +754,10 @@ parse_ip(struct ipset_session *session,
switch (addrtype) {
case IPADDR_PLAIN:
if (range_separator(str)
|| (cidr_separator(str) && !cidr_hostaddr(str, family)))
return syntax_err("plain IP address must be supplied: %s",
str);
if (range_separator(str) ||
(cidr_separator(str) && !cidr_hostaddr(str, family)))
return syntax_err("plain IP address must be supplied: "
"%s", str);
break;
case IPADDR_NET:
if (!cidr_separator(str) || range_separator(str))
@@ -795,7 +810,7 @@ ipset_parse_ip(struct ipset_session *session,
* @opt: option kind of the data
* @str: string to parse
*
* Parse string as an IPv4|IPv6 address or hostname. If family
* Parse string as an IPv4|IPv6 address or hostname. If family
* is not set yet in the data blob, INET is assumed.
* The value is stored in the data blob of the session.
*
@@ -806,9 +821,9 @@ ipset_parse_single_ip(struct ipset_session *session,
enum ipset_opt opt, const char *str)
{
assert(session);
assert(opt == IPSET_OPT_IP
|| opt == IPSET_OPT_IP_TO
|| opt == IPSET_OPT_IP2);
assert(opt == IPSET_OPT_IP ||
opt == IPSET_OPT_IP_TO ||
opt == IPSET_OPT_IP2);
assert(str);
return parse_ip(session, opt, str, IPADDR_PLAIN);
@@ -820,7 +835,7 @@ ipset_parse_single_ip(struct ipset_session *session,
* @opt: option kind of the data
* @str: string to parse
*
* Parse string as an IPv4|IPv6 address/cidr pattern. If family
* Parse string as an IPv4|IPv6 address/cidr pattern. If family
* is not set yet in the data blob, INET is assumed.
* The value is stored in the data blob of the session.
*
@@ -882,8 +897,8 @@ ipset_parse_netrange(struct ipset_session *session,
assert(str);
if (!(range_separator(str) || cidr_separator(str)))
return syntax_err("IP/cidr or IP-IP range must be specified: %s",
str);
return syntax_err("IP/cidr or IP-IP range must be specified: "
"%s", str);
return parse_ip(session, opt, str, IPADDR_ANY);
}
@@ -909,8 +924,8 @@ ipset_parse_iprange(struct ipset_session *session,
assert(str);
if (cidr_separator(str))
return syntax_err("IP address or IP-IP range must be specified: %s",
str);
return syntax_err("IP address or IP-IP range must be "
"specified: %s", str);
return parse_ip(session, opt, str, IPADDR_ANY);
}
@@ -966,15 +981,15 @@ ipset_parse_ip4_single6(struct ipset_session *session,
assert(session);
assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
assert(str);
data = ipset_session_data(session);
family = ipset_data_family(data);
if (family == AF_UNSPEC) {
family = AF_INET;
ipset_data_set(data, IPSET_OPT_FAMILY, &family);
}
return family == AF_INET ? ipset_parse_ip(session, opt, str)
: ipset_parse_single_ip(session, opt, str);
@@ -1006,15 +1021,15 @@ ipset_parse_ip4_net6(struct ipset_session *session,
assert(session);
assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
assert(str);
data = ipset_session_data(session);
family = ipset_data_family(data);
if (family == AF_UNSPEC) {
family = AF_INET;
ipset_data_set(data, IPSET_OPT_FAMILY, &family);
}
return family == AF_INET ? parse_ip(session, opt, str, IPADDR_ANY)
: ipset_parse_ipnet(session, opt, str);
@@ -1049,8 +1064,8 @@ ipset_parse_iptimeout(struct ipset_session *session,
if (ipset_data_flags_test(ipset_session_data(session),
IPSET_FLAG(IPSET_OPT_TIMEOUT)))
return syntax_err("mixed syntax, timeout already specified");
tmp = saved = strdup(str);
tmp = saved = strdup(str);
if (saved == NULL)
return ipset_err(session,
"Cannot allocate memory to duplicate %s.",
@@ -1072,12 +1087,12 @@ ipset_parse_iptimeout(struct ipset_session *session,
#define check_setname(str, saved) \
do { \
if (strlen(str) > IPSET_MAXNAMELEN - 1) { \
if (saved != NULL) \
free(saved); \
return syntax_err("setname '%s' is longer than %u characters", \
str, IPSET_MAXNAMELEN - 1); \
} \
if (strlen(str) > IPSET_MAXNAMELEN - 1) { \
if (saved != NULL) \
free(saved); \
return syntax_err("setname '%s' is longer than %u characters",\
str, IPSET_MAXNAMELEN - 1); \
} \
} while (0)
@@ -1112,7 +1127,7 @@ ipset_parse_name_compat(struct ipset_session *session,
if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_NAMEREF)))
syntax_err("mixed syntax, before|after option already used");
tmp = saved = strdup(str);
tmp = saved = strdup(str);
if (saved == NULL)
return ipset_err(session,
"Cannot allocate memory to duplicate %s.",
@@ -1122,8 +1137,8 @@ ipset_parse_name_compat(struct ipset_session *session,
*a++ = '\0';
if ((b = elem_separator(a)) != NULL)
*b++ = '\0';
if (b == NULL
|| !(STREQ(a, "before") || STREQ(a, "after"))) {
if (b == NULL ||
!(STREQ(a, "before") || STREQ(a, "after"))) {
err = ipset_err(session, "you must specify elements "
"as setname%s[before|after]%ssetname",
sep, sep);
@@ -1164,9 +1179,9 @@ ipset_parse_setname(struct ipset_session *session,
enum ipset_opt opt, const char *str)
{
assert(session);
assert(opt == IPSET_SETNAME
|| opt == IPSET_OPT_NAME
|| opt == IPSET_OPT_SETNAME2);
assert(opt == IPSET_SETNAME ||
opt == IPSET_OPT_NAME ||
opt == IPSET_OPT_SETNAME2);
assert(str);
check_setname(str, NULL);
@@ -1252,13 +1267,13 @@ ipset_parse_uint32(struct ipset_session *session,
{
uint32_t value;
int err;
assert(session);
assert(str);
if ((err = string_to_u32(session, str, &value)) == 0)
return ipset_session_data_set(session, opt, &value);
return err;
}
@@ -1279,7 +1294,7 @@ ipset_parse_uint8(struct ipset_session *session,
{
uint8_t value;
int err;
assert(session);
assert(str);
@@ -1308,7 +1323,7 @@ ipset_parse_netmask(struct ipset_session *session,
uint8_t family, cidr;
struct ipset_data *data;
int err = 0;
assert(session);
assert(opt == IPSET_OPT_NETMASK);
assert(str);
@@ -1321,7 +1336,7 @@ ipset_parse_netmask(struct ipset_session *session,
}
err = string_to_cidr(session, str,
family == AF_INET ? 1 : 4,
family == AF_INET ? 1 : 4,
family == AF_INET ? 31 : 124,
&cidr);
@@ -1350,7 +1365,7 @@ ipset_parse_flag(struct ipset_session *session,
enum ipset_opt opt, const char *str UNUSED)
{
assert(session);
return ipset_session_data_set(session, opt, NULL);
}
@@ -1390,10 +1405,45 @@ ipset_parse_typename(struct ipset_session *session,
if (type == NULL)
return -1;
return ipset_session_data_set(session, IPSET_OPT_TYPE, type);
}
/**
* ipset_parse_iface - parse string as an interface name
* @session: session structure
* @opt: option kind of the data
* @str: string to parse
*
* Parse string as an interface name, optionally with 'physdev:' prefix.
* The value is stored in the data blob of the session.
*
* Returns 0 on success or a negative error code.
*/
int
ipset_parse_iface(struct ipset_session *session,
enum ipset_opt opt, const char *str)
{
struct ipset_data *data;
int offset = 0, err = 0;
assert(session);
assert(opt == IPSET_OPT_IFACE);
assert(str);
data = ipset_session_data(session);
if (STREQ(str, "physdev:")) {
offset = 8;
err = ipset_data_set(data, IPSET_OPT_PHYSDEV, str);
}
if (strlen(str + offset) > IFNAMSIZ - 1)
return syntax_err("interface name '%s' is longer "
"than %u characters",
str + offset, IFNAMSIZ - 1);
return ipset_data_set(data, opt, str + offset);
}
/**
* ipset_parse_output - parse output format name
* @session: session structure
@@ -1442,7 +1492,8 @@ ipset_parse_ignored(struct ipset_session *session,
if (!ipset_data_ignored(ipset_session_data(session), opt))
ipset_warn(session,
"Option %s is ignored. Please upgrade your syntax.", str);
"Option %s is ignored. "
"Please upgrade your syntax.", str);
return 0;
}
@@ -1473,7 +1524,7 @@ ipset_call_parser(struct ipset_session *session,
}
#define parse_elem(s, t, d, str) \
do { \
do { \
if (!(t)->elem[d].parse) \
goto internal; \
ret = (t)->elem[d].parse(s, (t)->elem[d].opt, str); \
@@ -1531,8 +1582,8 @@ ipset_parse_elem(struct ipset_session *session,
} else if (a != NULL) {
if (type->compat_parse_elem) {
ret = type->compat_parse_elem(session,
type->elem[IPSET_DIM_ONE].opt,
saved);
type->elem[IPSET_DIM_ONE].opt,
saved);
goto out;
}
elem_syntax_err("Elem separator in %s, "

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <assert.h> /* assert */
@@ -12,6 +12,7 @@
#include <sys/socket.h> /* inet_ntop */
#include <arpa/inet.h> /* inet_ntop */
#include <net/ethernet.h> /* ETH_ALEN */
#include <net/if.h> /* IFNAMSIZ */
#include <libipset/debug.h> /* D() */
#include <libipset/data.h> /* ipset_data_* */
@@ -53,15 +54,15 @@ ipset_print_ether(char *buf, unsigned int len,
{
const unsigned char *ether;
int i, size, offset = 0;
assert(buf);
assert(len > 0);
assert(data);
assert(opt == IPSET_OPT_ETHER);
if (len < ETH_ALEN*3)
return -1;
ether = ipset_data_get(data, opt);
assert(ether);
@@ -71,7 +72,7 @@ ipset_print_ether(char *buf, unsigned int len,
size = snprintf(buf + offset, len, ":%02X", ether[i]);
SNPRINTF_FAILURE(size, len, offset);
}
return offset;
}
@@ -138,35 +139,60 @@ ipset_print_type(char *buf, unsigned int len,
assert(type);
if (len < strlen(type->name) + 1)
return -1;
return snprintf(buf, len, "%s", type->name);
}
#define GETNAMEINFO(family, f, n) \
static inline int \
__getnameinfo##f(char *buf, unsigned int len, \
int flags, const union nf_inet_addr *addr) \
{ \
struct sockaddr_in##n saddr; \
int err; \
\
memset(&saddr, 0, sizeof(saddr)); \
in##f##cpy(&saddr.sin##n##_addr, &addr->in##n); \
saddr.sin##n##_family = family; \
\
err = getnameinfo((const struct sockaddr *)&saddr, \
sizeof(saddr), \
buf, len, NULL, 0, flags); \
\
if (!(flags & NI_NUMERICHOST) && \
(err == EAI_AGAIN || (err == 0 && strchr(buf, '-') != NULL))) \
err = getnameinfo((const struct sockaddr *)&saddr, \
sizeof(saddr), \
buf, len, NULL, 0, \
flags | NI_NUMERICHOST); \
D("getnameinfo err: %i, errno %i", err, errno); \
return (err == 0 ? (int)strlen(buf) : \
(err == EAI_OVERFLOW || err == EAI_SYSTEM) ? (int)len : -1);\
static inline int
__getnameinfo4(char *buf, unsigned int len,
int flags, const union nf_inet_addr *addr)
{
struct sockaddr_in saddr;
int err;
memset(&saddr, 0, sizeof(saddr));
in4cpy(&saddr.sin_addr, &addr->in);
saddr.sin_family = AF_INET;
err = getnameinfo((const struct sockaddr *)&saddr,
sizeof(saddr),
buf, len, NULL, 0, flags);
if (!(flags & NI_NUMERICHOST) &&
(err == EAI_AGAIN || (err == 0 && strchr(buf, '-') != NULL)))
err = getnameinfo((const struct sockaddr *)&saddr,
sizeof(saddr),
buf, len, NULL, 0,
flags | NI_NUMERICHOST);
D("getnameinfo err: %i, errno %i", err, errno);
return (err == 0 ? (int)strlen(buf) :
(err == EAI_OVERFLOW || err == EAI_SYSTEM) ? (int)len : -1);
}
static inline int
__getnameinfo6(char *buf, unsigned int len,
int flags, const union nf_inet_addr *addr)
{
struct sockaddr_in6 saddr;
int err;
memset(&saddr, 0, sizeof(saddr));
in6cpy(&saddr.sin6_addr, &addr->in6);
saddr.sin6_family = AF_INET6;
err = getnameinfo((const struct sockaddr *)&saddr,
sizeof(saddr),
buf, len, NULL, 0, flags);
if (!(flags & NI_NUMERICHOST) &&
(err == EAI_AGAIN || (err == 0 && strchr(buf, '-') != NULL)))
err = getnameinfo((const struct sockaddr *)&saddr,
sizeof(saddr),
buf, len, NULL, 0,
flags | NI_NUMERICHOST);
D("getnameinfo err: %i, errno %i", err, errno);
return (err == 0 ? (int)strlen(buf) :
(err == EAI_OVERFLOW || err == EAI_SYSTEM) ? (int)len : -1);
}
#define SNPRINTF_IP(mask, f) \
@@ -189,10 +215,8 @@ snprintf_ipv##f(char *buf, unsigned int len, int flags, \
return offset; \
}
GETNAMEINFO(AF_INET, 4, )
SNPRINTF_IP(32, 4)
GETNAMEINFO(AF_INET6, 6, 6)
SNPRINTF_IP(128, 6)
/**
@@ -231,7 +255,7 @@ ipset_print_ip(char *buf, unsigned int len,
} else
cidr = family == AF_INET6 ? 128 : 32;
flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;
ip = ipset_data_get(data, opt);
assert(ip);
if (family == AF_INET)
@@ -257,8 +281,8 @@ ipset_print_ip(char *buf, unsigned int len,
size = snprintf_ipv6(buf + offset, len, flags, ip, cidr);
else
return -1;
SNPRINTF_FAILURE(size, len, offset);
SNPRINTF_FAILURE(size, len, offset);
return offset;
}
@@ -287,9 +311,9 @@ ipset_print_ipaddr(char *buf, unsigned int len,
assert(buf);
assert(len > 0);
assert(data);
assert(opt == IPSET_OPT_IP
|| opt == IPSET_OPT_IP_TO
|| opt == IPSET_OPT_IP2);
assert(opt == IPSET_OPT_IP ||
opt == IPSET_OPT_IP_TO ||
opt == IPSET_OPT_IP2);
family = ipset_data_family(data);
cidropt = opt == IPSET_OPT_IP ? IPSET_OPT_CIDR : IPSET_OPT_CIDR2;
@@ -332,7 +356,7 @@ ipset_print_number(char *buf, unsigned int len,
assert(buf);
assert(len > 0);
assert(data);
number = ipset_data_get(data, opt);
maxsize = ipset_data_sizeof(opt, AF_INET);
D("opt: %u, maxsize %zu", opt, maxsize);
@@ -379,7 +403,7 @@ ipset_print_name(char *buf, unsigned int len,
name = ipset_data_get(data, opt);
assert(name);
size = snprintf(buf, len, "%s", name);
SNPRINTF_FAILURE(size, len, offset);
SNPRINTF_FAILURE(size, len, offset);
if (ipset_data_test(data, IPSET_OPT_NAMEREF)) {
bool before = false;
@@ -389,10 +413,10 @@ ipset_print_name(char *buf, unsigned int len,
before = (*flags) & IPSET_FLAG_BEFORE;
}
size = snprintf(buf + offset, len,
" %s %s", before ? "before" : "after",
(const char *) ipset_data_get(data,
IPSET_OPT_NAMEREF));
SNPRINTF_FAILURE(size, len, offset);
" %s %s", before ? "before" : "after",
(const char *) ipset_data_get(data,
IPSET_OPT_NAMEREF));
SNPRINTF_FAILURE(size, len, offset);
}
return offset;
@@ -430,19 +454,58 @@ ipset_print_port(char *buf, unsigned int len,
port = ipset_data_get(data, IPSET_OPT_PORT);
assert(port);
size = snprintf(buf, len, "%u", *port);
SNPRINTF_FAILURE(size, len, offset);
SNPRINTF_FAILURE(size, len, offset);
if (ipset_data_test(data, IPSET_OPT_PORT_TO)) {
port = ipset_data_get(data, IPSET_OPT_PORT_TO);
size = snprintf(buf + offset, len,
"%s%u",
IPSET_RANGE_SEPARATOR, *port);
"%s%u",
IPSET_RANGE_SEPARATOR, *port);
SNPRINTF_FAILURE(size, len, offset);
}
return offset;
}
/**
* ipset_print_iface - print interface element string
* @buf: printing buffer
* @len: length of available buffer space
* @data: data blob
* @opt: the option kind
* @env: environment flags
*
* Print interface element string to output buffer.
*
* Return lenght of printed string or error size.
*/
int
ipset_print_iface(char *buf, unsigned int len,
const struct ipset_data *data, enum ipset_opt opt,
uint8_t env UNUSED)
{
const char *name;
int size, offset = 0;
assert(buf);
assert(len > 0);
assert(data);
assert(opt == IPSET_OPT_IFACE);
if (len < IFNAMSIZ + strlen("physdev:"))
return -1;
if (ipset_data_test(data, IPSET_OPT_PHYSDEV)) {
size = snprintf(buf, len, "physdev:");
SNPRINTF_FAILURE(size, len, offset);
}
name = ipset_data_get(data, opt);
assert(name);
size = snprintf(buf, len, "%s", name);
SNPRINTF_FAILURE(size, len, offset);
return offset;
}
/**
* ipset_print_proto - print protocol name
* @buf: printing buffer
@@ -471,12 +534,12 @@ ipset_print_proto(char *buf, unsigned int len,
proto = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO);
assert(proto);
protoent = getprotobynumber(proto);
if (protoent)
return snprintf(buf, len, "%s", protoent->p_name);
/* Should not happen */
/* Should not happen */
return snprintf(buf, len, "%u", proto);
}
@@ -511,7 +574,8 @@ ipset_print_icmp(char *buf, unsigned int len,
if (name != NULL)
return snprintf(buf, len, "%s", name);
else
return snprintf(buf, len, "%u/%u", typecode >> 8, typecode & 0xFF);
return snprintf(buf, len, "%u/%u",
typecode >> 8, typecode & 0xFF);
}
/**
@@ -545,7 +609,8 @@ ipset_print_icmpv6(char *buf, unsigned int len,
if (name != NULL)
return snprintf(buf, len, "%s", name);
else
return snprintf(buf, len, "%u/%u", typecode >> 8, typecode & 0xFF);
return snprintf(buf, len, "%u/%u",
typecode >> 8, typecode & 0xFF);
}
/**
@@ -574,8 +639,8 @@ ipset_print_proto_port(char *buf, unsigned int len,
assert(opt == IPSET_OPT_PORT);
if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_PROTO))) {
uint8_t proto = *(const uint8_t *) ipset_data_get(data,
IPSET_OPT_PROTO);
uint8_t proto = *(const uint8_t *) ipset_data_get(data,
IPSET_OPT_PROTO);
size = ipset_print_proto(buf, len, data, IPSET_OPT_PROTO, env);
SNPRINTF_FAILURE(size, len, offset);
if (len < 2)
@@ -601,16 +666,16 @@ ipset_print_proto_port(char *buf, unsigned int len,
}
size = ipset_print_port(buf + offset, len, data, IPSET_OPT_PORT, env);
SNPRINTF_FAILURE(size, len, offset);
return offset;
}
#define print_second(data) \
ipset_data_flags_test(data, \
IPSET_FLAG(IPSET_OPT_PORT)|IPSET_FLAG(IPSET_OPT_ETHER))
IPSET_FLAG(IPSET_OPT_PORT)|IPSET_FLAG(IPSET_OPT_ETHER))
#define print_third(data) \
ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_IP2))
ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_IP2))
/**
* ipset_print_elem - print ADT elem according to settype
@@ -639,25 +704,25 @@ ipset_print_elem(char *buf, unsigned int len,
type = ipset_data_get(data, IPSET_OPT_TYPE);
if (!type)
return -1;
size = type->elem[IPSET_DIM_ONE].print(buf, len, data,
type->elem[IPSET_DIM_ONE].opt, env);
SNPRINTF_FAILURE(size, len, offset);
IF_D(ipset_data_test(data, type->elem[IPSET_DIM_TWO].opt),
"print second elem");
if (type->dimension == IPSET_DIM_ONE
|| (type->last_elem_optional
&& !ipset_data_test(data, type->elem[IPSET_DIM_TWO].opt)))
if (type->dimension == IPSET_DIM_ONE ||
(type->last_elem_optional &&
!ipset_data_test(data, type->elem[IPSET_DIM_TWO].opt)))
return offset;
size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR);
SNPRINTF_FAILURE(size, len, offset);
size = type->elem[IPSET_DIM_TWO].print(buf + offset, len, data,
type->elem[IPSET_DIM_TWO].opt, env);
SNPRINTF_FAILURE(size, len, offset);
if (type->dimension == IPSET_DIM_TWO
|| (type->last_elem_optional
&& !ipset_data_test(data, type->elem[IPSET_DIM_THREE].opt)))
if (type->dimension == IPSET_DIM_TWO ||
(type->last_elem_optional &&
!ipset_data_test(data, type->elem[IPSET_DIM_THREE].opt)))
return offset;
size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR);
@@ -685,7 +750,7 @@ int
ipset_print_flag(char *buf UNUSED, unsigned int len UNUSED,
const struct ipset_data *data UNUSED,
enum ipset_opt opt UNUSED, uint8_t env UNUSED)
{
{
return 0;
}
@@ -731,6 +796,9 @@ ipset_print_data(char *buf, unsigned int len,
case IPSET_OPT_PORT:
size = ipset_print_port(buf, len, data, opt, env);
break;
case IPSET_OPT_IFACE:
size = ipset_print_iface(buf, len, data, opt, env);
break;
case IPSET_OPT_GC:
case IPSET_OPT_HASHSIZE:
case IPSET_OPT_MAXELEM:
@@ -747,6 +815,6 @@ ipset_print_data(char *buf, unsigned int len,
return -1;
}
SNPRINTF_FAILURE(size, len, offset);
return offset;
}

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <assert.h> /* assert */
@@ -13,6 +13,7 @@
#include <string.h> /* str* */
#include <unistd.h> /* getpagesize */
#include <net/ethernet.h> /* ETH_ALEN */
#include <net/if.h> /* IFNAMSIZ */
#include <libipset/debug.h> /* D() */
#include <libipset/data.h> /* IPSET_OPT_* */
@@ -199,14 +200,14 @@ ipset_session_output(struct ipset_session *session,
*
* Returns -1.
*/
int __attribute__((format(printf,3,4)))
int __attribute__((format(printf, 3, 4)))
ipset_session_report(struct ipset_session *session,
enum ipset_err_type type,
enum ipset_err_type type,
const char *fmt, ...)
{
int len, offset = 0;
va_list args;
assert(session);
assert(fmt);
@@ -215,13 +216,13 @@ ipset_session_report(struct ipset_session *session,
session->lineno);
}
offset = strlen(session->report);
va_start(args, fmt);
len = vsnprintf(session->report + offset,
IPSET_ERRORBUFLEN - 1 - offset,
fmt, args);
IPSET_ERRORBUFLEN - 1 - offset,
fmt, args);
va_end(args);
if (len >= IPSET_ERRORBUFLEN - 1 - offset)
session->report[IPSET_ERRORBUFLEN - 1] = '\0';
if (strlen(session->report) < IPSET_ERRORBUFLEN - 1)
@@ -475,6 +476,11 @@ static const struct ipset_attr_policy adt_attrs[] = {
.type = MNL_TYPE_NESTED,
.opt = IPSET_OPT_IP2_TO,
},
[IPSET_ATTR_IFACE] = {
.type = MNL_TYPE_NUL_STRING,
.opt = IPSET_OPT_IFACE,
.len = IFNAMSIZ,
},
};
static const struct ipset_attr_policy ipaddr_attrs[] = {
@@ -497,7 +503,7 @@ generic_data_attr_cb(const struct nlattr *attr, void *data,
{
const struct nlattr **tb = data;
int type = mnl_attr_get_type(attr);
IF_D(debug, "attr type: %u, len %u", type, attr->nla_len);
if (mnl_attr_type_valid(attr, attr_max) < 0) {
IF_D(debug, "attr type: %u INVALID", type);
@@ -508,9 +514,9 @@ generic_data_attr_cb(const struct nlattr *attr, void *data,
mnl_attr_get_payload_len(attr));
return MNL_CB_ERROR;
}
if (policy[type].type == MNL_TYPE_NUL_STRING
&& mnl_attr_get_payload_len(attr) > IPSET_MAXNAMELEN)
return MNL_CB_ERROR;
if (policy[type].type == MNL_TYPE_NUL_STRING &&
mnl_attr_get_payload_len(attr) > IPSET_MAXNAMELEN)
return MNL_CB_ERROR;
tb[type] = attr;
return MNL_CB_OK;
}
@@ -594,7 +600,7 @@ attr2data(struct ipset_session *session, struct nlattr *nla[],
switch (attr->type) {
case MNL_TYPE_U32: {
uint32_t value;
value = ntohl(*(const uint32_t *)d);
d = &value;
@@ -602,7 +608,7 @@ attr2data(struct ipset_session *session, struct nlattr *nla[],
}
case MNL_TYPE_U16: {
uint16_t value;
value = ntohs(*(const uint16_t *)d);
d = &value;
@@ -613,15 +619,15 @@ attr2data(struct ipset_session *session, struct nlattr *nla[],
}
}
#ifdef IPSET_DEBUG
if (type == IPSET_ATTR_TYPENAME)
if (type == IPSET_ATTR_TYPENAME)
D("nla typename %s", (const char *) d);
#endif
ret = ipset_data_set(data, attr->opt, d);
#ifdef IPSET_DEBUG
if (type == IPSET_ATTR_TYPENAME)
if (type == IPSET_ATTR_TYPENAME)
D("nla typename %s",
(const char *) ipset_data_get(data, IPSET_OPT_TYPENAME));
#endif
#endif
return ret;
}
@@ -650,16 +656,16 @@ static inline int
call_outfn(struct ipset_session *session)
{
int ret = session->outfn("%s", session->outbuf);
session->outbuf[0] = '\0';
return ret < 0 ? ret : 0;
}
/* Handle printing failures */
static jmp_buf printf_failure;
static int __attribute__((format(printf,2,3)))
static int __attribute__((format(printf, 2, 3)))
safe_snprintf(struct ipset_session *session, const char *fmt, ...)
{
va_list args;
@@ -672,7 +678,7 @@ retry:
ret = vsnprintf(session->outbuf + len, IPSET_OUTBUFLEN - len,
fmt, args);
va_end(args);
if (ret < 0) {
ipset_err(session,
"Internal error at printing to output buffer");
@@ -706,7 +712,7 @@ retry:
D("len: %u, retry %u", len, loop);
ret = fn(session->outbuf + len, IPSET_OUTBUFLEN - len,
session->data, opt, session->envopts);
if (ret < 0) {
ipset_err(session,
"Internal error at printing to output buffer");
@@ -728,7 +734,7 @@ retry:
}
return ret;
}
static int
list_adt(struct ipset_session *session, struct nlattr *nla[])
{
@@ -738,7 +744,7 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
uint8_t family;
int i, found = 0;
D("enter");
D("enter");
/* Check and load type, family */
if (!ipset_data_test(data, IPSET_OPT_TYPE))
type = ipset_type_get(session, IPSET_CMD_ADD);
@@ -769,7 +775,7 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
default:
break;
}
safe_dprintf(session, ipset_print_elem, IPSET_OPT_ELEM);
for (arg = type->args[IPSET_ADD]; arg != NULL && arg->print; arg++) {
@@ -800,7 +806,7 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
break;
}
}
if (session->mode == IPSET_LIST_XML)
safe_snprintf(session, "</member>\n");
else
@@ -859,10 +865,10 @@ list_create(struct ipset_session *session, struct nlattr *nla[])
}
for (arg = type->args[IPSET_CREATE]; arg != NULL && arg->opt; arg++) {
if (!arg->print
|| !ipset_data_test(data, arg->opt)
|| (arg->opt == IPSET_OPT_FAMILY
&& family == type->family))
if (!arg->print ||
!ipset_data_test(data, arg->opt) ||
(arg->opt == IPSET_OPT_FAMILY &&
family == type->family))
continue;
switch (session->mode) {
case IPSET_LIST_SAVE:
@@ -975,15 +981,15 @@ callback_list(struct ipset_session *session, struct nlattr *nla[],
if (STREQ(ipset_data_setname(data), session->saved_setname)) {
/* Header part already seen */
if (ipset_data_test(data, IPSET_OPT_TYPE)
&& nla[IPSET_ATTR_DATA] != NULL)
if (ipset_data_test(data, IPSET_OPT_TYPE) &&
nla[IPSET_ATTR_DATA] != NULL)
FAILURE("Broken %s kernel message: "
"extra DATA received!", cmd2name[cmd]);
} else {
if (nla[IPSET_ATTR_DATA] == NULL)
FAILURE("Broken %s kernel message: "
"missing DATA part!", cmd2name[cmd]);
/* Close previous set printing */
if (session->saved_setname[0] != '\0')
print_set_done(session);
@@ -992,13 +998,14 @@ callback_list(struct ipset_session *session, struct nlattr *nla[],
if (nla[IPSET_ATTR_DATA] != NULL) {
struct nlattr *cattr[IPSET_ATTR_CREATE_MAX+1] = {};
if (!(nla[IPSET_ATTR_TYPENAME]
&& nla[IPSET_ATTR_FAMILY]
&& nla[IPSET_ATTR_REVISION]))
if (!(nla[IPSET_ATTR_TYPENAME] &&
nla[IPSET_ATTR_FAMILY] &&
nla[IPSET_ATTR_REVISION]))
FAILURE("Broken %s kernel message: missing %s!",
cmd2name[cmd],
!nla[IPSET_ATTR_TYPENAME] ? "typename" :
!nla[IPSET_ATTR_FAMILY] ? "family" : "revision");
!nla[IPSET_ATTR_TYPENAME] ? "typename" :
!nla[IPSET_ATTR_FAMILY] ? "family" :
"revision");
/* Reset CREATE specific flags */
ipset_data_flags_unset(data, IPSET_CREATE_FLAGS);
@@ -1021,7 +1028,7 @@ callback_list(struct ipset_session *session, struct nlattr *nla[],
return MNL_CB_ERROR;
strcpy(session->saved_setname, ipset_data_setname(data));
}
if (nla[IPSET_ATTR_ADT] != NULL) {
struct nlattr *tb, *adt[IPSET_ATTR_ADT_MAX+1];
@@ -1053,7 +1060,7 @@ static int
callback_version(struct ipset_session *session, struct nlattr *nla[])
{
uint8_t min, max;
min = max = mnl_attr_get_u8(nla[IPSET_ATTR_PROTOCOL]);
if (nla[IPSET_ATTR_PROTOCOL_MIN]) {
@@ -1067,8 +1074,8 @@ callback_version(struct ipset_session *session, struct nlattr *nla[])
"while userspace supports protocol versions %u-%u",
min, max, IPSET_PROTOCOL_MIN, IPSET_PROTOCOL_MAX);
if (!(session->envopts & IPSET_ENV_QUIET)
&& max != IPSET_PROTOCOL_MAX)
if (!(session->envopts & IPSET_ENV_QUIET) &&
max != IPSET_PROTOCOL_MAX)
ipset_warn(session,
"Kernel support protocol versions %u-%u "
"while userspace supports protocol versions %u-%u",
@@ -1084,7 +1091,7 @@ callback_header(struct ipset_session *session, struct nlattr *nla[])
{
const char *setname;
const struct ipset_data *data = session->data;
if (!nla[IPSET_ATTR_SETNAME])
FAILURE("Broken HEADER kernel message: missing setname!");
@@ -1093,10 +1100,10 @@ callback_header(struct ipset_session *session, struct nlattr *nla[])
FAILURE("Broken HEADER kernel message: sent setname `%s' "
"does not match with received one `%s'!",
ipset_data_setname(data), setname);
if (!(nla[IPSET_ATTR_TYPENAME]
&& nla[IPSET_ATTR_REVISION]
&& nla[IPSET_ATTR_FAMILY]))
if (!(nla[IPSET_ATTR_TYPENAME] &&
nla[IPSET_ATTR_REVISION] &&
nla[IPSET_ATTR_FAMILY]))
FAILURE("Broken HEADER kernel message: "
"missing attribute '%s'!",
!nla[IPSET_ATTR_TYPENAME] ? "typename" :
@@ -1116,10 +1123,10 @@ callback_type(struct ipset_session *session, struct nlattr *nla[])
{
const struct ipset_data *data = session->data;
const char *typename, *orig;
if (!(nla[IPSET_ATTR_TYPENAME]
&& nla[IPSET_ATTR_REVISION]
&& nla[IPSET_ATTR_FAMILY]))
if (!(nla[IPSET_ATTR_TYPENAME] &&
nla[IPSET_ATTR_REVISION] &&
nla[IPSET_ATTR_FAMILY]))
FAILURE("Broken TYPE kernel message: "
"missing attribute '%s'!",
!nla[IPSET_ATTR_TYPENAME] ? "typename" :
@@ -1132,7 +1139,7 @@ callback_type(struct ipset_session *session, struct nlattr *nla[])
FAILURE("Broken TYPE kernel message: sent typename `%s' "
"does not match with received one `%s'!",
orig, typename);
ATTR2DATA(session, nla, IPSET_ATTR_TYPENAME, cmd_attrs);
ATTR2DATA(session, nla, IPSET_ATTR_REVISION, cmd_attrs);
ATTR2DATA(session, nla, IPSET_ATTR_FAMILY, cmd_attrs);
@@ -1156,7 +1163,7 @@ mnl_attr_parse_dbg(const struct nlmsghdr *nlh, int offset,
int ret = MNL_CB_OK;
struct nlattr *attr = mnl_nlmsg_get_payload_offset(nlh, offset);
int len = nlh->nlmsg_len - MNL_NLMSG_HDRLEN - MNL_ALIGN(offset);
while (mnl_attr_ok(attr, len)) {
D("attr: type %u, attrlen %u, len %u",
mnl_attr_get_type(attr), attr->nla_len, len);
@@ -1175,7 +1182,7 @@ callback_data(const struct nlmsghdr *nlh, void *data)
struct nlattr *nla[IPSET_ATTR_CMD_MAX+1] = {};
uint8_t proto, cmd;
int ret = MNL_CB_OK, nfmsglen = MNL_ALIGN(sizeof(struct genlmsghdr));
D("called, nlmsg_len %u", nlh->nlmsg_len);
cmd = ipset_get_nlmsg_type(nlh);
if (cmd == IPSET_CMD_LIST && session->cmd == IPSET_CMD_SAVE)
@@ -1195,8 +1202,8 @@ callback_data(const struct nlmsghdr *nlh, void *data)
if (!nla[IPSET_ATTR_PROTOCOL])
FAILURE("Sad, sad day: kernel message %s "
"does not carry the protocol version.",
cmd2name[cmd]);
"does not carry the protocol version.",
cmd2name[cmd]);
proto = mnl_attr_get_u8(nla[IPSET_ATTR_PROTOCOL]);
@@ -1241,8 +1248,8 @@ callback_done(const struct nlmsghdr *nlh UNUSED, void *data)
D(" called");
if (session->cmd == IPSET_CMD_LIST || session->cmd == IPSET_CMD_SAVE)
return print_set_done(session);
return print_set_done(session);
FAILURE("Invalid message received in non LIST or SAVE state.");
}
@@ -1254,7 +1261,7 @@ decode_errmsg(struct ipset_session *session, const struct nlmsghdr *nlh)
struct nlattr *nla[IPSET_ATTR_CMD_MAX+1] = {};
enum ipset_cmd cmd;
int nfmsglen = MNL_ALIGN(sizeof(struct genlmsghdr));
if (nlh->nlmsg_len < (uint32_t) MNL_ALIGN(sizeof(struct nlmsgerr))
|| nlh->nlmsg_len < MNL_ALIGN(sizeof(struct nlmsgerr))
+ msg->nlmsg_len)
@@ -1277,15 +1284,15 @@ decode_errmsg(struct ipset_session *session, const struct nlmsghdr *nlh)
FAILURE("Broken %s error report message: "
"missing protocol attribute",
cmd2name[cmd]);
if (nla[IPSET_ATTR_LINENO]) {
session->lineno = mnl_attr_get_u32(nla[IPSET_ATTR_LINENO]);
if (nla[IPSET_ATTR_LINENO]->nla_type & NLA_F_NET_BYTEORDER)
session->lineno = ntohl(session->lineno);
}
return ipset_errcode(session, cmd, -err->error);
}
}
static int
callback_error(const struct nlmsghdr *nlh, void *cbdata)
@@ -1318,16 +1325,20 @@ callback_error(const struct nlmsghdr *nlh, void *cbdata)
break;
case IPSET_CMD_RENAME:
ipset_cache_rename(ipset_data_setname(data),
ipset_data_get(data, IPSET_OPT_SETNAME2));
ipset_data_get(data,
IPSET_OPT_SETNAME2));
break;
case IPSET_CMD_SWAP:
ipset_cache_swap(ipset_data_setname(data),
ipset_data_get(data, IPSET_OPT_SETNAME2));
ipset_data_get(data,
IPSET_OPT_SETNAME2));
break;
case IPSET_CMD_TEST:
if (!(session->envopts & IPSET_ENV_QUIET)) {
ipset_print_elem(session->report, IPSET_ERRORBUFLEN,
session->data, IPSET_OPT_NONE, 0);
ipset_print_elem(session->report,
IPSET_ERRORBUFLEN,
session->data,
IPSET_OPT_NONE, 0);
ipset_warn(session, " is in set %s.",
ipset_data_setname(data));
}
@@ -1341,7 +1352,8 @@ callback_error(const struct nlmsghdr *nlh, void *cbdata)
print_set_done(session);
break;
default:
FAILURE("ACK message received to command %s[%u], which is not expected",
FAILURE("ACK message received to command %s[%u], "
"which is not expected",
session->cmd < IPSET_MSG_MAX
? cmd2name[session->cmd] : "unknown",
session->cmd);
@@ -1351,10 +1363,10 @@ callback_error(const struct nlmsghdr *nlh, void *cbdata)
D("nlmsgerr error: %u", -err->error);
/* Error messages */
/* Special case for IPSET_CMD_TEST */
if (session->cmd == IPSET_CMD_TEST
&& err->error == -IPSET_ERR_EXIST) {
if (session->cmd == IPSET_CMD_TEST &&
err->error == -IPSET_ERR_EXIST) {
if (!(session->envopts & IPSET_ENV_QUIET)) {
ipset_print_elem(session->report, IPSET_ERRORBUFLEN,
session->data, IPSET_OPT_NONE, 0);
@@ -1365,7 +1377,7 @@ callback_error(const struct nlmsghdr *nlh, void *cbdata)
}
decode_errmsg(session, nlh);
return ret;
}
@@ -1419,7 +1431,8 @@ attr_len(const struct ipset_attr_policy *attr, uint8_t family, uint16_t *flags)
}
#define BUFFER_FULL(bufsize, nlmsg_len, nestlen, attrlen) \
(nlmsg_len + nestlen + MNL_ATTR_HDRLEN + MNL_ALIGN(alen) + MNL_ALIGN(sizeof(struct nlmsgerr)) > bufsize)
(nlmsg_len + nestlen + MNL_ATTR_HDRLEN + MNL_ALIGN(alen) + \
MNL_ALIGN(sizeof(struct nlmsgerr)) > bufsize)
static int
rawdata2attr(struct ipset_session *session, struct nlmsghdr *nlh,
@@ -1439,14 +1452,15 @@ rawdata2attr(struct ipset_session *session, struct nlmsghdr *nlh,
: IPSET_ATTR_IPADDR_IPV6;
alen = attr_len(attr, family, &flags);
if (BUFFER_FULL(session->bufsize, nlh->nlmsg_len, MNL_ATTR_HDRLEN, alen))
if (BUFFER_FULL(session->bufsize, nlh->nlmsg_len,
MNL_ATTR_HDRLEN, alen))
return 1;
nested = mnl_attr_nest_start(nlh, type);
D("family: %s", family == AF_INET ? "INET" :
family == AF_INET6 ? "INET6" : "UNSPEC");
mnl_attr_put(nlh, atype | flags, alen, d);
mnl_attr_nest_end(nlh, nested);
return 0;
}
@@ -1460,20 +1474,20 @@ rawdata2attr(struct ipset_session *session, struct nlmsghdr *nlh,
break;
case MNL_TYPE_U32: {
uint32_t value = htonl(*(const uint32_t *)d);
d = &value;
break;
}
case MNL_TYPE_U16: {
uint16_t value = htons(*(const uint16_t *)d);
d = &value;
break;
}
default:
break;
}
mnl_attr_put(nlh, type | flags, alen, d);
return 0;
@@ -1500,7 +1514,7 @@ data2attr(struct ipset_session *session, struct nlmsghdr *nlh,
data2attr(session, nlh, data, IPSET_ATTR_SETNAME, AF_INET, cmd_attrs)
#define ADDATTR_IF(session, nlh, data, type, family, attrs) \
ipset_data_test(data, attrs[type].opt) ? \
ipset_data_test(data, attrs[type].opt) ? \
data2attr(session, nlh, data, type, family, attrs) : 0
#define ADDATTR_RAW(session, nlh, data, type, attrs) \
@@ -1521,7 +1535,7 @@ addattr_adt(struct ipset_session *session,
struct nlmsghdr *nlh, struct ipset_data *data, uint8_t family)
{
int i;
for (i = IPSET_ATTR_UNSPEC + 1; i <= IPSET_ATTR_ADT_MAX; i++)
if (ADDATTR_IF(session, nlh, data, i, family, adt_attrs))
return 1;
@@ -1541,7 +1555,7 @@ build_send_private_msg(struct ipset_session *session, enum ipset_cmd cmd)
/* Initialize header */
session->transport->fill_hdr(session->handle, cmd, buffer, len, 0);
ADDATTR_PROTOCOL(nlh);
switch (cmd) {
@@ -1559,9 +1573,11 @@ build_send_private_msg(struct ipset_session *session, enum ipset_cmd cmd)
return ipset_err(session,
"Invalid internal TYPE command: "
"missing settype");
ADDATTR(session, nlh, data, IPSET_ATTR_TYPENAME, AF_INET, cmd_attrs);
ADDATTR(session, nlh, data, IPSET_ATTR_TYPENAME,
AF_INET, cmd_attrs);
if (ipset_data_test(data, IPSET_OPT_FAMILY))
ADDATTR(session, nlh, data, IPSET_ATTR_FAMILY, AF_INET, cmd_attrs);
ADDATTR(session, nlh, data, IPSET_ATTR_FAMILY,
AF_INET, cmd_attrs);
else
/* bitmap:port and list:set types */
mnl_attr_put_u8(nlh, IPSET_ATTR_FAMILY, AF_UNSPEC);
@@ -1582,10 +1598,10 @@ build_send_private_msg(struct ipset_session *session, enum ipset_cmd cmd)
static inline bool
may_aggregate_ad(struct ipset_session *session, enum ipset_cmd cmd)
{
return session->lineno != 0
&& (cmd == IPSET_CMD_ADD || cmd == IPSET_CMD_DEL)
&& cmd == session->cmd
&& STREQ(ipset_data_setname(session->data), session->saved_setname);
return session->lineno != 0 &&
(cmd == IPSET_CMD_ADD || cmd == IPSET_CMD_DEL) &&
cmd == session->cmd &&
STREQ(ipset_data_setname(session->data), session->saved_setname);
}
static int
@@ -1618,12 +1634,13 @@ build_msg(struct ipset_session *session, bool aggregate)
if (!ipset_data_test(data, IPSET_OPT_TYPE))
return ipset_err(session,
"Invalid create command: missing settype");
type = ipset_data_get(data, IPSET_OPT_TYPE);
/* Core attributes:
* setname, typename, revision, family, flags (optional) */
ADDATTR_SETNAME(session, nlh, data);
ADDATTR(session, nlh, data, IPSET_ATTR_TYPENAME, AF_INET, cmd_attrs);
ADDATTR(session, nlh, data, IPSET_ATTR_TYPENAME,
AF_INET, cmd_attrs);
ADDATTR_RAW(session, nlh, &type->revision,
IPSET_ATTR_REVISION, cmd_attrs);
D("family: %u, type family %u",
@@ -1651,7 +1668,7 @@ build_msg(struct ipset_session *session, bool aggregate)
break;
case IPSET_CMD_LIST: {
uint32_t flags = 0;
if (session->envopts & IPSET_ENV_LIST_SETNAME)
flags |= IPSET_FLAG_LIST_SETNAME;
if (session->envopts & IPSET_ENV_LIST_HEADER)
@@ -1670,13 +1687,16 @@ build_msg(struct ipset_session *session, bool aggregate)
if (!ipset_data_test(data, IPSET_SETNAME))
return ipset_err(session,
"Invalid %s command: missing from-setname",
session->cmd == IPSET_CMD_SWAP ? "swap" : "rename");
session->cmd == IPSET_CMD_SWAP ? "swap" :
"rename");
if (!ipset_data_test(data, IPSET_OPT_SETNAME2))
return ipset_err(session,
"Invalid %s command: missing to-setname",
session->cmd == IPSET_CMD_SWAP ? "swap" : "rename");
session->cmd == IPSET_CMD_SWAP ? "swap" :
"rename");
ADDATTR_SETNAME(session, nlh, data);
ADDATTR_RAW(session, nlh, ipset_data_get(data, IPSET_OPT_SETNAME2),
ADDATTR_RAW(session, nlh,
ipset_data_get(data, IPSET_OPT_SETNAME2),
IPSET_ATTR_SETNAME2, cmd_attrs);
break;
case IPSET_CMD_ADD:
@@ -1688,12 +1708,14 @@ build_msg(struct ipset_session *session, bool aggregate)
if (!ipset_data_test(data, IPSET_SETNAME))
return ipset_err(session,
"Invalid %s command: missing setname",
session->cmd == IPSET_CMD_ADD ? "add" : "del");
session->cmd == IPSET_CMD_ADD ? "add" :
"del");
if (!ipset_data_test(data, IPSET_OPT_TYPE))
return ipset_err(session,
"Invalid %s command: missing settype",
session->cmd == IPSET_CMD_ADD ? "add" : "del");
session->cmd == IPSET_CMD_ADD ? "add" :
"del");
/* Core options: setname */
ADDATTR_SETNAME(session, nlh, data);
@@ -1711,11 +1733,12 @@ build_msg(struct ipset_session *session, bool aggregate)
D("open_nested failed");
return 1;
}
if (addattr_adt(session, nlh, data, ipset_data_family(data))
|| ADDATTR_RAW(session, nlh, &session->lineno,
IPSET_ATTR_LINENO, cmd_attrs)) {
if (addattr_adt(session, nlh, data, ipset_data_family(data)) ||
ADDATTR_RAW(session, nlh, &session->lineno,
IPSET_ATTR_LINENO, cmd_attrs)) {
/* Cancel last, unfinished nested attribute */
mnl_attr_nest_cancel(nlh, session->nested[session->nestid-1]);
mnl_attr_nest_cancel(nlh,
session->nested[session->nestid-1]);
session->nested[--session->nestid] = NULL;
return 1;
}
@@ -1727,7 +1750,7 @@ build_msg(struct ipset_session *session, bool aggregate)
/* Return codes are not aggregated, so tests cannot be either */
/* Setname, type not checked/added yet */
if (!ipset_data_test(data, IPSET_SETNAME))
return ipset_err(session,
"Invalid test command: missing setname");
@@ -1735,7 +1758,7 @@ build_msg(struct ipset_session *session, bool aggregate)
if (!ipset_data_test(data, IPSET_OPT_TYPE))
return ipset_err(session,
"Invalid test command: missing settype");
type = ipset_data_get(data, IPSET_OPT_TYPE);
D("family: %u, type family %u",
ipset_data_family(data), type->family);
@@ -1769,7 +1792,8 @@ ipset_commit(struct ipset_session *session)
assert(session);
nlh = session->buffer;
D("send buffer: len %u, cmd %s", nlh->nlmsg_len, cmd2name[session->cmd]);
D("send buffer: len %u, cmd %s",
nlh->nlmsg_len, cmd2name[session->cmd]);
if (nlh->nlmsg_len == 0)
/* Nothing to do */
return 0;
@@ -1798,7 +1822,7 @@ ipset_commit(struct ipset_session *session)
return -1;
else
return ipset_err(session,
"Internal protocol error");
"Internal protocol error");
}
return 0;
}
@@ -1810,7 +1834,7 @@ static mnl_cb_t cb_ctl[] = {
[NLMSG_OVERRUN] = callback_noop,
[NLMSG_MIN_TYPE] = callback_data,
};
static inline struct ipset_handle *
init_transport(struct ipset_session *session)
{
@@ -1839,7 +1863,7 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
struct ipset_data *data;
bool aggregate = false;
int ret = -1;
assert(session);
if (cmd <= IPSET_CMD_NONE || cmd >= IPSET_MSG_MAX)
@@ -1859,9 +1883,9 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
}
/* Private commands */
if (cmd == IPSET_CMD_TYPE || cmd == IPSET_CMD_HEADER)
if (cmd == IPSET_CMD_TYPE || cmd == IPSET_CMD_HEADER)
return build_send_private_msg(session, cmd);
/* Check aggregatable commands */
aggregate = may_aggregate_ad(session, cmd);
if (!aggregate) {
@@ -1874,7 +1898,7 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
/* Real command: update lineno too */
session->cmd = cmd;
session->lineno = lineno;
/* Set default output mode */
if (cmd == IPSET_CMD_LIST) {
if (session->mode == IPSET_LIST_NONE)
@@ -1902,8 +1926,8 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
/* We have to save the type for error handling */
session->saved_type = ipset_data_get(data, IPSET_OPT_TYPE);
if (session->lineno != 0
&& (cmd == IPSET_CMD_ADD || cmd == IPSET_CMD_DEL)) {
if (session->lineno != 0 &&
(cmd == IPSET_CMD_ADD || cmd == IPSET_CMD_DEL)) {
/* Save setname for the next possible aggregated restore line */
strcpy(session->saved_setname, ipset_data_setname(data));
ipset_data_reset(data);
@@ -1912,7 +1936,7 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
goto cleanup;
}
D("call commit");
D("call commit");
ret = ipset_commit(session);
cleanup:
@@ -1944,10 +1968,10 @@ ipset_session_init(ipset_outfn outfn)
/* The single transport method yet */
session->transport = &ipset_mnl_transport;
/* Output function */
session->outfn = outfn;
/* Initialize data structures */
session->data = ipset_data_init();
if (session->data == NULL)
@@ -1957,8 +1981,8 @@ ipset_session_init(ipset_outfn outfn)
return session;
free_session:
free(session);
return NULL;
free(session);
return NULL;
}
/**

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <assert.h> /* assert */
@@ -28,8 +28,8 @@ struct ipset {
struct ipset *next;
};
static struct ipset_type *typelist = NULL; /* registered set types */
static struct ipset *setlist = NULL; /* cached sets */
static struct ipset_type *typelist; /* registered set types */
static struct ipset *setlist; /* cached sets */
/**
* ipset_cache_add - add a set to the cache
@@ -57,7 +57,7 @@ ipset_cache_add(const char *name, const struct ipset_type *type,
ipset_strlcpy(n->name, name, IPSET_MAXNAMELEN);
n->type = type;
n->family = family;
n->next = NULL;
n->next = NULL;
if (setlist == NULL) {
setlist = n;
@@ -109,7 +109,7 @@ ipset_cache_del(const char *name)
}
if (match == NULL)
return -EEXIST;
free(match);
return 0;
}
@@ -168,7 +168,7 @@ ipset_cache_swap(const char *from, const char *to)
ipset_strlcpy(b->name, from, IPSET_MAXNAMELEN);
return 0;
}
return -EEXIST;
}
@@ -178,7 +178,7 @@ ipset_cache_swap(const char *from, const char *to)
bool
ipset_match_typename(const char *name, const struct ipset_type *type)
{
const char * const * alias = type->alias;
const char * const *alias = type->alias;
if (STREQ(name, type->name))
return true;
@@ -189,7 +189,7 @@ ipset_match_typename(const char *name, const struct ipset_type *type)
alias++;
}
return false;
}
}
static inline const struct ipset_type *
create_type_get(struct ipset_session *session)
@@ -215,17 +215,17 @@ create_type_get(struct ipset_session *session)
if (ipset_match_typename(typename, t)
&& MATCH_FAMILY(t, family)) {
if (match == NULL) {
match = t;
tmin = tmax = t->revision;
match = t;
tmin = tmax = t->revision;
} else if (t->family == match->family)
tmin = t->revision;
}
}
}
if (!match)
return ipset_errptr(session,
"Syntax error: unknown settype %s",
typename);
/* Family is unspecified yet: set from matching set type */
if (family == AF_UNSPEC && match->family != AF_UNSPEC) {
family = match->family == AF_INET46 ? AF_INET : match->family;
@@ -240,9 +240,11 @@ create_type_get(struct ipset_session *session)
if (ret != 0)
return NULL;
kmin = kmax = *(const uint8_t *)ipset_data_get(data, IPSET_OPT_REVISION);
kmin = kmax = *(const uint8_t *)ipset_data_get(data,
IPSET_OPT_REVISION);
if (ipset_data_test(data, IPSET_OPT_REVISION_MIN))
kmin = *(const uint8_t *)ipset_data_get(data, IPSET_OPT_REVISION_MIN);
kmin = *(const uint8_t *)ipset_data_get(data,
IPSET_OPT_REVISION_MIN);
if (MAX(tmin, kmin) > MIN(tmax, kmax)) {
if (kmin > tmax)
@@ -266,7 +268,7 @@ create_type_get(struct ipset_session *session)
family == AF_INET6 ? "INET6" : "UNSPEC",
kmax, tmin);
}
/* Disable unsupported revisions */
for (match = NULL, t = typelist; t != NULL; t = t->next) {
/* Skip revisions which are unsupported by the kernel */
@@ -274,16 +276,16 @@ create_type_get(struct ipset_session *session)
continue;
if (ipset_match_typename(typename, t)
&& MATCH_FAMILY(t, family)) {
if (t->revision < kmin || t->revision > kmax)
t->kernel_check = IPSET_KERNEL_MISMATCH;
if (t->revision < kmin || t->revision > kmax)
t->kernel_check = IPSET_KERNEL_MISMATCH;
else if (match == NULL)
match = t;
}
match = t;
}
}
match->kernel_check = IPSET_KERNEL_OK;
found:
ipset_data_set(data, IPSET_OPT_TYPE, match);
return match;
}
@@ -327,7 +329,7 @@ adt_type_get(struct ipset_session *session)
return NULL;
typename = ipset_data_get(data, IPSET_OPT_TYPENAME);
revision = ipset_data_get(data, IPSET_OPT_REVISION);
revision = ipset_data_get(data, IPSET_OPT_REVISION);
family = ipset_data_family(data);
/* Check registered types */
@@ -542,7 +544,7 @@ void
ipset_cache_fini(void)
{
struct ipset *set;
while (setlist) {
set = setlist;
setlist = setlist->next;

View File

@@ -148,7 +148,7 @@ const union nf_inet_addr ip_set_netmask_map[] = {
EXPORT_SYMBOL_GPL(ip_set_netmask_map);
#undef E
#define E(a, b, c, d) \
#define E(a, b, c, d) \
{.ip6 = { (__force __be32) a, (__force __be32) b, \
(__force __be32) c, (__force __be32) d, \
} }

View File

@@ -2,7 +2,7 @@
#define _PFXLEN_H
#include <asm/byteorder.h>
#include <linux/netfilter.h>
#include <linux/netfilter.h>
#include <net/tcp.h>
/* Prefixlen maps, by Jan Engelhardt */

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <assert.h> /* assert */
@@ -70,7 +70,7 @@ static const struct ipset_errcode_table core_errcode_table[] = {
"An IPv4 address is expected, but not received" },
{ IPSET_ERR_IPADDR_IPV6, 0,
"An IPv6 address is expected, but not received" },
/* ADD specific error codes */
{ IPSET_ERR_EXIST, IPSET_CMD_ADD,
"Element cannot be added to the set: it's already added" },
@@ -157,10 +157,10 @@ ipset_errcode(struct ipset_session *session, enum ipset_cmd cmd, int errcode)
{
const struct ipset_errcode_table *table = core_errcode_table;
int i, generic;
if (errcode >= IPSET_ERR_TYPE_SPECIFIC) {
const struct ipset_type *type;
type = ipset_saved_type(session);
if (type) {
if (MATCH_TYPENAME(type->name, "bitmap:"))
@@ -174,11 +174,11 @@ ipset_errcode(struct ipset_session *session, enum ipset_cmd cmd, int errcode)
retry:
for (i = 0, generic = -1; table[i].errcode; i++) {
if (table[i].errcode == errcode
&& (table[i].cmd == cmd || table[i].cmd == 0)) {
if (table[i].cmd == 0) {
generic = i;
continue;
if (table[i].errcode == errcode &&
(table[i].cmd == cmd || table[i].cmd == 0)) {
if (table[i].cmd == 0) {
generic = i;
continue;
}
return ipset_err(session, table[i].message);
}

View File

@@ -214,8 +214,8 @@ command follows the syntax
where the current list of the methods are
\fBbitmap\fR, \fBhash\fR, and \fBlist\fR and the possible data types
are \fBip\fR, \fBnet\fR, \fBmac\fR and \fBport\fR. The dimension of a set
is equal to the number of data types in its type name.
are \fBip\fR, \fBnet\fR, \fBmac\fR, \fBport\fR and \fBiface\fR.
The dimension of a set is equal to the number of data types in its type name.
When adding, deleting or testing entries in a set, the same comma separated
data syntax must be used for the entry parameter of the commands, i.e
@@ -711,6 +711,73 @@ ipset add foo 192.168.1,80,10.0.0/24
ipset add foo 192.168.2,25,10.1.0.0/16
.IP
ipset test foo 192.168.1,80.10.0.0/24
.SS hash:net,iface
The \fBhash:net,iface\fR set type uses a hash to store different sized IP network
address and interface name pairs. Network address with zero prefix size is not
accepted.
.PP
\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
.PP
\fIADD\-ENTRY\fR := \fInetaddr\fR,[\fBphysdev\fR:]\fIiface\fR
.PP
\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
.PP
\fIDEL\-ENTRY\fR := \fInetaddr\fR,[\fBphysdev\fR:]\fIiface\fR
.PP
\fITEST\-ENTRY\fR := \fInetaddr\fR,[\fBphysdev\fR:]\fIiface\fR
.PP
where
\fInetaddr\fR := \fIip\fR[/\fIcidr\fR]
.PP
Optional \fBcreate\fR options:
.TP
\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
The protocol family of the IP addresses to be stored in the set. The default is
\fBinet\fR, i.e IPv4.
.TP
\fBhashsize\fR \fIvalue\fR
The initial hash size for the set, default is 1024. The hash size must be a power
of two, the kernel automatically rounds up non power of two hash sizes to the first
correct value.
.TP
\fBmaxelem\fR \fIvalue\fR
The maximal number of elements which can be stored in the set, default 65536.
.PP
For the \fInetaddr\fR part of the elements
see the description at the \fBhash:net\fR set type.
.PP
When adding/deleting/testing entries, if the cidr prefix parameter is not specified,
then the host prefix value is assumed. When adding/deleting entries, the exact
element is added/deleted and overlapping elements are not checked by the kernel.
When testing entries, if a host address is tested, then the kernel tries to match
the host address in the networks added to the set and reports the result accordingly.
.PP
From the \fBset\fR netfilter match point of view the searching for a match
always starts from the smallest size of netblock (most specific
prefix) to the largest one (least specific prefix) added to the set.
When adding/deleting IP
addresses to the set by the \fBSET\fR netfilter target, it will be
added/deleted by the most specific prefix which can be found in the
set, or by the host prefix value if the set is empty.
.PP
The second direction parameter of the \fBset\fR match and
\fBSET\fR target modules corresponds to the incoming/outgoing interface
: \fBsrc\fR to the incoming, while \fBdst\fR to the outgoing. When
the interface is flagged with \fBphysdev:\fR, the interface is interpreted
as the incoming/outgoing bridge port.
.PP
The lookup time grows linearly with the number of the different prefix
values added to the set.
.PP
Examples:
.IP
ipset create foo hash:net,iface
.IP
ipset add foo 192.168.0/24,eth0
.IP
ipset add foo 10.1.0.0/16,eth1
.IP
ipset test foo 192.168.0/24,eth0
.SS list:set
The \fBlist:set\fR type uses a simple list in which you can store
set names.

View File

@@ -2,8 +2,8 @@
* Patrick Schaaf (bof@bof.de)
* Copyright 2003-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <ctype.h> /* isspace */
@@ -26,12 +26,12 @@
static char program_name[] = PACKAGE;
static char program_version[] = PACKAGE_VERSION;
static struct ipset_session *session = NULL;
static uint32_t restore_line = 0;
static bool interactive = false;
static struct ipset_session *session;
static uint32_t restore_line;
static bool interactive;
static char cmdline[1024];
static char *newargv[255];
static int newargc = 0;
static int newargc;
/* The known set types: (typename, revision, family) is unique */
extern struct ipset_type ipset_bitmap_ip0;
@@ -42,6 +42,7 @@ extern struct ipset_type ipset_hash_net0;
extern struct ipset_type ipset_hash_net1;
extern struct ipset_type ipset_hash_netport1;
extern struct ipset_type ipset_hash_netport2;
extern struct ipset_type ipset_hash_netiface0;
extern struct ipset_type ipset_hash_ipport1;
extern struct ipset_type ipset_hash_ipportip1;
extern struct ipset_type ipset_hash_ipportnet1;
@@ -56,12 +57,12 @@ enum exittype {
SESSION_PROBLEM,
};
static int __attribute__((format(printf,2,3)))
static int __attribute__((format(printf, 2, 3)))
exit_error(int status, const char *msg, ...)
{
bool quiet = !interactive
&& session
&& ipset_envopt_test(session, IPSET_ENV_QUIET);
bool quiet = !interactive &&
session &&
ipset_envopt_test(session, IPSET_ENV_QUIET);
if (status && msg && !quiet) {
va_list args;
@@ -97,8 +98,8 @@ exit_error(int status, const char *msg, ...)
static int
handle_error(void)
{
if (ipset_session_warning(session)
&& !ipset_envopt_test(session, IPSET_ENV_QUIET))
if (ipset_session_warning(session) &&
!ipset_envopt_test(session, IPSET_ENV_QUIET))
fprintf(stderr, "Warning: %s\n",
ipset_session_warning(session));
if (ipset_session_error(session))
@@ -110,7 +111,7 @@ handle_error(void)
exit(OTHER_PROBLEM);
}
ipset_session_report_reset(session);
ipset_session_report_reset(session);
return -1;
}
@@ -119,16 +120,15 @@ help(void)
{
const struct ipset_commands *c;
const struct ipset_envopts *opt = ipset_envopts;
printf("%s v%s\n\n"
"Usage: %s [options] COMMAND\n\nCommands:\n",
program_name, program_version, program_name);
for (c = ipset_commands; c->cmd; c++) {
for (c = ipset_commands; c->cmd; c++)
printf("%s %s\n", c->name[0], c->help);
}
printf("\nOptions:\n");
while (opt->flag) {
if (opt->help)
printf("%s %s\n", opt->name[0], opt->help);
@@ -143,7 +143,7 @@ build_argv(char *buffer)
char *ptr;
int i;
/* Reset */
/* Reset */
for (i = 1; i < newargc; i++)
newargv[i] = NULL;
newargc = 1;
@@ -172,7 +172,7 @@ restore(char *argv0)
{
int ret = 0;
char *c;
/* Initialize newargv/newargc */
newargc = 0;
newargv[newargc++] = argv0;
@@ -192,7 +192,7 @@ restore(char *argv0)
}
/* Build faked argv, argc */
build_argv(c);
/* Execute line */
ret = parse_commandline(newargc, newargv);
if (ret < 0)
@@ -212,7 +212,7 @@ call_parser(int *argc, char *argv[], const struct ipset_arg *args)
int ret = 0;
const struct ipset_arg *arg;
const char *optstr;
/* Currently CREATE and ADT may have got additional arguments */
if (!args && *argc > 1)
goto err_unknown;
@@ -236,7 +236,8 @@ call_parser(int *argc, char *argv[], const struct ipset_arg *args)
/* Fall through */
case IPSET_OPTIONAL_ARG:
if (*argc >= 2) {
ret = ipset_call_parser(session, arg, argv[1]);
ret = ipset_call_parser(session,
arg, argv[1]);
if (ret < 0)
return ret;
ipset_shift_argv(argc, argv, 1);
@@ -262,7 +263,7 @@ err_unknown:
static enum ipset_adt
cmd2cmd(int cmd)
{
switch(cmd) {
switch (cmd) {
case IPSET_CMD_ADD:
return IPSET_ADD;
case IPSET_CMD_DEL:
@@ -342,15 +343,15 @@ check_allowed(const struct ipset_type *type, enum ipset_cmd command)
? IPSET_CREATE_FLAGS : IPSET_ADT_FLAGS;
const struct ipset_arg *arg = type->args[cmd];
enum ipset_opt i;
/* Range can be expressed by ip/cidr or from-to */
if (allowed & IPSET_FLAG(IPSET_OPT_IP_TO))
allowed |= IPSET_FLAG(IPSET_OPT_CIDR);
for (i = IPSET_OPT_IP; i < IPSET_OPT_FLAGS; i++) {
if (!(cmdflags & IPSET_FLAG(i))
|| (allowed & IPSET_FLAG(i))
|| !(flags & IPSET_FLAG(i)))
if (!(cmdflags & IPSET_FLAG(i)) ||
(allowed & IPSET_FLAG(i)) ||
!(flags & IPSET_FLAG(i)))
continue;
/* Not allowed element-expressions */
switch (i) {
@@ -358,19 +359,22 @@ check_allowed(const struct ipset_type *type, enum ipset_cmd command)
exit_error(OTHER_PROBLEM,
"IP/CIDR range is not allowed in command %s "
"with set type %s and family %s",
cmd2name(command), type->name, session_family());
cmd2name(command), type->name,
session_family());
return;
case IPSET_OPT_IP_TO:
exit_error(OTHER_PROBLEM,
"FROM-TO IP range is not allowed in command %s "
"with set type %s and family %s",
cmd2name(command), type->name, session_family());
cmd2name(command), type->name,
session_family());
return;
case IPSET_OPT_PORT_TO:
exit_error(OTHER_PROBLEM,
"FROM-TO port range is not allowed in command %s "
"with set type %s and family %s",
cmd2name(command), type->name, session_family());
cmd2name(command), type->name,
session_family());
return;
default:
break;
@@ -390,7 +394,8 @@ check_allowed(const struct ipset_type *type, enum ipset_cmd command)
"%s parameter is not allowed in command %s "
"with set type %s and family %s",
arg->name[0],
cmd2name(command), type->name, session_family());
cmd2name(command), type->name,
session_family());
return;
}
exit_error(OTHER_PROBLEM,
@@ -405,7 +410,7 @@ static const struct ipset_type *
type_find(const char *name)
{
const struct ipset_type *t = ipset_types();
while (t) {
if (ipset_match_typename(name, t))
return t;
@@ -476,10 +481,10 @@ parse_commandline(int argc, char *argv[])
if (!ipset_match_cmd(argv[1], command->name))
continue;
if (restore_line != 0
&& (command->cmd == IPSET_CMD_RESTORE
|| command->cmd == IPSET_CMD_VERSION
|| command->cmd == IPSET_CMD_HELP))
if (restore_line != 0 &&
(command->cmd == IPSET_CMD_RESTORE ||
command->cmd == IPSET_CMD_VERSION ||
command->cmd == IPSET_CMD_HELP))
return exit_error(PARAMETER_PROBLEM,
"Command `%s' is invalid "
"in restore mode.",
@@ -564,9 +569,9 @@ parse_commandline(int argc, char *argv[])
case IPSET_CMD_HELP:
help();
if (interactive
|| !ipset_envopt_test(session, IPSET_ENV_QUIET)) {
if (arg0) {
if (interactive ||
!ipset_envopt_test(session, IPSET_ENV_QUIET)) {
if (arg0) {
/* Type-specific help, without kernel checking */
type = type_find(arg0);
if (!type)
@@ -596,7 +601,7 @@ parse_commandline(int argc, char *argv[])
printf(" %s\n", type->name);
type = type->next;
}
}
}
}
if (interactive)
return 0;
@@ -606,7 +611,7 @@ parse_commandline(int argc, char *argv[])
default:
break;
}
/* Forth: parse command args and issue the command */
switch (cmd) {
case IPSET_CMD_CREATE:
@@ -629,11 +634,11 @@ parse_commandline(int argc, char *argv[])
return handle_error();
else if (ret)
return ret;
/* Check mandatory, then allowed options */
check_mandatory(type, cmd);
check_allowed(type, cmd);
break;
case IPSET_CMD_DESTROY:
case IPSET_CMD_FLUSH:
@@ -677,22 +682,22 @@ parse_commandline(int argc, char *argv[])
type = ipset_type_get(session, cmd);
if (type == NULL)
return handle_error();
ret = ipset_parse_elem(session, type->last_elem_optional, arg1);
if (ret < 0)
return handle_error();
/* Parse additional ADT options */
ret = call_parser(&argc, argv, type->args[cmd2cmd(cmd)]);
if (ret < 0)
return handle_error();
else if (ret)
return ret;
/* Check mandatory, then allowed options */
check_mandatory(type, cmd);
check_allowed(type, cmd);
break;
default:
break;
@@ -729,6 +734,7 @@ main(int argc, char *argv[])
ipset_type_add(&ipset_hash_net1);
ipset_type_add(&ipset_hash_netport1);
ipset_type_add(&ipset_hash_netport2);
ipset_type_add(&ipset_hash_netiface0);
ipset_type_add(&ipset_hash_ipport1);
ipset_type_add(&ipset_hash_ipportip1);
ipset_type_add(&ipset_hash_ipportnet1);
@@ -742,8 +748,8 @@ main(int argc, char *argv[])
"Cannot initialize ipset session, aborting.");
ret = parse_commandline(argc, argv);
ipset_session_fini(session);
return ret;
}

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <libipset/data.h> /* IPSET_OPT_* */
@@ -37,7 +37,7 @@ static const struct ipset_arg bitmap_ip_create_args[] = {
.parse = ipset_parse_net,
},
{ },
};
};
static const struct ipset_arg bitmap_ip_add_args[] = {
{ .name = { "timeout", NULL },
@@ -45,7 +45,7 @@ static const struct ipset_arg bitmap_ip_add_args[] = {
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ },
};
};
static const char bitmap_ip_usage[] =
"create SETNAME bitmap:ip range IP/CIDR|FROM-TO\n"
@@ -62,8 +62,8 @@ struct ipset_type ipset_bitmap_ip0 = {
.revision = 0,
.family = AF_INET,
.dimension = IPSET_DIM_ONE,
.elem = {
[IPSET_DIM_ONE] = {
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_ip,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <libipset/data.h> /* IPSET_OPT_* */
@@ -33,7 +33,7 @@ static const struct ipset_arg bitmap_ipmac_create_args[] = {
.parse = ipset_parse_net,
},
{ },
};
};
static const struct ipset_arg bitmap_ipmac_add_args[] = {
{ .name = { "timeout", NULL },
@@ -41,7 +41,7 @@ static const struct ipset_arg bitmap_ipmac_add_args[] = {
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ },
};
};
static const char bitmap_ipmac_usage[] =
"create SETNAME bitmap:ip,mac range IP/CIDR|FROM-TO\n"
@@ -60,13 +60,13 @@ struct ipset_type ipset_bitmap_ipmac0 = {
.family = AF_INET,
.dimension = IPSET_DIM_TWO,
.last_elem_optional = true,
.elem = {
[IPSET_DIM_ONE] = {
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_single_ip,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP
},
[IPSET_DIM_TWO] = {
[IPSET_DIM_TWO] = {
.parse = ipset_parse_ether,
.print = ipset_print_ether,
.opt = IPSET_OPT_ETHER

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <libipset/data.h> /* IPSET_OPT_* */
@@ -29,7 +29,7 @@ static const struct ipset_arg bitmap_port_create_args[] = {
.parse = ipset_parse_single_tcp_port,
},
{ },
};
};
static const struct ipset_arg bitmap_port_add_args[] = {
{ .name = { "timeout", NULL },
@@ -37,7 +37,7 @@ static const struct ipset_arg bitmap_port_add_args[] = {
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ },
};
};
static const char bitmap_port_usage[] =
"create SETNAME bitmap:port range FROM-TO\n"
@@ -53,8 +53,8 @@ struct ipset_type ipset_bitmap_port0 = {
.revision = 0,
.family = AF_UNSPEC,
.dimension = IPSET_DIM_ONE,
.elem = {
[IPSET_DIM_ONE] = {
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_tcp_port,
.print = ipset_print_port,
.opt = IPSET_OPT_PORT

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <libipset/data.h> /* IPSET_OPT_* */
@@ -63,7 +63,7 @@ static const struct ipset_arg hash_ip_add_args[] = {
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ },
};
};
static const char hash_ip_usage[] =
"create SETNAME hash:ip\n"
@@ -85,8 +85,8 @@ struct ipset_type ipset_hash_ip0 = {
.revision = 0,
.family = AF_INET46,
.dimension = IPSET_DIM_ONE,
.elem = {
[IPSET_DIM_ONE] = {
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_ip4_single6,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <libipset/data.h> /* IPSET_OPT_* */
@@ -60,7 +60,7 @@ static const struct ipset_arg hash_ipport_create_args[] = {
.parse = ipset_parse_ignored,
},
{ },
};
};
static const struct ipset_arg hash_ipport_add_args[] = {
{ .name = { "timeout", NULL },
@@ -68,7 +68,7 @@ static const struct ipset_arg hash_ipport_add_args[] = {
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ },
};
};
static const char hash_ipport1_usage[] =
"create SETNAME hash:ip,port\n"
@@ -91,13 +91,13 @@ struct ipset_type ipset_hash_ipport1 = {
.revision = 1,
.family = AF_INET46,
.dimension = IPSET_DIM_TWO,
.elem = {
[IPSET_DIM_ONE] = {
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_ip4_single6,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP
},
[IPSET_DIM_TWO] = {
[IPSET_DIM_TWO] = {
.parse = ipset_parse_proto_port,
.print = ipset_print_proto_port,
.opt = IPSET_OPT_PORT

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <libipset/data.h> /* IPSET_OPT_* */
@@ -60,7 +60,7 @@ static const struct ipset_arg hash_ipportip_create_args[] = {
.parse = ipset_parse_ignored,
},
{ },
};
};
static const struct ipset_arg hash_ipportip_add_args[] = {
{ .name = { "timeout", NULL },
@@ -68,7 +68,7 @@ static const struct ipset_arg hash_ipportip_add_args[] = {
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ },
};
};
static const char hash_ipportip1_usage[] =
"create SETNAME hash:ip,port,ip\n"
@@ -91,18 +91,18 @@ struct ipset_type ipset_hash_ipportip1 = {
.revision = 1,
.family = AF_INET46,
.dimension = IPSET_DIM_THREE,
.elem = {
[IPSET_DIM_ONE] = {
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_ip4_single6,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP
},
[IPSET_DIM_TWO] = {
[IPSET_DIM_TWO] = {
.parse = ipset_parse_proto_port,
.print = ipset_print_proto_port,
.opt = IPSET_OPT_PORT
},
[IPSET_DIM_THREE] = {
[IPSET_DIM_THREE] = {
.parse = ipset_parse_single_ip,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP2

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <libipset/data.h> /* IPSET_OPT_* */
@@ -60,7 +60,7 @@ static const struct ipset_arg hash_ipportnet_create_args[] = {
.parse = ipset_parse_ignored,
},
{ },
};
};
static const struct ipset_arg hash_ipportnet_add_args[] = {
{ .name = { "timeout", NULL },
@@ -68,7 +68,7 @@ static const struct ipset_arg hash_ipportnet_add_args[] = {
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ },
};
};
static const char hash_ipportnet1_usage[] =
"create SETNAME hash:ip,port,net\n"
@@ -92,18 +92,18 @@ struct ipset_type ipset_hash_ipportnet1 = {
.revision = 1,
.family = AF_INET46,
.dimension = IPSET_DIM_THREE,
.elem = {
[IPSET_DIM_ONE] = {
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_ip4_single6,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP
},
[IPSET_DIM_TWO] = {
[IPSET_DIM_TWO] = {
.parse = ipset_parse_proto_port,
.print = ipset_print_proto_port,
.opt = IPSET_OPT_PORT
},
[IPSET_DIM_THREE] = {
[IPSET_DIM_THREE] = {
.parse = ipset_parse_ipnet,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP2
@@ -182,18 +182,18 @@ struct ipset_type ipset_hash_ipportnet2 = {
.revision = 2,
.family = AF_INET46,
.dimension = IPSET_DIM_THREE,
.elem = {
[IPSET_DIM_ONE] = {
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_ip4_single6,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP
},
[IPSET_DIM_TWO] = {
[IPSET_DIM_TWO] = {
.parse = ipset_parse_proto_port,
.print = ipset_print_proto_port,
.opt = IPSET_OPT_PORT
},
[IPSET_DIM_THREE] = {
[IPSET_DIM_THREE] = {
.parse = ipset_parse_ip4_net6,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP2

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <libipset/data.h> /* IPSET_OPT_* */
@@ -47,7 +47,7 @@ static const struct ipset_arg hash_net_create_args[] = {
.parse = ipset_parse_ignored, .print = ipset_print_number,
},
{ },
};
};
static const struct ipset_arg hash_net_add_args[] = {
{ .name = { "timeout", NULL },
@@ -55,7 +55,7 @@ static const struct ipset_arg hash_net_add_args[] = {
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ },
};
};
static const char hash_net0_usage[] =
"create SETNAME hash:net\n"
@@ -75,8 +75,8 @@ struct ipset_type ipset_hash_net0 = {
.revision = 0,
.family = AF_INET46,
.dimension = IPSET_DIM_ONE,
.elem = {
[IPSET_DIM_ONE] = {
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_ipnet,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP
@@ -127,8 +127,8 @@ struct ipset_type ipset_hash_net1 = {
.revision = 1,
.family = AF_INET46,
.dimension = IPSET_DIM_ONE,
.elem = {
[IPSET_DIM_ONE] = {
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_ip4_net6,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP

View File

@@ -0,0 +1,120 @@
/* Copyright 2011 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <libipset/data.h> /* IPSET_OPT_* */
#include <libipset/parse.h> /* parser functions */
#include <libipset/print.h> /* printing functions */
#include <libipset/ui.h> /* ipset_port_usage */
#include <libipset/types.h> /* prototypes */
/* Parse commandline arguments */
static const struct ipset_arg hash_netiface_create_args[] = {
{ .name = { "family", NULL },
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
.parse = ipset_parse_family, .print = ipset_print_family,
},
/* Alias: family inet */
{ .name = { "-4", NULL },
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
.parse = ipset_parse_family,
},
/* Alias: family inet6 */
{ .name = { "-6", NULL },
.has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
.parse = ipset_parse_family,
},
{ .name = { "hashsize", NULL },
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ .name = { "maxelem", NULL },
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ .name = { "timeout", NULL },
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ },
};
static const struct ipset_arg hash_netiface_add_args[] = {
{ .name = { "timeout", NULL },
.has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ },
};
static const char hash_netiface_usage[] =
"create SETNAME hash:net,iface\n"
" [family inet|inet6]\n"
" [hashsize VALUE] [maxelem VALUE]\n"
" [timeout VALUE]\n"
"add SETNAME IP[/CIDR]|FROM-TO,[physdev:]IFACE [timeout VALUE]\n"
"del SETNAME IP[/CIDR]|FROM-TO,[physdev:]IFACE\n"
"test SETNAME IP[/CIDR],[physdev:]IFACE\n\n"
"where depending on the INET family\n"
" IP is a valid IPv4 or IPv6 address (or hostname),\n"
" CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
" Adding/deleting multiple elements with IPv4 is supported.\n";
struct ipset_type ipset_hash_netiface0 = {
.name = "hash:net,iface",
.alias = { "netifacehash", NULL },
.revision = 0,
.family = AF_INET46,
.dimension = IPSET_DIM_TWO,
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_ip4_net6,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP
},
[IPSET_DIM_TWO] = {
.parse = ipset_parse_iface,
.print = ipset_print_iface,
.opt = IPSET_OPT_IFACE
},
},
.args = {
[IPSET_CREATE] = hash_netiface_create_args,
[IPSET_ADD] = hash_netiface_add_args,
},
.mandatory = {
[IPSET_CREATE] = 0,
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
| IPSET_FLAG(IPSET_OPT_IFACE),
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
| IPSET_FLAG(IPSET_OPT_IFACE),
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
| IPSET_FLAG(IPSET_OPT_IFACE),
},
.full = {
[IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
| IPSET_FLAG(IPSET_OPT_MAXELEM)
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
[IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
| IPSET_FLAG(IPSET_OPT_CIDR)
| IPSET_FLAG(IPSET_OPT_IP_TO)
| IPSET_FLAG(IPSET_OPT_IFACE)
| IPSET_FLAG(IPSET_OPT_PHYSDEV)
| IPSET_FLAG(IPSET_OPT_TIMEOUT),
[IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
| IPSET_FLAG(IPSET_OPT_CIDR)
| IPSET_FLAG(IPSET_OPT_IP_TO)
| IPSET_FLAG(IPSET_OPT_IFACE)
| IPSET_FLAG(IPSET_OPT_PHYSDEV),
[IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
| IPSET_FLAG(IPSET_OPT_CIDR)
| IPSET_FLAG(IPSET_OPT_IP_TO)
| IPSET_FLAG(IPSET_OPT_IFACE)
| IPSET_FLAG(IPSET_OPT_PHYSDEV),
},
.usage = hash_netiface_usage,
};

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <libipset/data.h> /* IPSET_OPT_* */
@@ -39,7 +39,7 @@ static const struct ipset_arg hash_netport_create_args[] = {
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ },
};
};
static const struct ipset_arg hash_netport_add_args[] = {
{ .name = { "timeout", NULL },
@@ -47,7 +47,7 @@ static const struct ipset_arg hash_netport_add_args[] = {
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ },
};
};
static const char hash_netport1_usage[] =
"create SETNAME hash:net,port\n"
@@ -69,13 +69,13 @@ struct ipset_type ipset_hash_netport1 = {
.revision = 1,
.family = AF_INET46,
.dimension = IPSET_DIM_TWO,
.elem = {
[IPSET_DIM_ONE] = {
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_ipnet,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP
},
[IPSET_DIM_TWO] = {
[IPSET_DIM_TWO] = {
.parse = ipset_parse_proto_port,
.print = ipset_print_proto_port,
.opt = IPSET_OPT_PORT
@@ -143,13 +143,13 @@ struct ipset_type ipset_hash_netport2 = {
.revision = 2,
.family = AF_INET46,
.dimension = IPSET_DIM_TWO,
.elem = {
[IPSET_DIM_ONE] = {
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_ip4_net6,
.print = ipset_print_ip,
.opt = IPSET_OPT_IP
},
[IPSET_DIM_TWO] = {
[IPSET_DIM_TWO] = {
.parse = ipset_parse_proto_port,
.print = ipset_print_proto_port,
.opt = IPSET_OPT_PORT

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <libipset/data.h> /* IPSET_OPT_* */
@@ -20,7 +20,7 @@ static const struct ipset_arg list_set_create_args[] = {
.parse = ipset_parse_uint32, .print = ipset_print_number,
},
{ },
};
};
static const struct ipset_arg list_set_adt_args[] = {
{ .name = { "timeout", NULL },
@@ -36,7 +36,7 @@ static const struct ipset_arg list_set_adt_args[] = {
.parse = ipset_parse_after,
},
{ },
};
};
static const char list_set_usage[] =
"create SETNAME list:set\n"
@@ -52,8 +52,8 @@ struct ipset_type ipset_list_set0 = {
.revision = 0,
.family = AF_UNSPEC,
.dimension = IPSET_DIM_ONE,
.elem = {
[IPSET_DIM_ONE] = {
.elem = {
[IPSET_DIM_ONE] = {
.parse = ipset_parse_setname,
.print = ipset_print_name,
.opt = IPSET_OPT_NAME

View File

@@ -1,7 +1,7 @@
/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <assert.h> /* assert */
@@ -35,91 +35,91 @@ const struct ipset_commands ipset_commands[] = {
.name = { "add", NULL },
.has_arg = IPSET_MANDATORY_ARG2,
.help = "SETNAME ENTRY\n"
" Add entry to the named set",
" Add entry to the named set",
},
{ /* d[el], --del, -D */
.cmd = IPSET_CMD_DEL,
.name = { "del", NULL },
.has_arg = IPSET_MANDATORY_ARG2,
.help = "SETNAME ENTRY\n"
" Delete entry from the named set",
" Delete entry from the named set",
},
{ /* t[est], --test, -T */
.cmd = IPSET_CMD_TEST,
.name = { "test", NULL },
.has_arg = IPSET_MANDATORY_ARG2,
.help = "SETNAME ENTRY\n"
" Test entry in the named set",
" Test entry in the named set",
},
{ /* des[troy], --destroy, x, -X */
.cmd = IPSET_CMD_DESTROY,
.name = { "destroy", "x" },
.has_arg = IPSET_OPTIONAL_ARG,
.help = "[SETNAME]\n"
" Destroy a named set or all sets",
" Destroy a named set or all sets",
},
{ /* l[ist], --list, -L */
.cmd = IPSET_CMD_LIST,
.name = { "list", NULL },
.has_arg = IPSET_OPTIONAL_ARG,
.help = "[SETNAME]\n"
" List the entries of a named set or all sets",
" List the entries of a named set or all sets",
},
{ /* s[save], --save, -S */
.cmd = IPSET_CMD_SAVE,
.name = { "save", NULL },
.has_arg = IPSET_OPTIONAL_ARG,
.help = "[SETNAME]\n"
" Save the named set or all sets to stdout",
" Save the named set or all sets to stdout",
},
{ /* r[estore], --restore, -R */
.cmd = IPSET_CMD_RESTORE,
.name = { "restore", NULL },
.has_arg = IPSET_NO_ARG,
.help = "\n"
" Restore a saved state",
" Restore a saved state",
},
{ /* f[lush], --flush, -F */
.cmd = IPSET_CMD_FLUSH,
.name = { "flush", NULL },
.has_arg = IPSET_OPTIONAL_ARG,
.help = "[SETNAME]\n"
" Flush a named set or all sets",
" Flush a named set or all sets",
},
{ /* ren[ame], --rename, e, -E */
.cmd = IPSET_CMD_RENAME,
.name = { "rename", "e" },
.has_arg = IPSET_MANDATORY_ARG2,
.help = "FROM-SETNAME TO-SETNAME\n"
" Rename two sets",
" Rename two sets",
},
{ /* sw[ap], --swap, w, -W */
.cmd = IPSET_CMD_SWAP,
.name = { "swap", "w" },
.has_arg = IPSET_MANDATORY_ARG2,
.help = "FROM-SETNAME TO-SETNAME\n"
" Swap the contect of two existing sets",
" Swap the contect of two existing sets",
},
{ /* h[elp, --help, -H */
.cmd = IPSET_CMD_HELP,
.name = { "help", NULL },
.has_arg = IPSET_OPTIONAL_ARG,
.help = "[TYPENAME]\n"
" Print help, and settype specific help",
" Print help, and settype specific help",
},
{ /* v[ersion], --version, -V */
.cmd = IPSET_CMD_VERSION,
.name = { "version", NULL },
.has_arg = IPSET_NO_ARG,
.help = "\n"
" Print version information",
" Print version information",
},
{ /* q[uit] */
.cmd = IPSET_CMD_QUIT,
.name = { "quit", NULL },
.has_arg = IPSET_NO_ARG,
.help = "\n"
" Quit interactive mode",
" Quit interactive mode",
},
{ },
};
@@ -149,8 +149,9 @@ ipset_match_cmd(const char *arg, const char * const name[])
return true;
else if (len != 1)
return false;
else return tolower(arg[0]) == name[0][0] ||
(name[1] != NULL && tolower(arg[0]) == name[1][0]);
else
return tolower(arg[0]) == name[0][0] ||
(name[1] != NULL && tolower(arg[0]) == name[1][0]);
}
const struct ipset_envopts ipset_envopts[] = {
@@ -158,47 +159,47 @@ const struct ipset_envopts ipset_envopts[] = {
.has_arg = IPSET_MANDATORY_ARG, .flag = IPSET_OPT_MAX,
.parse = ipset_parse_output,
.help = "plain|save|xml\n"
" Specify output mode for listing sets.\n"
" Default value for \"list\" command is mode \"plain\"\n"
" and for \"save\" command is mode \"save\".",
" Specify output mode for listing sets.\n"
" Default value for \"list\" command is mode \"plain\"\n"
" and for \"save\" command is mode \"save\".",
},
{ .name = { "-s", "-sorted" },
.parse = ipset_envopt_parse,
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_SORTED,
.help = "\n"
" Print elements sorted (if supported by the set type).",
" Print elements sorted (if supported by the set type).",
},
{ .name = { "-q", "-quiet" },
.parse = ipset_envopt_parse,
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_QUIET,
.help = "\n"
" Suppress any notice or warning message.",
" Suppress any notice or warning message.",
},
{ .name = { "-r", "-resolve" },
.parse = ipset_envopt_parse,
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_RESOLVE,
.help = "\n"
" Try to resolve IP addresses in the output (slow!)",
" Try to resolve IP addresses in the output (slow!)",
},
{ .name = { "-!", "-exist" },
.parse = ipset_envopt_parse,
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_EXIST,
.help = "\n"
" Ignore errors when creating already created sets,\n"
" when adding already existing elements\n"
" Ignore errors when creating already created sets,\n"
" when adding already existing elements\n"
" or when deleting non-existing elements.",
},
{ .name = { "-n", "-name" },
.parse = ipset_envopt_parse,
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_LIST_SETNAME,
.help = "\n"
" When listing, list just setnames from kernel.\n",
" When listing, list just setnames from kernel.\n",
},
{ .name = { "-t", "-terse" },
.parse = ipset_envopt_parse,
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_LIST_HEADER,
.help = "\n"
" When listing, list setnames and set headers\n"
" When listing, list setnames and set headers\n"
" from kernel only.",
},
{ },
@@ -210,13 +211,13 @@ ipset_match_option(const char *arg, const char * const name[])
{
assert(arg);
assert(name && name[0]);
/* Skip two leading dashes */
if (arg[0] == '-' && arg[1] == '-')
arg++, arg++;
return STREQ(arg, name[0])
|| (name[1] != NULL && STREQ(arg, name[1]));
return STREQ(arg, name[0]) ||
(name[1] != NULL && STREQ(arg, name[1]));
}
/* Strict envopt matching */
@@ -225,13 +226,13 @@ ipset_match_envopt(const char *arg, const char * const name[])
{
assert(arg);
assert(name && name[0]);
/* Skip one leading dash */
if (arg[0] == '-' && arg[1] == '-')
arg++;
return STREQ(arg, name[0])
|| (name[1] != NULL && STREQ(arg, name[1]));
return STREQ(arg, name[0]) ||
(name[1] != NULL && STREQ(arg, name[1]));
}
/**
@@ -247,19 +248,18 @@ void
ipset_shift_argv(int *argc, char *argv[], int from)
{
int i;
assert(*argc >= from + 1);
for (i = from + 1; i <= *argc; i++) {
for (i = from + 1; i <= *argc; i++)
argv[i-1] = argv[i];
}
(*argc)--;
return;
}
/**
* ipset_port_usage - prints the usage for the port parameter
*
*
* Print the usage for the port parameter to stdout.
*/
void

View File

@@ -37,7 +37,7 @@ match_set(ip_set_id_t index, const struct sk_buff *skb,
return inv;
}
#define ADT_OPT(n, f, d, fs, cfs, t) \
#define ADT_OPT(n, f, d, fs, cfs, t) \
const struct ip_set_adt_opt n = { \
.family = f, \
.dim = d, \