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