libnftnl  1.1.4
connlimit.c
1 /*
2  * (C) 2018 by Pablo Neira Ayuso <pablo@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published
6  * by the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  */
9 
10 #include <stdio.h>
11 #include <stdint.h>
12 #include <arpa/inet.h>
13 #include <errno.h>
14 #include <inttypes.h>
15 
16 #include <linux/netfilter/nf_tables.h>
17 
18 #include "internal.h"
19 #include <libmnl/libmnl.h>
20 #include <libnftnl/expr.h>
21 #include <libnftnl/rule.h>
22 
24  uint32_t count;
25  uint32_t flags;
26 };
27 
28 static int
29 nftnl_expr_connlimit_set(struct nftnl_expr *e, uint16_t type,
30  const void *data, uint32_t data_len)
31 {
32  struct nftnl_expr_connlimit *connlimit = nftnl_expr_data(e);
33 
34  switch(type) {
35  case NFTNL_EXPR_CONNLIMIT_COUNT:
36  memcpy(&connlimit->count, data, sizeof(connlimit->count));
37  break;
38  case NFTNL_EXPR_CONNLIMIT_FLAGS:
39  memcpy(&connlimit->flags, data, sizeof(connlimit->flags));
40  break;
41  default:
42  return -1;
43  }
44  return 0;
45 }
46 
47 static const void *
48 nftnl_expr_connlimit_get(const struct nftnl_expr *e, uint16_t type,
49  uint32_t *data_len)
50 {
51  struct nftnl_expr_connlimit *connlimit = nftnl_expr_data(e);
52 
53  switch(type) {
54  case NFTNL_EXPR_CONNLIMIT_COUNT:
55  *data_len = sizeof(connlimit->count);
56  return &connlimit->count;
57  case NFTNL_EXPR_CONNLIMIT_FLAGS:
58  *data_len = sizeof(connlimit->flags);
59  return &connlimit->flags;
60  }
61  return NULL;
62 }
63 
64 static int nftnl_expr_connlimit_cb(const struct nlattr *attr, void *data)
65 {
66  const struct nlattr **tb = data;
67  int type = mnl_attr_get_type(attr);
68 
69  if (mnl_attr_type_valid(attr, NFTA_CONNLIMIT_MAX) < 0)
70  return MNL_CB_OK;
71 
72  switch(type) {
73  case NFTA_CONNLIMIT_COUNT:
74  case NFTA_CONNLIMIT_FLAGS:
75  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
76  abi_breakage();
77  break;
78  }
79 
80  tb[type] = attr;
81  return MNL_CB_OK;
82 }
83 
84 static void
85 nftnl_expr_connlimit_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
86 {
87  struct nftnl_expr_connlimit *connlimit = nftnl_expr_data(e);
88 
89  if (e->flags & (1 << NFTNL_EXPR_CONNLIMIT_COUNT))
90  mnl_attr_put_u32(nlh, NFTA_CONNLIMIT_COUNT,
91  htonl(connlimit->count));
92  if (e->flags & (1 << NFTNL_EXPR_CONNLIMIT_FLAGS))
93  mnl_attr_put_u32(nlh, NFTA_CONNLIMIT_FLAGS,
94  htonl(connlimit->flags));
95 }
96 
97 static int
98 nftnl_expr_connlimit_parse(struct nftnl_expr *e, struct nlattr *attr)
99 {
100  struct nftnl_expr_connlimit *connlimit = nftnl_expr_data(e);
101  struct nlattr *tb[NFTA_CONNLIMIT_MAX+1] = {};
102 
103  if (mnl_attr_parse_nested(attr, nftnl_expr_connlimit_cb, tb) < 0)
104  return -1;
105 
106  if (tb[NFTA_CONNLIMIT_COUNT]) {
107  connlimit->count =
108  ntohl(mnl_attr_get_u32(tb[NFTA_CONNLIMIT_COUNT]));
109  e->flags |= (1 << NFTNL_EXPR_CONNLIMIT_COUNT);
110  }
111  if (tb[NFTA_CONNLIMIT_FLAGS]) {
112  connlimit->flags =
113  ntohl(mnl_attr_get_u32(tb[NFTA_CONNLIMIT_FLAGS]));
114  e->flags |= (1 << NFTNL_EXPR_CONNLIMIT_FLAGS);
115  }
116 
117  return 0;
118 }
119 
120 static int nftnl_expr_connlimit_snprintf_default(char *buf, size_t len,
121  const struct nftnl_expr *e)
122 {
123  struct nftnl_expr_connlimit *connlimit = nftnl_expr_data(e);
124 
125  return snprintf(buf, len, "count %u flags %x ",
126  connlimit->count, connlimit->flags);
127 }
128 
129 static int nftnl_expr_connlimit_snprintf(char *buf, size_t len, uint32_t type,
130  uint32_t flags,
131  const struct nftnl_expr *e)
132 {
133  switch (type) {
134  case NFTNL_OUTPUT_DEFAULT:
135  return nftnl_expr_connlimit_snprintf_default(buf, len, e);
136  case NFTNL_OUTPUT_XML:
137  case NFTNL_OUTPUT_JSON:
138  default:
139  break;
140  }
141  return -1;
142 }
143 
144 struct expr_ops expr_ops_connlimit = {
145  .name = "connlimit",
146  .alloc_len = sizeof(struct nftnl_expr_connlimit),
147  .max_attr = NFTA_CONNLIMIT_MAX,
148  .set = nftnl_expr_connlimit_set,
149  .get = nftnl_expr_connlimit_get,
150  .parse = nftnl_expr_connlimit_parse,
151  .build = nftnl_expr_connlimit_build,
152  .snprintf = nftnl_expr_connlimit_snprintf,
153 };