aboutgitcodelistschat:MatrixIRC
path: root/cooker
diff options
context:
space:
mode:
Diffstat (limited to 'cooker')
-rw-r--r--cooker/call.c10
-rw-r--r--cooker/calls/net.c92
-rw-r--r--cooker/emit.c52
-rw-r--r--cooker/emit.h7
-rw-r--r--cooker/match.c169
5 files changed, 270 insertions, 60 deletions
diff --git a/cooker/call.c b/cooker/call.c
index dbdc52b..19a7b7e 100644
--- a/cooker/call.c
+++ b/cooker/call.c
@@ -77,8 +77,8 @@ static union value parse_metadata(struct gluten_ctx *g, struct field *f,
} else if ((*base_offset)->type == OFFSET_NULL || (f->flags & WBUF)) {
**base_offset = tag_offset;
} else if (f->flags & MASK || add) {
- emit_bitwise(g, f->type, BITWISE_OR, offset, offset,
- tag_offset);
+ emit_bitwise(g, f->type, NULL, BITWISE_OR,
+ offset, offset, tag_offset);
} else {
emit_copy_field(g, f, offset, tag_offset);
}
@@ -337,6 +337,9 @@ bool arg_needs_temp(struct field *f, int pos, JSON_Value *jvalue,
if (json_object_get_string(tmp, "set"))
return true;
+ if (json_object_get_string(tmp, "get") && f->flags & FD)
+ return true;
+
if (level)
return true;
@@ -603,6 +606,9 @@ void handle_calls(struct gluten_ctx *g, JSON_Value *value)
}
name = json_object_get_name(obj, n);
+ if (!name)
+ continue;
+
value = json_object_get_value_at(obj, n);
args = json_object_get_object(obj, name);
diff --git a/cooker/calls/net.c b/cooker/calls/net.c
index 94b13cd..0688467 100644
--- a/cooker/calls/net.c
+++ b/cooker/calls/net.c
@@ -65,22 +65,23 @@ static struct num socket_flags[] = {
};
static struct num protocols[] = {
- { "ip", IPPROTO_IP },
- { "icmp", IPPROTO_ICMP },
- { "igmp", IPPROTO_IGMP },
- { "tcp", IPPROTO_TCP },
- { "udp", IPPROTO_UDP },
- { "ipv6", IPPROTO_IPV6 },
- { "gre", IPPROTO_GRE },
- { "esp", IPPROTO_ESP },
- { "ah", IPPROTO_AH },
- { "sctp", IPPROTO_SCTP },
- { "udplite", IPPROTO_UDPLITE },
- { "mpls", IPPROTO_MPLS },
- { "raw", IPPROTO_RAW },
- { "mptcp", IPPROTO_MPTCP },
+ { "ip", IPPROTO_IP },
+ { "icmp", IPPROTO_ICMP },
+ { "igmp", IPPROTO_IGMP },
+ { "tcp", IPPROTO_TCP },
+ { "udp", IPPROTO_UDP },
+ { "ipv6", IPPROTO_IPV6 },
+ { "gre", IPPROTO_GRE },
+ { "esp", IPPROTO_ESP },
+ { "ah", IPPROTO_AH },
+ { "sctp", IPPROTO_SCTP },
+ { "udplite", IPPROTO_UDPLITE },
+ { "mpls", IPPROTO_MPLS },
+ { "raw", IPPROTO_RAW },
+ { "mptcp", IPPROTO_MPTCP },
- { "nl_route", NETLINK_ROUTE },
+ { "nl_route", NETLINK_ROUTE },
+ { "nl_netfilter", NETLINK_NETFILTER },
{ 0 },
};
@@ -261,7 +262,7 @@ static struct num send_flags[] = {
static struct arg send_args[] = {
{ 0,
{
- "fd", INT, 0,
+ "fd", INT, FD,
0,
0,
{ 0 },
@@ -297,7 +298,7 @@ static struct arg send_args[] = {
static struct arg sendto_args[] = {
{ 0,
{
- "fd", INT, 0,
+ "fd", INT, FD,
0,
0,
{ 0 },
@@ -346,7 +347,7 @@ static struct arg sendto_args[] = {
{ 0 }
};
-static struct select sendmsg_name_select = {
+static struct select msg_name_select = {
&connect_family, { .d_num = connect_addr_select_family }
};
@@ -355,13 +356,13 @@ static struct field sendmsg_msghdr[] = {
"name", SELECT, 0,
offsetof(struct msghdr, msg_name),
sizeof(struct sockaddr_storage),
- { .d_select = &sendmsg_name_select },
+ { .d_select = &msg_name_select },
},
{
"namelen", LONG, SIZE,
offsetof(struct msghdr, msg_namelen),
0,
- { .d_size = (intptr_t)&sendmsg_name_select },
+ { .d_size = (intptr_t)&msg_name_select },
},
{
"iov", STRING, WBUF | IOV,
@@ -400,7 +401,7 @@ static struct field sendmsg_msghdr[] = {
static struct arg sendmsg_args[] = {
{ 0,
{
- "fd", INT, 0,
+ "fd", INT, FD,
0,
0,
{ 0 },
@@ -425,6 +426,53 @@ static struct arg sendmsg_args[] = {
{ 0 }
};
+static struct field recvmsg_msghdr[] = {
+ {
+ "name", SELECT, 0,
+ offsetof(struct msghdr, msg_name),
+ sizeof(struct sockaddr_storage),
+ { .d_select = &msg_name_select },
+ },
+ {
+ "namelen", LONG, SIZE,
+ offsetof(struct msghdr, msg_namelen),
+ 0,
+ { .d_size = (intptr_t)&msg_name_select },
+ },
+ {
+ "iov", STRING, RBUF | IOV,
+ offsetof(struct msghdr, msg_iov),
+ BUFSIZ,
+ { .d_iovlen = offsetof(struct msghdr, msg_iovlen) -
+ offsetof(struct msghdr, msg_iov) },
+ },
+ {
+ "iovlen", LONG, 0,
+ offsetof(struct msghdr, msg_iovlen),
+ 0,
+ { 0 },
+ },
+ {
+ "control", STRING, 0,
+ offsetof(struct msghdr, msg_control),
+ BUFSIZ,
+ { 0 },
+ },
+ {
+ "controllen", LONG, SIZE,
+ offsetof(struct msghdr, msg_controllen),
+ 0,
+ { 0 },
+ },
+ {
+ "flags", INT, 0,
+ offsetof(struct msghdr, msg_flags),
+ 0,
+ { 0 },
+ },
+ { 0 }
+};
+
static struct arg recvmsg_args[] = {
{ 0,
{
@@ -439,7 +487,7 @@ static struct arg recvmsg_args[] = {
"msg", STRUCT, 0,
0,
sizeof(struct msghdr),
- { .d_struct = sendmsg_msghdr },
+ { .d_struct = recvmsg_msghdr },
},
},
{ 2,
diff --git a/cooker/emit.c b/cooker/emit.c
index 33355b6..7d13a02 100644
--- a/cooker/emit.c
+++ b/cooker/emit.c
@@ -217,18 +217,19 @@ void emit_store(struct gluten_ctx *g, struct gluten_offset dst,
* @iov: Pointer to msg_iov, already stored in gluten
* @iovlen: Pointer to msg_iovlen, already stored in gluten
* @dst: gluten destination to copy dereferenced data
+ * @alloc: Allocation size (alloc - len bytes filled with zeroes)
* @len: Maximum length of data to copy altogether
*/
struct gluten_offset emit_iovload(struct gluten_ctx *g,
struct gluten_offset iov,
struct gluten_offset iovlen,
- size_t len)
+ size_t alloc, size_t len)
{
struct op *op = (struct op *)gluten_ptr(&g->g, g->ip);
struct op_iovload *load = &op->op.iovload;
struct gluten_offset dst;
- dst = gluten_rw_alloc(g, len);
+ dst = gluten_rw_alloc(g, alloc);
op->type = OP_IOVLOAD;
@@ -237,6 +238,7 @@ struct gluten_offset emit_iovload(struct gluten_ctx *g,
load->dst = dst;
load->size = len;
+ load->zero_fill = alloc - len;
debug(" %i: OP_IOVLOAD: #%i < (#%i) as iovec (size: %lu)",
g->ip.offset, dst.offset, iov.offset, len);
@@ -294,6 +296,7 @@ void emit_resolvefd(struct gluten_ctx *g, enum type type,
* emit_bitwise(): Emit OP_BITWISE instruction: bitwise operation and store
* @g: gluten context
* @type: Type of operands
+ * @vec: Description of vector structure, NULL for scalar operation
* @op_type: Type of bitwise operation
* @dst: gluten pointer to destination operand, can be OFFSET_NULL
* @x: gluten pointer to first source operand
@@ -302,6 +305,7 @@ void emit_resolvefd(struct gluten_ctx *g, enum type type,
* Return: offset to destination operand, allocated here if not given
*/
struct gluten_offset emit_bitwise(struct gluten_ctx *g, enum type type,
+ struct vec_desc *vec,
enum bitwise_type op_type,
struct gluten_offset dst,
struct gluten_offset x,
@@ -311,6 +315,7 @@ struct gluten_offset emit_bitwise(struct gluten_ctx *g, enum type type,
struct op_bitwise *op_bitwise = &op->op.bitwise;
struct gluten_offset o;
struct bitwise_desc *desc;
+ char ip_str[BUFSIZ];
op->type = OP_BITWISE;
@@ -319,21 +324,42 @@ struct gluten_offset emit_bitwise(struct gluten_ctx *g, enum type type,
desc->size = gluten_size[type];
desc->type = op_type;
- if (dst.type == OFFSET_NULL)
- desc->dst = gluten_rw_alloc(g, desc->size);
- else
+
+ if (vec)
+ desc->vec = *vec;
+
+ if (dst.type == OFFSET_NULL) {
+ size_t dst_size;
+ if (vec) /* FIXME: UIO_MAXIOV (1024) is a dubious choice */
+ dst_size = (desc->size + sizeof(uint32_t)) * 1024;
+ else
+ dst_size = desc->size;
+
+ desc->dst = gluten_rw_alloc(g, dst_size);
+ } else {
desc->dst = dst;
+ }
+
desc->x = x;
desc->y = y;
op_bitwise->desc = o;
- debug(" %i: OP_BITWISE: %s: #%lu (size: %lu) := %s: #%lu %s %s: #%lu",
- g->ip.offset,
+ snprintf(ip_str, BUFSIZ, "%i", g->ip.offset);
+
+ debug(" %s: OP_BITWISE: %s: #%lu (size: %lu) := %s: #%lu %s %s: #%lu",
+ ip_str,
gluten_offset_name[desc->dst.type], desc->dst.offset, desc->size,
gluten_offset_name[desc->x.type], desc->x.offset,
bitwise_type_str[op_type],
gluten_offset_name[desc->y.type], desc->y.offset);
+ if (vec) {
+ memset(ip_str, ' ', strlen(ip_str));
+ debug(" %s vector start: %s: #%lu, length descriptor at %lu",
+ ip_str,
+ gluten_offset_name[vec->start.type], vec->start.offset,
+ vec->len_offset);
+ }
if (++g->ip.offset > INST_MAX)
die("Too many instructions");
@@ -345,12 +371,14 @@ struct gluten_offset emit_bitwise(struct gluten_ctx *g, enum type type,
* emit_cmp(): Emit OP_CMP instruction: compare data from two offsets
* @g: gluten context
* @cmp_type: Type of comparison
+ * @vec: Description of vector structure, NULL for scalar comparison
* @x: gluten pointer to first operand of comparison
* @y: gluten pointer to second operand of comparison
* @size: Size of comparison
* @jmp: Jump direction if comparison is true
*/
void emit_cmp(struct gluten_ctx *g, enum op_cmp_type cmp_type,
+ struct vec_desc *vec,
struct gluten_offset x, struct gluten_offset y, size_t size,
enum jump_type jmp)
{
@@ -367,6 +395,11 @@ void emit_cmp(struct gluten_ctx *g, enum op_cmp_type cmp_type,
desc->x = x;
desc->y = y;
desc->size = size;
+ if (vec)
+ desc->vec = *vec;
+ else
+ desc->vec.start.type = OFFSET_NULL;
+
desc->cmp = cmp_type;
desc->jmp.type = OFFSET_INSTRUCTION;
desc->jmp.offset = jmp;
@@ -388,17 +421,18 @@ void emit_cmp(struct gluten_ctx *g, enum op_cmp_type cmp_type,
* emit_cmp_field() - Emit OP_CMP for a given field type
* @g: gluten context
* @cmp: Type of comparison
+ * @vec: Description of vector structure, NULL for scalar comparison
* @field: Description of field from system call model
* @x: gluten pointer to first operand of comparison
* @y: gluten pointer to second operand of comparison
* @jmp: Jump direction if comparison is true
*/
void emit_cmp_field(struct gluten_ctx *g, enum op_cmp_type cmp,
- struct field *field,
+ struct vec_desc *vec, struct field *field,
struct gluten_offset x, struct gluten_offset y,
enum jump_type jmp)
{
- emit_cmp(g, cmp, x, y,
+ emit_cmp(g, cmp, vec, x, y,
field->size ? field->size : gluten_size[field->type],
jmp);
}
diff --git a/cooker/emit.h b/cooker/emit.h
index abdeda9..7948071 100644
--- a/cooker/emit.h
+++ b/cooker/emit.h
@@ -19,20 +19,21 @@ void emit_load(struct gluten_ctx *g, struct gluten_offset dst,
struct gluten_offset emit_iovload(struct gluten_ctx *g,
struct gluten_offset iov,
struct gluten_offset iovlen,
- size_t len);
+ size_t alloc, size_t len);
void emit_store(struct gluten_ctx *g, struct gluten_offset dst,
struct gluten_offset src, struct gluten_offset count);
struct gluten_offset emit_seccomp_data(int index);
struct gluten_offset emit_bitwise(struct gluten_ctx *g, enum type type,
+ struct vec_desc *desc,
enum bitwise_type op_type,
struct gluten_offset dst,
struct gluten_offset x,
struct gluten_offset y);
-void emit_cmp(struct gluten_ctx *g, enum op_cmp_type cmp,
+void emit_cmp(struct gluten_ctx *g, enum op_cmp_type cmp, struct vec_desc *vec,
struct gluten_offset x, struct gluten_offset y, size_t size,
enum jump_type jmp);
void emit_cmp_field(struct gluten_ctx *g, enum op_cmp_type cmp,
- struct field *field,
+ struct vec_desc *vec, struct field *field,
struct gluten_offset base, struct gluten_offset match,
enum jump_type jmp);
void emit_return(struct gluten_ctx *g, struct gluten_offset v,
diff --git a/cooker/match.c b/cooker/match.c
index 1fd726f..f65ac5c 100644
--- a/cooker/match.c
+++ b/cooker/match.c
@@ -22,9 +22,70 @@
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nf_tables.h>
+#include <linux/netfilter/nf_tables_compat.h>
static struct num netlink_types[] = {
- { "newroute", RTM_NEWROUTE },
+ { "newroute", RTM_NEWROUTE },
+
+#define SUBSYS_NFCOMPAT(x) (NFNL_SUBSYS_NFT_COMPAT << 8 | (x))
+ { "nf_compat_get", (SUBSYS_NFCOMPAT(NFNL_MSG_COMPAT_GET))},
+
+#define SUBSYS_NFT(x) (NFNL_SUBSYS_NFTABLES << 8 | (x))
+ { "nf_get_any",
+ SUBSYS_NFT(NFT_MSG_GETTABLE | NFT_MSG_GETCHAIN | NFT_MSG_GETRULE |
+ NFT_MSG_GETSET | NFT_MSG_GETSETELEM | NFT_MSG_GETGEN |
+ NFT_MSG_GETFLOWTABLE | NFT_MSG_GETOBJ) |
+ SUBSYS_NFCOMPAT(NFNL_MSG_COMPAT_GET) },
+
+#undef SUBSYS_NFCOMPAT
+
+ { "nf_newtable", SUBSYS_NFT(NFT_MSG_NEWTABLE) },
+ { "nf_gettable", SUBSYS_NFT(NFT_MSG_GETTABLE) },
+ { "nf_deltable", SUBSYS_NFT(NFT_MSG_DELTABLE) },
+ { "nf_destroytable", SUBSYS_NFT(NFT_MSG_DESTROYTABLE) },
+ /* ignores ENOENT */
+
+ { "nf_newchain", SUBSYS_NFT(NFT_MSG_NEWCHAIN) },
+ { "nf_getchain", SUBSYS_NFT(NFT_MSG_GETCHAIN) },
+ { "nf_delchain", SUBSYS_NFT(NFT_MSG_DELCHAIN) },
+ { "nf_destroychain", SUBSYS_NFT(NFT_MSG_DESTROYCHAIN) },
+
+ { "nf_newrule", SUBSYS_NFT(NFT_MSG_NEWRULE) },
+ { "nf_getrule", SUBSYS_NFT(NFT_MSG_GETRULE) },
+ { "nf_getrule_reset", SUBSYS_NFT(NFT_MSG_GETRULE_RESET) },
+ { "nf_delrule", SUBSYS_NFT(NFT_MSG_DELRULE) },
+ { "nf_destroyrule", SUBSYS_NFT(NFT_MSG_DESTROYRULE) },
+
+ { "nf_newset", SUBSYS_NFT(NFT_MSG_NEWSET) },
+ { "nf_getset", SUBSYS_NFT(NFT_MSG_GETSET) },
+ { "nf_delset", SUBSYS_NFT(NFT_MSG_DELSET) },
+ { "nf_destroyset", SUBSYS_NFT(NFT_MSG_DESTROYSET) },
+
+ { "nf_newsetelem", SUBSYS_NFT(NFT_MSG_NEWSETELEM) },
+ { "nf_getsetelem", SUBSYS_NFT(NFT_MSG_GETSETELEM) },
+ { "nf_getsetelem_reset", SUBSYS_NFT(NFT_MSG_GETSETELEM_RESET) },
+ { "nf_delsetelem", SUBSYS_NFT(NFT_MSG_DELSETELEM) },
+ { "nf_destroysetelem", SUBSYS_NFT(NFT_MSG_DESTROYSETELEM) },
+
+ { "nf_newgen", SUBSYS_NFT(NFT_MSG_NEWGEN) },
+ { "nf_getgen", SUBSYS_NFT(NFT_MSG_GETGEN) },
+
+ { "nf_trace", SUBSYS_NFT(NFT_MSG_TRACE) },
+
+ { "nf_newobj", SUBSYS_NFT(NFT_MSG_NEWOBJ) },
+ { "nf_getobj", SUBSYS_NFT(NFT_MSG_GETOBJ) },
+ { "nf_getobj_reset", SUBSYS_NFT(NFT_MSG_GETOBJ_RESET) },
+ { "nf_delobj", SUBSYS_NFT(NFT_MSG_DELOBJ) },
+ { "nf_destroyobj", SUBSYS_NFT(NFT_MSG_DESTROYOBJ) },
+
+ { "nf_newflowtable", SUBSYS_NFT(NFT_MSG_NEWFLOWTABLE) },
+ { "nf_getflowtable", SUBSYS_NFT(NFT_MSG_GETFLOWTABLE) },
+ { "nf_delflowtable", SUBSYS_NFT(NFT_MSG_DELFLOWTABLE) },
+ { "nf_destroyflowtable", SUBSYS_NFT(NFT_MSG_DESTROYFLOWTABLE) },
+#undef SUBSYS_NFT
+
{ 0 },
};
@@ -109,6 +170,7 @@ static struct gluten_offset arg_load(struct gluten_ctx *g, struct arg *a)
*/
static union value parse_field(struct gluten_ctx *g,
struct gluten_offset offset,
+ struct vec_desc *vec,
enum op_cmp_type cmp, enum jump_type jump,
int index, struct field *f, JSON_Value *jvalue)
{
@@ -134,7 +196,7 @@ ______________________ _____________
*/
v.v_num = ((long long)0xfff << 44) | (0xfff << 8);
mask_offset = emit_data(g, U64, 0, &v);
- offset = emit_bitwise(g, U64, BITWISE_AND, NULL_OFFSET,
+ offset = emit_bitwise(g, U64, NULL, BITWISE_AND, NULL_OFFSET,
offset, mask_offset);
break;
case GNU_DEV_MINOR:
@@ -144,7 +206,7 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
*/
v.v_num = 0xff | ((long long)0xfff << 20);
mask_offset = emit_data(g, U64, 0, &v);
- offset = emit_bitwise(g, U64, BITWISE_AND, NULL_OFFSET,
+ offset = emit_bitwise(g, U64, NULL, BITWISE_AND, NULL_OFFSET,
offset, mask_offset);
break;
default:
@@ -155,9 +217,19 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
if (f->flags & IOV) {
struct gluten_offset iovlen = offset;
+ size_t alloc;
+
+ /* vectorised ops need a zero length descriptor at the end */
+ if (json_value_get_type(jvalue) == JSONObject &&
+ (tmp = json_value_get_object(jvalue)) &&
+ json_object_get_value(tmp, "netlink"))
+ alloc = f->size +
+ sizeof(((struct nlmsghdr *)NULL)->nlmsg_len);
+ else
+ alloc = f->size;
iovlen.offset += f->desc.d_iovlen;
- offset = emit_iovload(g, offset, iovlen, f->size);
+ offset = emit_iovload(g, offset, iovlen, alloc, f->size);
}
if (json_value_get_type(jvalue) == JSONObject &&
@@ -188,7 +260,16 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
}
jvalue = json_array_get_value(set, i);
- parse_field(g, offset, cmp, jump, index, f, jvalue);
+
+ /* FIXME: ugly. Otherwise nested parse_field() will
+ * increment twice.
+ */
+ offset.offset -= f->offset;
+
+ parse_field(g, offset, vec, cmp, jump, index, f,
+ jvalue);
+
+ offset.offset += f->offset;
}
return v; /* No SELECT based on sets... of course */
@@ -215,12 +296,12 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
&set, &cmp, &cmpterm);
set_offset = emit_data(g, f->type, 0, &set);
- masked = emit_bitwise(g, f->type, BITWISE_AND,
+ masked = emit_bitwise(g, f->type, vec, BITWISE_AND,
NULL_OFFSET,
offset, set_offset);
cmp_offset = emit_data(g, f->type, 0, &cmpterm);
- emit_cmp(g, cmp, masked, cmp_offset,
+ emit_cmp(g, cmp, vec, masked, cmp_offset,
gluten_size[f->type], jump);
emit_bpf_arg(index, f->type, cmpterm, set, cmp, g->mode);
@@ -241,9 +322,13 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
} else if (f->flags & MASK) {
mask.v_num = value_get_mask(f->desc.d_num);
mask_offset = emit_data(g, f->type, 0, &mask);
- data_offset = emit_bitwise(g, f->type, BITWISE_AND,
+
+ data_offset = emit_bitwise(g, f->type, vec, BITWISE_AND,
NULL_OFFSET, offset,
mask_offset);
+ if (vec)
+ vec->len_offset = 0;
+
v.v_num = value_get_num(f->desc.d_num, jvalue);
} else {
v.v_num = value_get_num(f->desc.d_num, jvalue);
@@ -251,7 +336,7 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
const_offset = emit_data(g, f->type, 0, &v);
- emit_cmp(g, cmp, data_offset, const_offset,
+ emit_cmp(g, cmp, vec, data_offset, const_offset,
gluten_size[f->type], jump);
emit_bpf_arg(index, f->type, v, mask, cmp, g->mode);
@@ -266,7 +351,7 @@ ______________________ _____________
v.v_num = (v.v_num & 0xfff) << 8 | (v.v_num & ~0xfff) << 32;
const_offset = emit_data(g, U64, 0, &v);
- emit_cmp_field(g, cmp, f, offset, const_offset, jump);
+ emit_cmp_field(g, cmp, vec, f, offset, const_offset, jump);
filter_needs_deref(); /* No shifts in BPF */
break;
@@ -278,7 +363,7 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
v.v_num = value_get_num(f->desc.d_num, jvalue);
v.v_num = (v.v_num & 0xff) | (v.v_num & ~0xfff) << 12;
const_offset = emit_data(g, U64, 0, &v);
- emit_cmp_field(g, cmp, f, offset, const_offset, jump);
+ emit_cmp_field(g, cmp, vec, f, offset, const_offset, jump);
filter_needs_deref(); /* No shifts in BPF */
break;
@@ -292,17 +377,43 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
sel = jvalue;
}
- v = parse_field(g, offset, cmp, jump, index, f_inner, sel);
+ v = parse_field(g, offset, vec, cmp, jump, index, f_inner, sel);
f = select_field(g, index, f->desc.d_select, v);
- if (f)
- parse_field(g, offset, cmp, jump, index, f, jvalue);
+ if (f) {
+ parse_field(g, offset, vec, cmp, jump, index, f,
+ jvalue);
+ }
break;
case STRING:
if (json_value_get_type(jvalue) == JSONObject &&
(tmp = json_value_get_object(jvalue))) {
if ((jvalue = json_object_get_value(tmp, "netlink"))) {
- parse_field(g, offset, cmp, jump, index,
+ struct vec_desc v_nl, *vecptr;
+
+ /* FIXME: even send()/sendto() might need
+ * vectorised operations
+ */
+ if (f->flags & IOV) {
+ v_nl.start = offset;
+ v_nl.len_offset = offsetof(struct nlmsghdr,
+ nlmsg_len);
+ vecptr = &v_nl;
+ } else {
+ vecptr = NULL;
+ }
+
+ /* TODO: mark as CMPVEC, with:
+ * - offset of length (offsetof nlmsghdr)
+ * - vector pointer: that's already offset?
+ * - offset of comparison in vector (0 atm)
+ * - second term of comparison (from jvalue)
+ * - length (still needed?)
+ *
+ * plus BITWISEVEC? is it even needed?
+ */
+
+ parse_field(g, offset, vecptr, cmp, jump, index,
&netlink_header, jvalue);
} else {
die(" unrecognised blob type");
@@ -317,8 +428,8 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
die(" string %s too long for field", v.v_str);
const_offset = emit_data(g, STRING, strlen(v.v_str) + 1, &v);
- emit_cmp(g, CMP_NE, offset, const_offset, strlen(v.v_str) + 1,
- JUMP_NEXT_BLOCK);
+ emit_cmp(g, CMP_NE, vec, offset, const_offset,
+ strlen(v.v_str) + 1, JUMP_NEXT_BLOCK);
break;
case FDPATH:
case FDMOUNT:
@@ -328,8 +439,8 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
const_offset = emit_data(g, STRING, size, &v);
seccomp_offset = emit_seccomp_data(index);
emit_resolvefd(g, f->type, seccomp_offset, offset, size);
- emit_cmp(g, CMP_NE, offset, const_offset, size,
- JUMP_NEXT_BLOCK);
+ emit_cmp(g, CMP_NE, vec, offset, const_offset,
+ size, JUMP_NEXT_BLOCK);
break;
case STRUCT:
for (f_inner = f->desc.d_struct; f_inner->name; f_inner++) {
@@ -340,7 +451,7 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
if (!field_value)
continue;
- parse_field(g, offset, cmp, jump, index, f_inner,
+ parse_field(g, offset, vec, cmp, jump, index, f_inner,
field_value);
}
break;
@@ -365,7 +476,8 @@ static void parse_arg(struct gluten_ctx *g, JSON_Value *jvalue, struct arg *a)
offset = arg_load(g, a);
- parse_field(g, offset, CMP_NE, JUMP_NEXT_BLOCK, a->pos, &a->f, jvalue);
+ parse_field(g, offset, NULL, CMP_NE, JUMP_NEXT_BLOCK, a->pos, &a->f,
+ jvalue);
}
/**
@@ -407,16 +519,25 @@ static void parse_match(struct gluten_ctx *g, JSON_Object *obj,
void handle_matches(struct gluten_ctx *g, JSON_Value *value)
{
JSON_Array *matches = json_value_get_array(value);
- unsigned i;
+ unsigned i, count;
- for (i = 0; i < json_array_get_count(matches); i++) {
+ if (matches)
+ count = json_array_get_count(matches);
+ else
+ count = 1;
+
+ for (i = 0; i < count; i++) {
JSON_Object *match, *args;
struct call **set, *call;
const char *name;
+ if (matches)
+ match = json_array_get_object(matches, i);
+ else
+ match = json_value_get_object(value);
+
g->mr = g->ip;
- match = json_array_get_object(matches, i);
name = json_object_get_name(match, 0);
args = json_object_get_object(match, name);
debug(" Parsing match %i: %s", i, name);