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