summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/data.c14
-rw-r--r--lib/debug.c1
-rw-r--r--lib/parse.c35
-rw-r--r--lib/print.c43
-rw-r--r--lib/session.c6
5 files changed, 98 insertions, 1 deletions
diff --git a/lib/data.c b/lib/data.c
index 1541728..9663efb 100644
--- a/lib/data.c
+++ b/lib/data.c
@@ -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[] = {