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