libnftnl  1.3.2
osf.c
1 #include <stdio.h>
2 #include <stdint.h>
3 #include <string.h>
4 #include <arpa/inet.h>
5 #include <errno.h>
6 #include <linux/netfilter/nf_tables.h>
7 
8 #include "internal.h"
9 #include <libmnl/libmnl.h>
10 #include <libnftnl/expr.h>
11 #include <libnftnl/rule.h>
12 
13 #define OSF_GENRE_SIZE 32
14 
16  enum nft_registers dreg;
17  uint8_t ttl;
18  uint32_t flags;
19 };
20 
21 static int
22 nftnl_expr_osf_set(struct nftnl_expr *e, uint16_t type,
23  const void *data, uint32_t data_len, uint32_t byteorder)
24 {
25  struct nftnl_expr_osf *osf = nftnl_expr_data(e);
26 
27  switch(type) {
28  case NFTNL_EXPR_OSF_DREG:
29  memcpy(&osf->dreg, data, data_len);
30  break;
31  case NFTNL_EXPR_OSF_TTL:
32  memcpy(&osf->ttl, data, data_len);
33  break;
34  case NFTNL_EXPR_OSF_FLAGS:
35  memcpy(&osf->flags, data, data_len);
36  break;
37  }
38  return 0;
39 }
40 
41 static const void *
42 nftnl_expr_osf_get(const struct nftnl_expr *e, uint16_t type,
43  uint32_t *data_len)
44 {
45  struct nftnl_expr_osf *osf = nftnl_expr_data(e);
46 
47  switch(type) {
48  case NFTNL_EXPR_OSF_DREG:
49  *data_len = sizeof(osf->dreg);
50  return &osf->dreg;
51  case NFTNL_EXPR_OSF_TTL:
52  *data_len = sizeof(osf->ttl);
53  return &osf->ttl;
54  case NFTNL_EXPR_OSF_FLAGS:
55  *data_len = sizeof(osf->flags);
56  return &osf->flags;
57  }
58  return NULL;
59 }
60 
61 static int nftnl_expr_osf_cb(const struct nlattr *attr, void *data)
62 {
63  const struct nlattr **tb = data;
64  int type = mnl_attr_get_type(attr);
65 
66  if (mnl_attr_type_valid(attr, NFTA_OSF_MAX) < 0)
67  return MNL_CB_OK;
68 
69  switch(type) {
70  case NFTNL_EXPR_OSF_DREG:
71  case NFTNL_EXPR_OSF_FLAGS:
72  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
73  abi_breakage();
74  break;
75 
76  case NFTNL_EXPR_OSF_TTL:
77  if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
78  abi_breakage();
79  break;
80 
81  }
82 
83  tb[type] = attr;
84  return MNL_CB_OK;
85 }
86 
87 static void
88 nftnl_expr_osf_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
89 {
90  struct nftnl_expr_osf *osf = nftnl_expr_data(e);
91 
92  if (e->flags & (1 << NFTNL_EXPR_OSF_DREG))
93  mnl_attr_put_u32(nlh, NFTA_OSF_DREG, htonl(osf->dreg));
94  if (e->flags & (1 << NFTNL_EXPR_OSF_TTL))
95  mnl_attr_put_u8(nlh, NFTA_OSF_TTL, osf->ttl);
96  if (e->flags & (1 << NFTNL_EXPR_OSF_FLAGS))
97  if (osf->flags)
98  mnl_attr_put_u32(nlh, NFTA_OSF_FLAGS, htonl(osf->flags));
99 }
100 
101 static int
102 nftnl_expr_osf_parse(struct nftnl_expr *e, struct nlattr *attr)
103 {
104  struct nftnl_expr_osf *osf = nftnl_expr_data(e);
105  struct nlattr *tb[NFTA_OSF_MAX + 1] = {};
106 
107  if (mnl_attr_parse_nested(attr, nftnl_expr_osf_cb, tb) < 0)
108  return -1;
109 
110  if (tb[NFTA_OSF_DREG]) {
111  osf->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_OSF_DREG]));
112  e->flags |= (1 << NFTNL_EXPR_OSF_DREG);
113  }
114 
115  if (tb[NFTA_OSF_TTL]) {
116  osf->ttl = mnl_attr_get_u8(tb[NFTA_OSF_TTL]);
117  e->flags |= (1 << NFTNL_EXPR_OSF_TTL);
118  }
119 
120  if (tb[NFTA_OSF_FLAGS]) {
121  osf->flags = ntohl(mnl_attr_get_u32(tb[NFTA_OSF_FLAGS]));
122  e->flags |= (1 << NFTNL_EXPR_OSF_FLAGS);
123  }
124 
125  return 0;
126 }
127 
128 static int
129 nftnl_expr_osf_snprintf(char *buf, size_t len,
130  uint32_t flags, const struct nftnl_expr *e)
131 {
132  struct nftnl_expr_osf *osf = nftnl_expr_data(e);
133  int ret, offset = 0;
134 
135  if (e->flags & (1 << NFTNL_EXPR_OSF_DREG)) {
136  ret = snprintf(buf, len, "dreg %u ", osf->dreg);
137  SNPRINTF_BUFFER_SIZE(ret, len, offset);
138  }
139 
140  return offset;
141 }
142 
143 static struct attr_policy osf_attr_policy[__NFTNL_EXPR_OSF_MAX] = {
144  [NFTNL_EXPR_OSF_DREG] = { .maxlen = sizeof(uint32_t) },
145  [NFTNL_EXPR_OSF_TTL] = { .maxlen = sizeof(uint8_t) },
146  [NFTNL_EXPR_OSF_FLAGS] = { .maxlen = sizeof(uint32_t) },
147 };
148 
149 struct expr_ops expr_ops_osf = {
150  .name = "osf",
151  .alloc_len = sizeof(struct nftnl_expr_osf),
152  .nftnl_max_attr = __NFTNL_EXPR_OSF_MAX - 1,
153  .attr_policy = osf_attr_policy,
154  .set = nftnl_expr_osf_set,
155  .get = nftnl_expr_osf_get,
156  .parse = nftnl_expr_osf_parse,
157  .build = nftnl_expr_osf_build,
158  .output = nftnl_expr_osf_snprintf,
159 };