libnftnl  1.2.6
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 nftnl_expr_osf_set(struct nftnl_expr *e, uint16_t type,
22  const void *data, uint32_t data_len)
23 {
24  struct nftnl_expr_osf *osf = nftnl_expr_data(e);
25 
26  switch(type) {
27  case NFTNL_EXPR_OSF_DREG:
28  memcpy(&osf->dreg, data, sizeof(osf->dreg));
29  break;
30  case NFTNL_EXPR_OSF_TTL:
31  memcpy(&osf->ttl, data, sizeof(osf->ttl));
32  break;
33  case NFTNL_EXPR_OSF_FLAGS:
34  memcpy(&osf->flags, data, sizeof(osf->flags));
35  break;
36  }
37  return 0;
38 }
39 
40 static const void *
41 nftnl_expr_osf_get(const struct nftnl_expr *e, uint16_t type,
42  uint32_t *data_len)
43 {
44  struct nftnl_expr_osf *osf = nftnl_expr_data(e);
45 
46  switch(type) {
47  case NFTNL_EXPR_OSF_DREG:
48  *data_len = sizeof(osf->dreg);
49  return &osf->dreg;
50  case NFTNL_EXPR_OSF_TTL:
51  *data_len = sizeof(osf->ttl);
52  return &osf->ttl;
53  case NFTNL_EXPR_OSF_FLAGS:
54  *data_len = sizeof(osf->flags);
55  return &osf->flags;
56  }
57  return NULL;
58 }
59 
60 static int nftnl_expr_osf_cb(const struct nlattr *attr, void *data)
61 {
62  const struct nlattr **tb = data;
63  int type = mnl_attr_get_type(attr);
64 
65  if (mnl_attr_type_valid(attr, NFTA_OSF_MAX) < 0)
66  return MNL_CB_OK;
67 
68  switch(type) {
69  case NFTNL_EXPR_OSF_DREG:
70  case NFTNL_EXPR_OSF_FLAGS:
71  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
72  abi_breakage();
73  break;
74 
75  case NFTNL_EXPR_OSF_TTL:
76  if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
77  abi_breakage();
78  break;
79 
80  }
81 
82  tb[type] = attr;
83  return MNL_CB_OK;
84 }
85 
86 static void
87 nftnl_expr_osf_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
88 {
89  struct nftnl_expr_osf *osf = nftnl_expr_data(e);
90 
91  if (e->flags & (1 << NFTNL_EXPR_OSF_DREG))
92  mnl_attr_put_u32(nlh, NFTNL_EXPR_OSF_DREG, htonl(osf->dreg));
93  if (e->flags & (1 << NFTNL_EXPR_OSF_TTL))
94  mnl_attr_put_u8(nlh, NFTNL_EXPR_OSF_TTL, osf->ttl);
95  if (e->flags & (1 << NFTNL_EXPR_OSF_FLAGS))
96  if (osf->flags)
97  mnl_attr_put_u32(nlh, NFTNL_EXPR_OSF_FLAGS, htonl(osf->flags));
98 }
99 
100 static int
101 nftnl_expr_osf_parse(struct nftnl_expr *e, struct nlattr *attr)
102 {
103  struct nftnl_expr_osf *osf = nftnl_expr_data(e);
104  struct nlattr *tb[NFTA_OSF_MAX + 1] = {};
105 
106  if (mnl_attr_parse_nested(attr, nftnl_expr_osf_cb, tb) < 0)
107  return -1;
108 
109  if (tb[NFTA_OSF_DREG]) {
110  osf->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_OSF_DREG]));
111  e->flags |= (1 << NFTNL_EXPR_OSF_DREG);
112  }
113 
114  if (tb[NFTA_OSF_TTL]) {
115  osf->ttl = mnl_attr_get_u8(tb[NFTA_OSF_TTL]);
116  e->flags |= (1 << NFTNL_EXPR_OSF_TTL);
117  }
118 
119  if (tb[NFTA_OSF_FLAGS]) {
120  osf->flags = ntohl(mnl_attr_get_u32(tb[NFTA_OSF_FLAGS]));
121  e->flags |= (1 << NFTNL_EXPR_OSF_FLAGS);
122  }
123 
124  return 0;
125 }
126 
127 static int
128 nftnl_expr_osf_snprintf(char *buf, size_t len,
129  uint32_t flags, const struct nftnl_expr *e)
130 {
131  struct nftnl_expr_osf *osf = nftnl_expr_data(e);
132  int ret, offset = 0;
133 
134  if (e->flags & (1 << NFTNL_EXPR_OSF_DREG)) {
135  ret = snprintf(buf, len, "dreg %u ", osf->dreg);
136  SNPRINTF_BUFFER_SIZE(ret, len, offset);
137  }
138 
139  return offset;
140 }
141 
142 struct expr_ops expr_ops_osf = {
143  .name = "osf",
144  .alloc_len = sizeof(struct nftnl_expr_osf),
145  .max_attr = NFTA_OSF_MAX,
146  .set = nftnl_expr_osf_set,
147  .get = nftnl_expr_osf_get,
148  .parse = nftnl_expr_osf_parse,
149  .build = nftnl_expr_osf_build,
150  .output = nftnl_expr_osf_snprintf,
151 };