libnftnl 1.2.7
obj/limit.c
1/*
2 * Copyright (c) 2017 Pablo M. Bermudo Garay <pablombg@gmail.com>
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/object.h>
21
22#include "obj.h"
23
24static int nftnl_obj_limit_set(struct nftnl_obj *e, uint16_t type,
25 const void *data, uint32_t data_len)
26{
27 struct nftnl_obj_limit *limit = nftnl_obj_data(e);
28
29 switch (type) {
30 case NFTNL_OBJ_LIMIT_RATE:
31 memcpy(&limit->rate, data, data_len);
32 break;
33 case NFTNL_OBJ_LIMIT_UNIT:
34 memcpy(&limit->unit, data, data_len);
35 break;
36 case NFTNL_OBJ_LIMIT_BURST:
37 memcpy(&limit->burst, data, data_len);
38 break;
39 case NFTNL_OBJ_LIMIT_TYPE:
40 memcpy(&limit->type, data, data_len);
41 break;
42 case NFTNL_OBJ_LIMIT_FLAGS:
43 memcpy(&limit->flags, data, data_len);
44 break;
45 }
46 return 0;
47}
48
49static const void *nftnl_obj_limit_get(const struct nftnl_obj *e,
50 uint16_t type, uint32_t *data_len)
51{
52 struct nftnl_obj_limit *limit = nftnl_obj_data(e);
53
54 switch (type) {
55 case NFTNL_OBJ_LIMIT_RATE:
56 *data_len = sizeof(limit->rate);
57 return &limit->rate;
58 case NFTNL_OBJ_LIMIT_UNIT:
59 *data_len = sizeof(limit->unit);
60 return &limit->unit;
61 case NFTNL_OBJ_LIMIT_BURST:
62 *data_len = sizeof(limit->burst);
63 return &limit->burst;
64 case NFTNL_OBJ_LIMIT_TYPE:
65 *data_len = sizeof(limit->type);
66 return &limit->type;
67 case NFTNL_OBJ_LIMIT_FLAGS:
68 *data_len = sizeof(limit->flags);
69 return &limit->flags;
70 }
71 return NULL;
72}
73
74static int nftnl_obj_limit_cb(const struct nlattr *attr, void *data)
75{
76 int type = mnl_attr_get_type(attr);
77 const struct nlattr **tb = data;
78
79 if (mnl_attr_type_valid(attr, NFTA_LIMIT_MAX) < 0)
80 return MNL_CB_OK;
81
82 switch (type) {
83 case NFTA_LIMIT_RATE:
84 case NFTA_LIMIT_UNIT:
85 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
86 abi_breakage();
87 break;
88 case NFTA_LIMIT_BURST:
89 case NFTA_LIMIT_TYPE:
90 case NFTA_LIMIT_FLAGS:
91 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
92 abi_breakage();
93 break;
94 }
95
96 tb[type] = attr;
97 return MNL_CB_OK;
98}
99
100static void nftnl_obj_limit_build(struct nlmsghdr *nlh,
101 const struct nftnl_obj *e)
102{
103 struct nftnl_obj_limit *limit = nftnl_obj_data(e);
104
105 if (e->flags & (1 << NFTNL_OBJ_LIMIT_RATE))
106 mnl_attr_put_u64(nlh, NFTA_LIMIT_RATE, htobe64(limit->rate));
107 if (e->flags & (1 << NFTNL_OBJ_LIMIT_UNIT))
108 mnl_attr_put_u64(nlh, NFTA_LIMIT_UNIT, htobe64(limit->unit));
109 if (e->flags & (1 << NFTNL_OBJ_LIMIT_BURST))
110 mnl_attr_put_u32(nlh, NFTA_LIMIT_BURST, htonl(limit->burst));
111 if (e->flags & (1 << NFTNL_OBJ_LIMIT_TYPE))
112 mnl_attr_put_u32(nlh, NFTA_LIMIT_TYPE, htonl(limit->type));
113 if (e->flags & (1 << NFTNL_OBJ_LIMIT_FLAGS))
114 mnl_attr_put_u32(nlh, NFTA_LIMIT_FLAGS, htonl(limit->flags));
115}
116
117static int nftnl_obj_limit_parse(struct nftnl_obj *e, struct nlattr *attr)
118{
119 struct nftnl_obj_limit *limit = nftnl_obj_data(e);
120 struct nlattr *tb[NFTA_LIMIT_MAX + 1] = {};
121
122 if (mnl_attr_parse_nested(attr, nftnl_obj_limit_cb, tb) < 0)
123 return -1;
124
125 if (tb[NFTA_LIMIT_RATE]) {
126 limit->rate = be64toh(mnl_attr_get_u64(tb[NFTA_LIMIT_RATE]));
127 e->flags |= (1 << NFTNL_OBJ_LIMIT_RATE);
128 }
129 if (tb[NFTA_LIMIT_UNIT]) {
130 limit->unit = be64toh(mnl_attr_get_u64(tb[NFTA_LIMIT_UNIT]));
131 e->flags |= (1 << NFTNL_OBJ_LIMIT_UNIT);
132 }
133 if (tb[NFTA_LIMIT_BURST]) {
134 limit->burst = ntohl(mnl_attr_get_u32(tb[NFTA_LIMIT_BURST]));
135 e->flags |= (1 << NFTNL_OBJ_LIMIT_BURST);
136 }
137 if (tb[NFTA_LIMIT_TYPE]) {
138 limit->type = ntohl(mnl_attr_get_u32(tb[NFTA_LIMIT_TYPE]));
139 e->flags |= (1 << NFTNL_OBJ_LIMIT_TYPE);
140 }
141 if (tb[NFTA_LIMIT_FLAGS]) {
142 limit->flags = ntohl(mnl_attr_get_u32(tb[NFTA_LIMIT_FLAGS]));
143 e->flags |= (1 << NFTNL_OBJ_LIMIT_FLAGS);
144 }
145
146 return 0;
147}
148
149static int nftnl_obj_limit_snprintf(char *buf, size_t len,
150 uint32_t flags,
151 const struct nftnl_obj *e)
152{
153 struct nftnl_obj_limit *limit = nftnl_obj_data(e);
154
155 return snprintf(buf, len, "rate %"PRIu64" unit %"PRIu64" burst %u "
156 "type %u flags %u ", limit->rate, limit->unit,
157 limit->burst, limit->type, limit->flags);
158}
159
160static struct attr_policy obj_limit_attr_policy[__NFTNL_OBJ_LIMIT_MAX] = {
161 [NFTNL_OBJ_LIMIT_RATE] = { .maxlen = sizeof(uint64_t) },
162 [NFTNL_OBJ_LIMIT_UNIT] = { .maxlen = sizeof(uint64_t) },
163 [NFTNL_OBJ_LIMIT_BURST] = { .maxlen = sizeof(uint32_t) },
164 [NFTNL_OBJ_LIMIT_TYPE] = { .maxlen = sizeof(uint32_t) },
165 [NFTNL_OBJ_LIMIT_FLAGS] = { .maxlen = sizeof(uint32_t) },
166};
167
168struct obj_ops obj_ops_limit = {
169 .name = "limit",
170 .type = NFT_OBJECT_LIMIT,
171 .alloc_len = sizeof(struct nftnl_obj_limit),
172 .nftnl_max_attr = __NFTNL_OBJ_LIMIT_MAX - 1,
173 .attr_policy = obj_limit_attr_policy,
174 .set = nftnl_obj_limit_set,
175 .get = nftnl_obj_limit_get,
176 .parse = nftnl_obj_limit_parse,
177 .build = nftnl_obj_limit_build,
178 .output = nftnl_obj_limit_snprintf,
179};