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