xref: /aosp_15_r20/external/libnl/lib/idiag/idiag_req_obj.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
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