diff options
author | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2011-05-30 17:48:01 +0200 |
---|---|---|
committer | Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 2011-05-30 21:30:10 +0200 |
commit | 418a3a4f4d4e38abd1d691f81f2445590f02ecaf (patch) | |
tree | a41ed16b366c854786eea8f3da5c80fa50636dc6 /lib | |
parent | 4e21d6b5ce623f7601a872b94f3b88105356e2d3 (diff) |
hash:net,iface type introduced
The hash:net,iface type makes possible to store network address and
interface name pairs in a set. It's mostly suitable for egress
and ingress filtering. Examples:
# ipset create test hash:net,iface
# ipset add test 192.168.0.0/16,eth0
# ipset add test 192.168.0.0/24,eth1
Diffstat (limited to 'lib')
-rw-r--r-- | lib/data.c | 14 | ||||
-rw-r--r-- | lib/debug.c | 1 | ||||
-rw-r--r-- | lib/parse.c | 35 | ||||
-rw-r--r-- | lib/print.c | 43 | ||||
-rw-r--r-- | lib/session.c | 6 |
5 files changed, 98 insertions, 1 deletions
@@ -7,6 +7,7 @@ #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 */ @@ -72,6 +73,7 @@ struct ipset_data { char ether[ETH_ALEN]; char name[IPSET_MAXNAMELEN]; char nameref[IPSET_MAXNAMELEN]; + char iface[IFNAMSIZ]; } adt; }; }; @@ -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; @@ -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; diff --git a/lib/debug.c b/lib/debug.c index 174567d..5b97e6e 100644 --- a/lib/debug.c +++ b/lib/debug.c @@ -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 diff --git a/lib/parse.c b/lib/parse.c index 091fc6d..3d2a12b 100644 --- a/lib/parse.c +++ b/lib/parse.c @@ -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() */ @@ -1395,6 +1396,40 @@ ipset_parse_typename(struct ipset_session *session, } /** + * 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 * @opt: option kind of the data diff --git a/lib/print.c b/lib/print.c index 66b9c1a..bcccd3f 100644 --- a/lib/print.c +++ b/lib/print.c @@ -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_* */ @@ -444,6 +445,45 @@ ipset_print_port(char *buf, unsigned int len, } /** + * 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 * @len: length of available buffer space @@ -731,6 +771,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: diff --git a/lib/session.c b/lib/session.c index c03ed5d..93d33ff 100644 --- a/lib/session.c +++ b/lib/session.c @@ -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_* */ @@ -473,6 +474,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[] = { |