expect/api.c
/*
* (C) 2005-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdlib.h>
#include <string.h> /* for memset */
#include <errno.h>
#include <assert.h>
#include <libmnl/libmnl.h>
#include "internal/internal.h"
struct nf_expect *nfexp_new(void)
{
struct nf_expect *exp;
exp = malloc(sizeof(struct nf_expect));
if (!exp)
return NULL;
memset(exp, 0, sizeof(struct nf_expect));
return exp;
}
void nfexp_destroy(struct nf_expect *exp)
{
assert(exp != NULL);
free(exp);
exp = NULL; /* bugtrap */
}
size_t nfexp_sizeof(const struct nf_expect *exp)
{
assert(exp != NULL);
return sizeof(*exp);
}
size_t nfexp_maxsize(void)
{
return sizeof(struct nf_expect);
}
struct nf_expect *nfexp_clone(const struct nf_expect *exp)
{
struct nf_expect *clone;
assert(exp != NULL);
if ((clone = nfexp_new()) == NULL)
return NULL;
memcpy(clone, exp, sizeof(*exp));
return clone;
}
int nfexp_cmp(const struct nf_expect *exp1, const struct nf_expect *exp2,
unsigned int flags)
{
assert(exp1 != NULL);
assert(exp2 != NULL);
return __cmp_expect(exp1, exp2, flags);
}
int nfexp_callback_register(struct nfct_handle *h,
enum nf_conntrack_msg_type type,
int (*cb)(enum nf_conntrack_msg_type type,
struct nf_expect *exp,
void *data),
void *data)
{
struct __data_container *container;
assert(h != NULL);
container = malloc(sizeof(struct __data_container));
if (!container)
return -1;
memset(container, 0, sizeof(struct __data_container));
h->expect_cb = cb;
container->h = h;
container->type = type;
container->data = data;
h->nfnl_cb_exp.call = __callback;
h->nfnl_cb_exp.data = container;
h->nfnl_cb_exp.attr_count = CTA_EXPECT_MAX;
nfnl_callback_register(h->nfnlssh_exp,
IPCTNL_MSG_EXP_NEW,
&h->nfnl_cb_exp);
nfnl_callback_register(h->nfnlssh_exp,
IPCTNL_MSG_EXP_DELETE,
&h->nfnl_cb_exp);
return 0;
}
void nfexp_callback_unregister(struct nfct_handle *h)
{
assert(h != NULL);
nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_NEW);
nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_DELETE);
h->expect_cb = NULL;
free(h->nfnl_cb_exp.data);
h->nfnl_cb_exp.call = NULL;
h->nfnl_cb_exp.data = NULL;
h->nfnl_cb_exp.attr_count = 0;
}
int nfexp_callback_register2(struct nfct_handle *h,
enum nf_conntrack_msg_type type,
int (*cb)(const struct nlmsghdr *nlh,
enum nf_conntrack_msg_type type,
struct nf_expect *exp,
void *data),
void *data)
{
struct __data_container *container;
assert(h != NULL);
container = malloc(sizeof(struct __data_container));
if (!container)
return -1;
memset(container, 0, sizeof(struct __data_container));
h->expect_cb2 = cb;
container->h = h;
container->type = type;
container->data = data;
h->nfnl_cb_exp.call = __callback;
h->nfnl_cb_exp.data = container;
h->nfnl_cb_exp.attr_count = CTA_EXPECT_MAX;
nfnl_callback_register(h->nfnlssh_exp,
IPCTNL_MSG_EXP_NEW,
&h->nfnl_cb_exp);
nfnl_callback_register(h->nfnlssh_exp,
IPCTNL_MSG_EXP_DELETE,
&h->nfnl_cb_exp);
return 0;
}
void nfexp_callback_unregister2(struct nfct_handle *h)
{
assert(h != NULL);
nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_NEW);
nfnl_callback_unregister(h->nfnlssh_exp, IPCTNL_MSG_EXP_DELETE);
h->expect_cb2 = NULL;
free(h->nfnl_cb_exp.data);
h->nfnl_cb_exp.call = NULL;
h->nfnl_cb_exp.data = NULL;
h->nfnl_cb_exp.attr_count = 0;
}
void nfexp_set_attr(struct nf_expect *exp,
const enum nf_expect_attr type,
const void *value)
{
assert(exp != NULL);
assert(value != NULL);
if (type >= ATTR_EXP_MAX)
return;
if (set_exp_attr_array[type]) {
set_exp_attr_array[type](exp, value);
set_bit(type, exp->set);
}
}
void nfexp_set_attr_u8(struct nf_expect *exp,
const enum nf_expect_attr type,
uint8_t value)
{
nfexp_set_attr(exp, type, &value);
}
void nfexp_set_attr_u16(struct nf_expect *exp,
const enum nf_expect_attr type,
uint16_t value)
{
nfexp_set_attr(exp, type, &value);
}
void nfexp_set_attr_u32(struct nf_expect *exp,
const enum nf_expect_attr type,
uint32_t value)
{
nfexp_set_attr(exp, type, &value);
}
const void *nfexp_get_attr(const struct nf_expect *exp,
const enum nf_expect_attr type)
{
assert(exp != NULL);
if (type >= ATTR_EXP_MAX) {
errno = EINVAL;
return NULL;
}
if (!test_bit(type, exp->set)) {
errno = ENODATA;
return NULL;
}
return get_exp_attr_array[type](exp);
}
uint8_t nfexp_get_attr_u8(const struct nf_expect *exp,
const enum nf_expect_attr type)
{
const uint8_t *ret = nfexp_get_attr(exp, type);
return ret == NULL ? 0 : *ret;
}
uint16_t nfexp_get_attr_u16(const struct nf_expect *exp,
const enum nf_expect_attr type)
{
const uint16_t *ret = nfexp_get_attr(exp, type);
return ret == NULL ? 0 : *ret;
}
uint32_t nfexp_get_attr_u32(const struct nf_expect *exp,
const enum nf_expect_attr type)
{
const uint32_t *ret = nfexp_get_attr(exp, type);
return ret == NULL ? 0 : *ret;
}
int nfexp_attr_is_set(const struct nf_expect *exp,
const enum nf_expect_attr type)
{
assert(exp != NULL);
if (type >= ATTR_EXP_MAX) {
errno = EINVAL;
return -1;
}
return test_bit(type, exp->set);
}
int nfexp_attr_unset(struct nf_expect *exp,
const enum nf_expect_attr type)
{
assert(exp != NULL);
if (type >= ATTR_EXP_MAX) {
errno = EINVAL;
return -1;
}
unset_bit(type, exp->set);
return 0;
}
int nfexp_build_expect(struct nfnl_subsys_handle *ssh,
void *req,
size_t size,
uint16_t type,
uint16_t flags,
const struct nf_expect *exp)
{
assert(ssh != NULL);
assert(req != NULL);
assert(exp != NULL);
memset(req, 0, size);
return __build_expect(req, size, type, flags, exp);
}
static void nfexp_fill_hdr(struct nfnlhdr *req, uint16_t type, uint16_t flags,
uint8_t l3num, uint8_t version)
{
char *buf = (char *)&req->nlh;
struct nlmsghdr *nlh;
struct nfgenmsg *nfh;
nlh = mnl_nlmsg_put_header(buf);
nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK_EXP << 8) | type;
nlh->nlmsg_flags = NLM_F_REQUEST | flags;
nlh->nlmsg_seq = 0;
nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg));
nfh->nfgen_family = l3num;
nfh->version = version;
nfh->res_id = 0;
}
static int
__build_query_exp(const enum nf_conntrack_query qt,
const void *data, void *buffer, unsigned int size)
{
struct nfnlhdr *req = buffer;
const uint8_t *family = data;
assert(data != NULL);
assert(req != NULL);
memset(buffer, 0, size);
switch(qt) {
case NFCT_Q_CREATE:
__build_expect(req, size, IPCTNL_MSG_EXP_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK|NLM_F_EXCL, data);
break;
case NFCT_Q_CREATE_UPDATE:
__build_expect(req, size, IPCTNL_MSG_EXP_NEW, NLM_F_REQUEST|NLM_F_CREATE|NLM_F_ACK, data);
break;
case NFCT_Q_GET:
__build_expect(req, size, IPCTNL_MSG_EXP_GET, NLM_F_REQUEST|NLM_F_ACK, data);
break;
case NFCT_Q_DESTROY:
__build_expect(req, size, IPCTNL_MSG_EXP_DELETE, NLM_F_REQUEST|NLM_F_ACK, data);
break;
case NFCT_Q_FLUSH:
nfexp_fill_hdr(req, IPCTNL_MSG_EXP_DELETE, NLM_F_ACK, *family,
NFNETLINK_V0);
break;
case NFCT_Q_DUMP:
nfexp_fill_hdr(req, IPCTNL_MSG_EXP_GET, NLM_F_DUMP, *family,
NFNETLINK_V0);
break;
default:
errno = ENOTSUP;
return -1;
}
return 1;
}
int nfexp_build_query(struct nfnl_subsys_handle *ssh,
const enum nf_conntrack_query qt,
const void *data,
void *buffer,
unsigned int size)
{
return __build_query_exp(qt, data, buffer, size);
}
static int __parse_expect_message_type(const struct nlmsghdr *nlh)
{
uint16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
uint16_t flags = nlh->nlmsg_flags;
int ret = NFCT_T_UNKNOWN;
if (type == IPCTNL_MSG_EXP_NEW) {
if (flags & (NLM_F_CREATE|NLM_F_EXCL))
ret = NFCT_T_NEW;
else
ret = NFCT_T_UPDATE;
} else if (type == IPCTNL_MSG_EXP_DELETE)
ret = NFCT_T_DESTROY;
return ret;
}
int nfexp_parse_expect(enum nf_conntrack_msg_type type,
const struct nlmsghdr *nlh,
struct nf_expect *exp)
{
unsigned int flags;
assert(nlh != NULL);
assert(exp != NULL);
flags = __parse_expect_message_type(nlh);
if (!(flags & type))
return 0;
nfexp_nlmsg_parse(nlh, exp);
return flags;
}
int nfexp_query(struct nfct_handle *h,
const enum nf_conntrack_query qt,
const void *data)
{
const size_t size = 4096; /* enough for now */
union {
char buffer[size];
struct nfnlhdr req;
} u;
assert(h != NULL);
assert(data != NULL);
if (__build_query_exp(qt, data, &u.req, size) == -1)
return -1;
return nfnl_query(h->nfnlh, &u.req.nlh);
}
int nfexp_send(struct nfct_handle *h,
const enum nf_conntrack_query qt,
const void *data)
{
const size_t size = 4096; /* enough for now */
union {
char buffer[size];
struct nfnlhdr req;
} u;
assert(h != NULL);
assert(data != NULL);
if (__build_query_exp(qt, data, &u.req, size) == -1)
return -1;
return nfnl_send(h->nfnlh, &u.req.nlh);
}
int nfexp_catch(struct nfct_handle *h)
{
assert(h != NULL);
return nfnl_catch(h->nfnlh);
}
int nfexp_snprintf(char *buf,
unsigned int size,
const struct nf_expect *exp,
unsigned int msg_type,
unsigned int out_type,
unsigned int flags)
{
assert(buf != NULL);
assert(size > 0);
assert(exp != NULL);
return __snprintf_expect(buf, size, exp, msg_type, out_type, flags);
}
nfexp_callback_unregister
void nfexp_callback_unregister(struct nfct_handle *h)
Definition expect/api.c:198
nfexp_callback_unregister2
void nfexp_callback_unregister2(struct nfct_handle *h)
Definition expect/api.c:273
nfexp_callback_register2
int nfexp_callback_register2(struct nfct_handle *h, enum nf_conntrack_msg_type type, int(*cb)(const struct nlmsghdr *nlh, enum nf_conntrack_msg_type type, struct nf_expect *exp, void *data), void *data)
Definition expect/api.c:232
nfexp_callback_register
int nfexp_callback_register(struct nfct_handle *h, enum nf_conntrack_msg_type type, int(*cb)(enum nf_conntrack_msg_type type, struct nf_expect *exp, void *data), void *data)
Definition expect/api.c:158
nfexp_catch
int nfexp_catch(struct nfct_handle *h)
Definition expect/api.c:760
nfexp_send
int nfexp_send(struct nfct_handle *h, const enum nf_conntrack_query qt, const void *data)
Definition expect/api.c:727
nfexp_query
int nfexp_query(struct nfct_handle *h, const enum nf_conntrack_query qt, const void *data)
Definition expect/api.c:695
nfexp_set_attr_u32
void nfexp_set_attr_u32(struct nf_expect *exp, const enum nf_expect_attr type, uint32_t value)
Definition expect/api.c:357
nfexp_new
struct nf_expect * nfexp_new(void)
Definition expect/api.c:29
nfexp_get_attr_u32
uint32_t nfexp_get_attr_u32(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition expect/api.c:431
nfexp_sizeof
size_t nfexp_sizeof(const struct nf_expect *exp)
Definition expect/api.c:57
nfexp_get_attr
const void * nfexp_get_attr(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition expect/api.c:372
nfexp_set_attr_u16
void nfexp_set_attr_u16(struct nf_expect *exp, const enum nf_expect_attr type, uint16_t value)
Definition expect/api.c:344
nfexp_set_attr
void nfexp_set_attr(struct nf_expect *exp, const enum nf_expect_attr type, const void *value)
Definition expect/api.c:309
nfexp_cmp
int nfexp_cmp(const struct nf_expect *exp1, const struct nf_expect *exp2, unsigned int flags)
Definition expect/api.c:127
nfexp_get_attr_u16
uint16_t nfexp_get_attr_u16(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition expect/api.c:415
nfexp_set_attr_u8
void nfexp_set_attr_u8(struct nf_expect *exp, const enum nf_expect_attr type, uint8_t value)
Definition expect/api.c:331
nfexp_get_attr_u8
uint8_t nfexp_get_attr_u8(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition expect/api.c:399
nfexp_snprintf
int nfexp_snprintf(char *buf, unsigned int size, const struct nf_expect *exp, unsigned int msg_type, unsigned int out_type, unsigned int flags)
Definition expect/api.c:802
nfexp_destroy
void nfexp_destroy(struct nf_expect *exp)
Definition expect/api.c:46
nfexp_attr_unset
int nfexp_attr_unset(struct nf_expect *exp, const enum nf_expect_attr type)
Definition expect/api.c:466
nfexp_clone
struct nf_expect * nfexp_clone(const struct nf_expect *exp)
Definition expect/api.c:89
nfexp_attr_is_set
int nfexp_attr_is_set(const struct nf_expect *exp, const enum nf_expect_attr type)
Definition expect/api.c:446
nfexp_maxsize
size_t nfexp_maxsize(void)
Definition expect/api.c:77
nfexp_build_query
int nfexp_build_query(struct nfnl_subsys_handle *ssh, const enum nf_conntrack_query qt, const void *data, void *buffer, unsigned int size)
Definition expect/api.c:609
nfexp_build_expect
int nfexp_build_expect(struct nfnl_subsys_handle *ssh, void *req, size_t size, uint16_t type, uint16_t flags, const struct nf_expect *exp)
Definition expect/api.c:505
nfexp_parse_expect
int nfexp_parse_expect(enum nf_conntrack_msg_type type, const struct nlmsghdr *nlh, struct nf_expect *exp)
Definition expect/api.c:659