1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3 * Copyright (c) 2013 Sassano Systems LLC <[email protected]>
4 */
5
6 #include "nl-default.h"
7
8 #include <linux/inet_diag.h>
9
10 #include <netlink/idiag/req.h>
11 #include <netlink/idiag/idiagnl.h>
12 #include <netlink/data.h>
13 #include <netlink/addr.h>
14 #include <netlink/msg.h>
15
16 #include "nl-priv-dynamic-core/object-api.h"
17
18 struct idiagnl_req {
19 NLHDR_COMMON
20
21 uint8_t idiag_family;
22 uint8_t idiag_ext;
23 struct nl_addr * idiag_src;
24 struct nl_addr * idiag_dst;
25 uint32_t idiag_ifindex;
26 uint32_t idiag_states;
27 uint32_t idiag_dbs;
28 };
29
30 /**
31 * @ingroup idiag
32 * @defgroup idiagnl_req Inet Diag Requests
33 *
34 * @details
35 * @idiagnl_doc{idiagnl_req, Inet Diag Request Documentation}
36 * @{
37 */
idiagnl_req_alloc(void)38 struct idiagnl_req *idiagnl_req_alloc(void)
39 {
40 return (struct idiagnl_req *) nl_object_alloc(&idiagnl_req_obj_ops);
41 }
42
idiagnl_req_get(struct idiagnl_req * req)43 void idiagnl_req_get(struct idiagnl_req *req)
44 {
45 nl_object_get((struct nl_object *) req);
46 }
47
idiagnl_req_put(struct idiagnl_req * req)48 void idiagnl_req_put(struct idiagnl_req *req)
49 {
50 nl_object_put((struct nl_object *) req);
51 }
52
53 /**
54 * @name Attributes
55 * @{
56 */
57
idiagnl_req_get_family(const struct idiagnl_req * req)58 uint8_t idiagnl_req_get_family(const struct idiagnl_req *req)
59 {
60 return req->idiag_family;
61 }
62
idiagnl_req_set_family(struct idiagnl_req * req,uint8_t family)63 void idiagnl_req_set_family(struct idiagnl_req *req, uint8_t family)
64 {
65 req->idiag_family = family;
66 }
67
idiagnl_req_get_ext(const struct idiagnl_req * req)68 uint8_t idiagnl_req_get_ext(const struct idiagnl_req *req)
69 {
70 return req->idiag_ext;
71 }
72
idiagnl_req_set_ext(struct idiagnl_req * req,uint8_t ext)73 void idiagnl_req_set_ext(struct idiagnl_req *req, uint8_t ext)
74 {
75 req->idiag_ext = ext;
76 }
77
idiagnl_req_get_ifindex(const struct idiagnl_req * req)78 uint32_t idiagnl_req_get_ifindex(const struct idiagnl_req *req)
79 {
80 return req->idiag_ifindex;
81 }
82
idiagnl_req_set_ifindex(struct idiagnl_req * req,uint32_t ifindex)83 void idiagnl_req_set_ifindex(struct idiagnl_req *req, uint32_t ifindex)
84 {
85 req->idiag_ifindex = ifindex;
86 }
87
idiagnl_req_get_states(const struct idiagnl_req * req)88 uint32_t idiagnl_req_get_states(const struct idiagnl_req *req)
89 {
90 return req->idiag_states;
91 }
92
idiagnl_req_set_states(struct idiagnl_req * req,uint32_t states)93 void idiagnl_req_set_states(struct idiagnl_req *req, uint32_t states)
94 {
95 req->idiag_states = states;
96 }
97
idiagnl_req_get_dbs(const struct idiagnl_req * req)98 uint32_t idiagnl_req_get_dbs(const struct idiagnl_req *req)
99 {
100 return req->idiag_dbs;
101 }
102
idiagnl_req_set_dbs(struct idiagnl_req * req,uint32_t dbs)103 void idiagnl_req_set_dbs(struct idiagnl_req *req, uint32_t dbs)
104 {
105 req->idiag_dbs = dbs;
106 }
107
idiagnl_req_get_src(const struct idiagnl_req * req)108 struct nl_addr *idiagnl_req_get_src(const struct idiagnl_req *req)
109 {
110 return req->idiag_src;
111 }
112
idiagnl_req_set_src(struct idiagnl_req * req,struct nl_addr * addr)113 int idiagnl_req_set_src(struct idiagnl_req *req, struct nl_addr *addr)
114 {
115 if (req->idiag_src)
116 nl_addr_put(req->idiag_src);
117
118 nl_addr_get(addr);
119 req->idiag_src = addr;
120
121 return 0;
122 }
123
idiagnl_req_get_dst(const struct idiagnl_req * req)124 struct nl_addr *idiagnl_req_get_dst(const struct idiagnl_req *req)
125 {
126 return req->idiag_dst;
127 }
128
idiagnl_req_set_dst(struct idiagnl_req * req,struct nl_addr * addr)129 int idiagnl_req_set_dst(struct idiagnl_req *req, struct nl_addr *addr)
130 {
131 if (req->idiag_dst)
132 nl_addr_put(req->idiag_dst);
133
134 nl_addr_get(addr);
135 req->idiag_dst = addr;
136
137 return 0;
138 }
139
140 /** @} */
141
idiag_req_dump_line(struct nl_object * a,struct nl_dump_params * p)142 static void idiag_req_dump_line(struct nl_object *a, struct nl_dump_params *p)
143 {
144 struct idiagnl_req *req = (struct idiagnl_req *) a;
145 char buf[64] = { 0 };
146
147 nl_dump_line(p, "%s ", nl_af2str(req->idiag_family, buf, sizeof(buf)));
148 nl_dump(p, "src %s ", nl_addr2str(req->idiag_src, buf, sizeof(buf)));
149 nl_dump(p, "dst %s ", nl_addr2str(req->idiag_dst, buf, sizeof(buf)));
150 nl_dump(p, "iif %d ", req->idiag_ifindex);
151 nl_dump(p, "\n");
152 }
153
idiag_req_dump_details(struct nl_object * a,struct nl_dump_params * p)154 static void idiag_req_dump_details(struct nl_object *a, struct nl_dump_params *p)
155 {
156 struct idiagnl_req *req = (struct idiagnl_req *) a;
157 char buf[64];
158
159 nl_dump_line(p, " ");
160 nl_dump(p, "%s ", nl_af2str(req->idiag_family, buf, sizeof(buf)));
161 nl_dump(p, "exts %s ",
162 idiagnl_exts2str(req->idiag_ext, buf, sizeof(buf)));
163 nl_dump(p, "src %s ", nl_addr2str(req->idiag_src, buf, sizeof(buf)));
164 nl_dump(p, "dst %s ", nl_addr2str(req->idiag_dst, buf, sizeof(buf)));
165 nl_dump(p, "iif %d ", req->idiag_ifindex);
166 nl_dump(p, "states %s ", idiagnl_state2str(req->idiag_states, buf,
167 sizeof(buf)));
168 nl_dump(p, "dbs %d", req->idiag_dbs);
169 nl_dump(p, "\n");
170 }
171
idiag_req_dump_stats(struct nl_object * obj,struct nl_dump_params * p)172 static void idiag_req_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
173 {
174 idiag_req_dump_details(obj, p);
175 }
176
idiagnl_req_free(struct nl_object * a)177 static void idiagnl_req_free(struct nl_object *a)
178 {
179 struct idiagnl_req *req = (struct idiagnl_req *) a;
180 if (a == NULL)
181 return;
182
183 nl_addr_put(req->idiag_src);
184 nl_addr_put(req->idiag_dst);
185 }
186
idiagnl_req_clone(struct nl_object * _dst,struct nl_object * _src)187 static int idiagnl_req_clone(struct nl_object *_dst, struct nl_object *_src)
188 {
189 struct idiagnl_req *dst = (struct idiagnl_req *) _dst;
190 struct idiagnl_req *src = (struct idiagnl_req *) _src;
191
192 src->idiag_src = NULL;
193 src->idiag_dst = NULL;
194
195 if (src->idiag_src)
196 if (!(dst->idiag_src = nl_addr_clone(src->idiag_src)))
197 return -NLE_NOMEM;
198
199 if (src->idiag_dst)
200 if (!(dst->idiag_dst = nl_addr_clone(src->idiag_dst)))
201 return -NLE_NOMEM;
202
203 return 0;
204 }
205
idiagnl_req_parse(struct nlmsghdr * nlh,struct idiagnl_req ** result)206 int idiagnl_req_parse(struct nlmsghdr *nlh, struct idiagnl_req **result)
207 {
208 struct idiagnl_req *req = NULL;
209 struct inet_diag_req *raw_req = NULL;
210 struct nl_addr *src = NULL, *dst = NULL;
211 int err = 0;
212
213 req = idiagnl_req_alloc();
214 if (!req)
215 goto errout_nomem;
216
217 raw_req = nlmsg_data(nlh);
218 req->idiag_family = raw_req->idiag_family;
219 req->idiag_ext = raw_req->idiag_ext;
220 req->idiag_states = raw_req->idiag_states;
221 req->idiag_dbs = raw_req->idiag_dbs;
222 req->idiag_ifindex = raw_req->id.idiag_if;
223
224 dst = nl_addr_build(raw_req->idiag_family, raw_req->id.idiag_dst,
225 sizeof(raw_req->id.idiag_dst));
226 if (!dst)
227 goto errout_nomem;
228
229 err = idiagnl_req_set_dst(req, dst);
230 if (err < 0)
231 goto errout;
232
233 nl_addr_put(dst);
234
235 src = nl_addr_build(raw_req->idiag_family, raw_req->id.idiag_src,
236 sizeof(raw_req->id.idiag_src));
237 if (!src)
238 goto errout_nomem;
239
240 err = idiagnl_req_set_src(req, src);
241 if (err < 0)
242 goto errout;
243
244 nl_addr_put(src);
245
246 *result = req;
247 return 0;
248
249 errout:
250 idiagnl_req_put(req);
251 return err;
252
253 errout_nomem:
254 err = -NLE_NOMEM;
255 goto errout;
256 }
257
258 /** @cond SKIP */
259 struct nl_object_ops idiagnl_req_obj_ops = {
260 .oo_name = "idiag/idiag_req",
261 .oo_size = sizeof(struct idiagnl_req),
262 .oo_free_data = idiagnl_req_free,
263 .oo_clone = idiagnl_req_clone,
264 .oo_dump = {
265 [NL_DUMP_LINE] = idiag_req_dump_line,
266 [NL_DUMP_DETAILS] = idiag_req_dump_details,
267 [NL_DUMP_STATS] = idiag_req_dump_stats,
268 },
269 };
270 /** @endcond */
271
272 /** @} */
273