18#include <netinet/in.h>
20#include <libmnl/libmnl.h>
21#include <linux/netfilter/nfnetlink.h>
22#include <linux/netfilter/nfnetlink_cttimeout.h>
24#include <libnetfilter_cttimeout/libnetfilter_cttimeout.h>
26static const char *
const tcp_state_to_name[] = {
27 [NFCT_TIMEOUT_ATTR_TCP_SYN_SENT] =
"SYN_SENT",
28 [NFCT_TIMEOUT_ATTR_TCP_SYN_RECV] =
"SYN_RECV",
29 [NFCT_TIMEOUT_ATTR_TCP_ESTABLISHED] =
"ESTABLISHED",
30 [NFCT_TIMEOUT_ATTR_TCP_FIN_WAIT] =
"FIN_WAIT",
31 [NFCT_TIMEOUT_ATTR_TCP_CLOSE_WAIT] =
"CLOSE_WAIT",
32 [NFCT_TIMEOUT_ATTR_TCP_LAST_ACK] =
"LAST_ACK",
33 [NFCT_TIMEOUT_ATTR_TCP_TIME_WAIT] =
"TIME_WAIT",
34 [NFCT_TIMEOUT_ATTR_TCP_CLOSE] =
"CLOSE",
35 [NFCT_TIMEOUT_ATTR_TCP_SYN_SENT2] =
"SYN_SENT2",
36 [NFCT_TIMEOUT_ATTR_TCP_RETRANS] =
"RETRANS",
37 [NFCT_TIMEOUT_ATTR_TCP_UNACK] =
"UNACKNOWLEDGED",
40static const char *
const generic_state_to_name[] = {
41 [NFCT_TIMEOUT_ATTR_GENERIC] =
"TIMEOUT",
44static const char *
const udp_state_to_name[] = {
45 [NFCT_TIMEOUT_ATTR_UDP_UNREPLIED] =
"UNREPLIED",
46 [NFCT_TIMEOUT_ATTR_UDP_REPLIED] =
"REPLIED",
49static const char *
const sctp_state_to_name[] = {
50 [NFCT_TIMEOUT_ATTR_SCTP_CLOSED] =
"CLOSED",
51 [NFCT_TIMEOUT_ATTR_SCTP_COOKIE_WAIT] =
"COOKIE_WAIT",
52 [NFCT_TIMEOUT_ATTR_SCTP_COOKIE_ECHOED] =
"COOKIE_ECHOED",
53 [NFCT_TIMEOUT_ATTR_SCTP_ESTABLISHED] =
"ESTABLISHED",
54 [NFCT_TIMEOUT_ATTR_SCTP_SHUTDOWN_SENT] =
"SHUTDOWN_SENT",
55 [NFCT_TIMEOUT_ATTR_SCTP_SHUTDOWN_RECD] =
"SHUTDOWN_RECD",
56 [NFCT_TIMEOUT_ATTR_SCTP_SHUTDOWN_ACK_SENT] =
"SHUTDOWN_ACK_SENT",
59static const char *
const dccp_state_to_name[] = {
60 [NFCT_TIMEOUT_ATTR_DCCP_REQUEST] =
"REQUEST",
61 [NFCT_TIMEOUT_ATTR_DCCP_RESPOND] =
"RESPOND",
62 [NFCT_TIMEOUT_ATTR_DCCP_PARTOPEN] =
"PARTOPEN",
63 [NFCT_TIMEOUT_ATTR_DCCP_OPEN] =
"OPEN",
64 [NFCT_TIMEOUT_ATTR_DCCP_CLOSEREQ] =
"CLOSEREQ",
65 [NFCT_TIMEOUT_ATTR_DCCP_CLOSING] =
"CLOSING",
66 [NFCT_TIMEOUT_ATTR_DCCP_TIMEWAIT] =
"TIMEWAIT",
69static const char *
const icmp_state_to_name[] = {
70 [NFCT_TIMEOUT_ATTR_ICMP] =
"TIMEOUT",
73static const char *
const icmpv6_state_to_name[] = {
74 [NFCT_TIMEOUT_ATTR_ICMPV6] =
"TIMEOUT",
80 const char *
const *state_to_name;
81} timeout_protocol[IPPROTO_MAX] = {
83 .nlattr_max = __CTA_TIMEOUT_ICMP_MAX,
84 .attr_max = NFCT_TIMEOUT_ATTR_ICMP_MAX,
85 .state_to_name = icmp_state_to_name,
88 .nlattr_max = __CTA_TIMEOUT_TCP_MAX,
89 .attr_max = NFCT_TIMEOUT_ATTR_TCP_MAX,
90 .state_to_name = tcp_state_to_name,
93 .nlattr_max = __CTA_TIMEOUT_UDP_MAX,
94 .attr_max = NFCT_TIMEOUT_ATTR_UDP_MAX,
95 .state_to_name = udp_state_to_name,
98 .nlattr_max = __CTA_TIMEOUT_GRE_MAX,
99 .attr_max = NFCT_TIMEOUT_ATTR_GRE_MAX,
100 .state_to_name = udp_state_to_name,
103 .nlattr_max = __CTA_TIMEOUT_SCTP_MAX,
104 .attr_max = NFCT_TIMEOUT_ATTR_SCTP_MAX,
105 .state_to_name = sctp_state_to_name,
108 .nlattr_max = __CTA_TIMEOUT_DCCP_MAX,
109 .attr_max = NFCT_TIMEOUT_ATTR_DCCP_MAX,
110 .state_to_name = dccp_state_to_name,
112 [IPPROTO_UDPLITE] = {
113 .nlattr_max = __CTA_TIMEOUT_UDPLITE_MAX,
114 .attr_max = NFCT_TIMEOUT_ATTR_UDPLITE_MAX,
115 .state_to_name = udp_state_to_name,
118 .nlattr_max = __CTA_TIMEOUT_ICMPV6_MAX,
119 .attr_max = NFCT_TIMEOUT_ATTR_ICMPV6_MAX,
120 .state_to_name = icmpv6_state_to_name,
124 .nlattr_max = __CTA_TIMEOUT_GENERIC_MAX,
125 .attr_max = NFCT_TIMEOUT_ATTR_GENERIC_MAX,
126 .state_to_name = generic_state_to_name,
192 struct nfct_timeout *t;
194 t = calloc(1,
sizeof(
struct nfct_timeout));
222 case NFCT_TIMEOUT_ATTR_NAME:
223 strncpy(t->name, data,
sizeof(t->name));
224 t->name[
sizeof(t->name)-1] =
'\0';
226 case NFCT_TIMEOUT_ATTR_L3PROTO:
227 t->l3num = *((uint16_t *) data);
229 case NFCT_TIMEOUT_ATTR_L4PROTO:
230 t->l4num = *((uint8_t *) data);
234 t->attrset |= (1 << type);
269 t->attrset &= ~(1 << type);
280 uint32_t type, uint32_t data)
282 size_t timeout_array_size;
285 if (!(t->attrset & (1 << NFCT_TIMEOUT_ATTR_L4PROTO)))
288 if (t->timeout == NULL) {
290 if (timeout_protocol[t->l4num].attr_max != 0) {
293 timeout_protocol[t->l4num].attr_max;
297 timeout_protocol[IPPROTO_RAW].attr_max;
299 t->timeout = calloc(1, timeout_array_size);
300 if (t->timeout == NULL)
305 if (type > timeout_protocol[t->l4num].attr_max)
308 t->timeout[type] = data;
309 t->polset |= (1 << type);
311 if (!(t->attrset & (1 << NFCT_TIMEOUT_ATTR_POLICY)))
312 t->attrset |= (1 << NFCT_TIMEOUT_ATTR_POLICY);
325 t->attrset &= ~(1 << type);
336const char __EXPORTED *
339 if (timeout_protocol[l4proto].state_to_name == NULL) {
340 printf(
"no array state name\n");
344 if (timeout_protocol[l4proto].state_to_name[state] == NULL) {
345 printf(
"state %d does not exists\n", state);
349 return timeout_protocol[l4proto].state_to_name[state];
362nfct_timeout_snprintf_default(
char *buf,
size_t size,
363 const struct nfct_timeout *t,
367 unsigned int offset = 0;
369 if (t->attrset & (1 << NFCT_TIMEOUT_ATTR_NAME)) {
370 ret = snprintf(buf+offset, size,
".%s = {\n", t->name);
374 if (t->attrset & (1 << NFCT_TIMEOUT_ATTR_L3PROTO)) {
375 ret = snprintf(buf+offset, size,
"\t.l3proto = %u,\n",
380 if (t->attrset & (1 << NFCT_TIMEOUT_ATTR_L4PROTO)) {
381 ret = snprintf(buf+offset, size,
"\t.l4proto = %u,\n",
386 if (t->attrset & (1 << NFCT_TIMEOUT_ATTR_POLICY)) {
387 uint8_t l4num = t->l4num;
391 if (timeout_protocol[t->l4num].attr_max == 0)
394 ret = snprintf(buf+offset, size,
"\t.policy = {\n");
398 for (i=0; i<timeout_protocol[l4num].attr_max; i++) {
399 const char *state_name =
400 timeout_protocol[l4num].state_to_name[i][0] ?
401 timeout_protocol[l4num].state_to_name[i] :
404 ret = snprintf(buf+offset, size,
405 "\t\t.%s = %u,\n", state_name, t->timeout[i]);
410 ret = snprintf(buf+offset, size,
"\t},\n");
414 ret = snprintf(buf+offset, size,
"};");
436 unsigned int type,
unsigned int flags)
441 case NFCT_TIMEOUT_O_DEFAULT:
442 ret = nfct_timeout_snprintf_default(buf, size, t, flags);
473struct nlmsghdr __EXPORTED *
475 uint16_t flags, uint32_t seq)
477 struct nlmsghdr *nlh;
478 struct nfgenmsg *nfh;
480 nlh = mnl_nlmsg_put_header(buf);
481 nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8) | cmd;
482 nlh->nlmsg_flags = NLM_F_REQUEST | flags;
483 nlh->nlmsg_seq = seq;
485 nfh = mnl_nlmsg_put_extra_header(nlh,
sizeof(
struct nfgenmsg));
486 nfh->nfgen_family = AF_UNSPEC;
487 nfh->version = NFNETLINK_V0;
500 const struct nfct_timeout *t)
505 if (t->attrset & (1 << NFCT_TIMEOUT_ATTR_NAME))
506 mnl_attr_put_strz(nlh, CTA_TIMEOUT_NAME, t->name);
508 if (t->attrset & (1 << NFCT_TIMEOUT_ATTR_L3PROTO))
509 mnl_attr_put_u16(nlh, CTA_TIMEOUT_L3PROTO, htons(t->l3num));
511 if (t->attrset & (1 << NFCT_TIMEOUT_ATTR_L4PROTO))
512 mnl_attr_put_u8(nlh, CTA_TIMEOUT_L4PROTO, t->l4num);
514 if (t->attrset & (1 << NFCT_TIMEOUT_ATTR_POLICY) && t->polset) {
515 nest = mnl_attr_nest_start(nlh, CTA_TIMEOUT_DATA);
517 for (i=0; i<timeout_protocol[t->l4num].attr_max; i++) {
518 if (t->polset & (1 << i)) {
519 mnl_attr_put_u32(nlh, i+1,
520 htonl(t->timeout[i]));
523 mnl_attr_nest_end(nlh, nest);
529timeout_nlmsg_parse_attr_cb(
const struct nlattr *attr,
void *data)
531 const struct nlattr **tb = data;
532 uint16_t type = mnl_attr_get_type(attr);
534 if (mnl_attr_type_valid(attr, CTA_TIMEOUT_MAX) < 0)
538 case CTA_TIMEOUT_NAME:
539 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) {
540 perror(
"mnl_attr_validate");
544 case CTA_TIMEOUT_L3PROTO:
545 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
546 perror(
"mnl_attr_validate");
550 case CTA_TIMEOUT_L4PROTO:
551 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) {
552 perror(
"mnl_attr_validate");
556 case CTA_TIMEOUT_DATA:
557 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
558 perror(
"mnl_attr_validate");
567struct _container_policy_cb {
568 unsigned int nlattr_max;
573parse_timeout_attr_policy_cb(
const struct nlattr *attr,
void *data)
575 struct _container_policy_cb *data_cb = data;
576 const struct nlattr **tb = data_cb->tb;
577 uint16_t type = mnl_attr_get_type(attr);
579 if (mnl_attr_type_valid(attr, data_cb->nlattr_max) < 0)
582 if (type <= data_cb->nlattr_max) {
583 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
584 perror(
"mnl_attr_validate");
593timeout_parse_attr_data(
struct nfct_timeout *t,
const struct nlattr *nest)
595 unsigned int nlattr_max = timeout_protocol[t->l4num].nlattr_max;
596 struct nlattr *tb[nlattr_max];
597 struct _container_policy_cb cnt = {
598 .nlattr_max = nlattr_max,
603 memset(tb, 0,
sizeof(
struct nlattr *) * nlattr_max);
605 mnl_attr_parse_nested(nest, parse_timeout_attr_policy_cb, &cnt);
607 for (i=1; i<nlattr_max; i++) {
610 ntohl(mnl_attr_get_u32(tb[i])));
625 struct nfct_timeout *t)
627 struct nlattr *tb[CTA_TIMEOUT_MAX+1] = {};
628 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
630 mnl_attr_parse(nlh,
sizeof(*nfg), timeout_nlmsg_parse_attr_cb, tb);
631 if (tb[CTA_TIMEOUT_NAME]) {
633 mnl_attr_get_str(tb[CTA_TIMEOUT_NAME]));
635 if (tb[CTA_TIMEOUT_L3PROTO]) {
637 ntohs(mnl_attr_get_u16(tb[CTA_TIMEOUT_L3PROTO])));
639 if (tb[CTA_TIMEOUT_L4PROTO]) {
641 mnl_attr_get_u8(tb[CTA_TIMEOUT_L4PROTO]));
643 if (tb[CTA_TIMEOUT_DATA]) {
644 timeout_parse_attr_data(t, tb[CTA_TIMEOUT_DATA]);
int __EXPORTED nfct_timeout_snprintf(char *buf, size_t size, const struct nfct_timeout *t, unsigned int type, unsigned int flags)
int __EXPORTED nfct_timeout_policy_attr_set_u32(struct nfct_timeout *t, uint32_t type, uint32_t data)
const char __EXPORTED * nfct_timeout_policy_attr_to_name(uint8_t l4proto, uint32_t state)
void __EXPORTED nfct_timeout_policy_attr_unset(struct nfct_timeout *t, uint32_t type)
int __EXPORTED nfct_timeout_attr_set_u16(struct nfct_timeout *t, uint32_t type, uint16_t data)
void __EXPORTED nfct_timeout_free(struct nfct_timeout *t)
struct nfct_timeout __EXPORTED * nfct_timeout_alloc(void)
int __EXPORTED nfct_timeout_attr_set(struct nfct_timeout *t, uint32_t type, const void *data)
int __EXPORTED nfct_timeout_attr_set_u8(struct nfct_timeout *t, uint32_t type, uint8_t data)
void __EXPORTED nfct_timeout_attr_unset(struct nfct_timeout *t, uint32_t type)
struct nlmsghdr __EXPORTED * nfct_timeout_nlmsg_build_hdr(char *buf, uint8_t cmd, uint16_t flags, uint32_t seq)
void __EXPORTED nfct_timeout_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nfct_timeout *t)
int __EXPORTED nfct_timeout_nlmsg_parse_payload(const struct nlmsghdr *nlh, struct nfct_timeout *t)