]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
89489ef7 TG |
2 | |
3 | #include <netinet/in.h> | |
b43dfb6e | 4 | #include <linux/fib_rules.h> |
30746d60 | 5 | #include <linux/if_addrlabel.h> |
1903c9bb | 6 | #include <linux/if_bridge.h> |
c16c7808 | 7 | #include <linux/nexthop.h> |
89489ef7 TG |
8 | #include <stdbool.h> |
9 | #include <unistd.h> | |
10 | ||
07630cea LP |
11 | #include "sd-netlink.h" |
12 | ||
f97b34a6 | 13 | #include "format-util.h" |
89489ef7 TG |
14 | #include "netlink-internal.h" |
15 | #include "netlink-types.h" | |
07630cea | 16 | #include "netlink-util.h" |
07630cea | 17 | #include "socket-util.h" |
89489ef7 | 18 | |
13c026ca YW |
19 | static bool rtnl_message_type_is_neigh(uint16_t type) { |
20 | return IN_SET(type, RTM_NEWNEIGH, RTM_GETNEIGH, RTM_DELNEIGH); | |
21 | } | |
22 | ||
23 | static bool rtnl_message_type_is_route(uint16_t type) { | |
24 | return IN_SET(type, RTM_NEWROUTE, RTM_GETROUTE, RTM_DELROUTE); | |
25 | } | |
26 | ||
27 | static bool rtnl_message_type_is_nexthop(uint16_t type) { | |
28 | return IN_SET(type, RTM_NEWNEXTHOP, RTM_GETNEXTHOP, RTM_DELNEXTHOP); | |
29 | } | |
30 | ||
31 | static bool rtnl_message_type_is_link(uint16_t type) { | |
32 | return IN_SET(type, | |
33 | RTM_NEWLINK, RTM_SETLINK, RTM_GETLINK, RTM_DELLINK, | |
34 | RTM_NEWLINKPROP, RTM_DELLINKPROP, RTM_GETLINKPROP); | |
35 | } | |
36 | ||
37 | static bool rtnl_message_type_is_addr(uint16_t type) { | |
38 | return IN_SET(type, RTM_NEWADDR, RTM_GETADDR, RTM_DELADDR); | |
39 | } | |
40 | ||
41 | static bool rtnl_message_type_is_addrlabel(uint16_t type) { | |
42 | return IN_SET(type, RTM_NEWADDRLABEL, RTM_DELADDRLABEL, RTM_GETADDRLABEL); | |
43 | } | |
44 | ||
45 | static bool rtnl_message_type_is_routing_policy_rule(uint16_t type) { | |
46 | return IN_SET(type, RTM_NEWRULE, RTM_DELRULE, RTM_GETRULE); | |
47 | } | |
48 | ||
49 | static bool rtnl_message_type_is_traffic_control(uint16_t type) { | |
50 | return IN_SET(type, | |
51 | RTM_NEWQDISC, RTM_DELQDISC, RTM_GETQDISC, | |
52 | RTM_NEWTCLASS, RTM_DELTCLASS, RTM_GETTCLASS); | |
53 | } | |
54 | ||
55 | static bool rtnl_message_type_is_mdb(uint16_t type) { | |
56 | return IN_SET(type, RTM_NEWMDB, RTM_DELMDB, RTM_GETMDB); | |
57 | } | |
58 | ||
dd35a61c | 59 | int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char prefixlen) { |
89489ef7 TG |
60 | struct rtmsg *rtm; |
61 | ||
62 | assert_return(m, -EINVAL); | |
63 | assert_return(m->hdr, -EINVAL); | |
64 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
65 | ||
66 | rtm = NLMSG_DATA(m->hdr); | |
67 | ||
68 | if ((rtm->rtm_family == AF_INET && prefixlen > 32) || | |
69 | (rtm->rtm_family == AF_INET6 && prefixlen > 128)) | |
70 | return -ERANGE; | |
71 | ||
72 | rtm->rtm_dst_len = prefixlen; | |
73 | ||
74 | return 0; | |
75 | } | |
76 | ||
dd35a61c | 77 | int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char prefixlen) { |
89489ef7 TG |
78 | struct rtmsg *rtm; |
79 | ||
80 | assert_return(m, -EINVAL); | |
81 | assert_return(m->hdr, -EINVAL); | |
82 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
83 | ||
84 | rtm = NLMSG_DATA(m->hdr); | |
85 | ||
86 | if ((rtm->rtm_family == AF_INET && prefixlen > 32) || | |
87 | (rtm->rtm_family == AF_INET6 && prefixlen > 128)) | |
88 | return -ERANGE; | |
89 | ||
90 | rtm->rtm_src_len = prefixlen; | |
91 | ||
92 | return 0; | |
93 | } | |
94 | ||
ef4e0b7e YW |
95 | int sd_rtnl_message_route_set_tos(sd_netlink_message *m, unsigned char tos) { |
96 | struct rtmsg *rtm; | |
97 | ||
98 | assert_return(m, -EINVAL); | |
99 | assert_return(m->hdr, -EINVAL); | |
100 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
101 | ||
102 | rtm = NLMSG_DATA(m->hdr); | |
103 | ||
104 | rtm->rtm_tos = tos; | |
105 | ||
106 | return 0; | |
107 | } | |
108 | ||
dd35a61c | 109 | int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope) { |
89489ef7 TG |
110 | struct rtmsg *rtm; |
111 | ||
112 | assert_return(m, -EINVAL); | |
113 | assert_return(m->hdr, -EINVAL); | |
114 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
115 | ||
116 | rtm = NLMSG_DATA(m->hdr); | |
117 | ||
118 | rtm->rtm_scope = scope; | |
119 | ||
120 | return 0; | |
121 | } | |
122 | ||
dd35a61c | 123 | int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags) { |
6b9e85a7 TG |
124 | struct rtmsg *rtm; |
125 | ||
126 | assert_return(m, -EINVAL); | |
127 | assert_return(m->hdr, -EINVAL); | |
128 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
129 | ||
130 | rtm = NLMSG_DATA(m->hdr); | |
131 | ||
132 | rtm->rtm_flags = flags; | |
133 | ||
134 | return 0; | |
135 | } | |
136 | ||
dd35a61c | 137 | int sd_rtnl_message_route_get_flags(sd_netlink_message *m, unsigned *flags) { |
6b9e85a7 TG |
138 | struct rtmsg *rtm; |
139 | ||
140 | assert_return(m, -EINVAL); | |
141 | assert_return(m->hdr, -EINVAL); | |
142 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
143 | assert_return(flags, -EINVAL); | |
144 | ||
145 | rtm = NLMSG_DATA(m->hdr); | |
146 | ||
147 | *flags = rtm->rtm_flags; | |
148 | ||
149 | return 0; | |
150 | } | |
151 | ||
dd35a61c | 152 | int sd_rtnl_message_route_set_table(sd_netlink_message *m, unsigned char table) { |
ec1bb279 SS |
153 | struct rtmsg *rtm; |
154 | ||
155 | assert_return(m, -EINVAL); | |
156 | assert_return(m->hdr, -EINVAL); | |
157 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
158 | ||
159 | rtm = NLMSG_DATA(m->hdr); | |
160 | ||
161 | rtm->rtm_table = table; | |
162 | ||
163 | return 0; | |
164 | } | |
165 | ||
dd35a61c | 166 | int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family) { |
89489ef7 TG |
167 | struct rtmsg *rtm; |
168 | ||
169 | assert_return(m, -EINVAL); | |
170 | assert_return(m->hdr, -EINVAL); | |
171 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
172 | assert_return(family, -EINVAL); | |
173 | ||
174 | rtm = NLMSG_DATA(m->hdr); | |
175 | ||
176 | *family = rtm->rtm_family; | |
177 | ||
178 | return 0; | |
179 | } | |
180 | ||
dd35a61c | 181 | int sd_rtnl_message_route_get_type(sd_netlink_message *m, unsigned char *type) { |
983226f3 SS |
182 | struct rtmsg *rtm; |
183 | ||
184 | assert_return(m, -EINVAL); | |
185 | assert_return(m->hdr, -EINVAL); | |
186 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
187 | assert_return(type, -EINVAL); | |
188 | ||
189 | rtm = NLMSG_DATA(m->hdr); | |
190 | ||
191 | *type = rtm->rtm_type; | |
192 | ||
193 | return 0; | |
194 | } | |
195 | ||
dd35a61c | 196 | int sd_rtnl_message_route_set_type(sd_netlink_message *m, unsigned char type) { |
983226f3 SS |
197 | struct rtmsg *rtm; |
198 | ||
199 | assert_return(m, -EINVAL); | |
200 | assert_return(m->hdr, -EINVAL); | |
201 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
202 | ||
203 | rtm = NLMSG_DATA(m->hdr); | |
204 | ||
205 | rtm->rtm_type = type; | |
206 | ||
207 | return 0; | |
208 | } | |
209 | ||
dd35a61c | 210 | int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol) { |
ad70f789 TG |
211 | struct rtmsg *rtm; |
212 | ||
213 | assert_return(m, -EINVAL); | |
214 | assert_return(m->hdr, -EINVAL); | |
215 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
216 | assert_return(protocol, -EINVAL); | |
217 | ||
218 | rtm = NLMSG_DATA(m->hdr); | |
219 | ||
220 | *protocol = rtm->rtm_protocol; | |
221 | ||
222 | return 0; | |
223 | } | |
224 | ||
dd35a61c | 225 | int sd_rtnl_message_route_get_scope(sd_netlink_message *m, unsigned char *scope) { |
ad70f789 TG |
226 | struct rtmsg *rtm; |
227 | ||
228 | assert_return(m, -EINVAL); | |
229 | assert_return(m->hdr, -EINVAL); | |
230 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
231 | assert_return(scope, -EINVAL); | |
232 | ||
233 | rtm = NLMSG_DATA(m->hdr); | |
234 | ||
235 | *scope = rtm->rtm_scope; | |
236 | ||
237 | return 0; | |
238 | } | |
239 | ||
dd35a61c | 240 | int sd_rtnl_message_route_get_tos(sd_netlink_message *m, uint8_t *tos) { |
ad70f789 TG |
241 | struct rtmsg *rtm; |
242 | ||
243 | assert_return(m, -EINVAL); | |
244 | assert_return(m->hdr, -EINVAL); | |
245 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
246 | assert_return(tos, -EINVAL); | |
247 | ||
248 | rtm = NLMSG_DATA(m->hdr); | |
249 | ||
250 | *tos = rtm->rtm_tos; | |
251 | ||
252 | return 0; | |
253 | } | |
254 | ||
dd35a61c | 255 | int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table) { |
ad70f789 TG |
256 | struct rtmsg *rtm; |
257 | ||
258 | assert_return(m, -EINVAL); | |
259 | assert_return(m->hdr, -EINVAL); | |
260 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
261 | assert_return(table, -EINVAL); | |
262 | ||
263 | rtm = NLMSG_DATA(m->hdr); | |
264 | ||
265 | *table = rtm->rtm_table; | |
266 | ||
267 | return 0; | |
268 | } | |
269 | ||
dd35a61c | 270 | int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char *dst_len) { |
89489ef7 TG |
271 | struct rtmsg *rtm; |
272 | ||
273 | assert_return(m, -EINVAL); | |
274 | assert_return(m->hdr, -EINVAL); | |
275 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
276 | assert_return(dst_len, -EINVAL); | |
277 | ||
278 | rtm = NLMSG_DATA(m->hdr); | |
279 | ||
280 | *dst_len = rtm->rtm_dst_len; | |
281 | ||
282 | return 0; | |
283 | } | |
284 | ||
dd35a61c | 285 | int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len) { |
89489ef7 TG |
286 | struct rtmsg *rtm; |
287 | ||
288 | assert_return(m, -EINVAL); | |
289 | assert_return(m->hdr, -EINVAL); | |
290 | assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL); | |
291 | assert_return(src_len, -EINVAL); | |
292 | ||
293 | rtm = NLMSG_DATA(m->hdr); | |
294 | ||
295 | *src_len = rtm->rtm_src_len; | |
296 | ||
297 | return 0; | |
298 | } | |
299 | ||
dd35a61c | 300 | int sd_rtnl_message_new_route(sd_netlink *rtnl, sd_netlink_message **ret, |
89489ef7 TG |
301 | uint16_t nlmsg_type, int rtm_family, |
302 | unsigned char rtm_protocol) { | |
303 | struct rtmsg *rtm; | |
304 | int r; | |
305 | ||
306 | assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL); | |
307 | assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) || | |
945c2931 | 308 | IN_SET(rtm_family, AF_INET, AF_INET6), -EINVAL); |
89489ef7 TG |
309 | assert_return(ret, -EINVAL); |
310 | ||
311 | r = message_new(rtnl, ret, nlmsg_type); | |
312 | if (r < 0) | |
313 | return r; | |
314 | ||
315 | if (nlmsg_type == RTM_NEWROUTE) | |
316 | (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND; | |
317 | ||
318 | rtm = NLMSG_DATA((*ret)->hdr); | |
319 | ||
320 | rtm->rtm_family = rtm_family; | |
89489ef7 TG |
321 | rtm->rtm_protocol = rtm_protocol; |
322 | ||
323 | return 0; | |
324 | } | |
325 | ||
dd35a61c | 326 | int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret, |
409856d3 | 327 | uint16_t nlmsg_type, int nh_family, |
c16c7808 SS |
328 | unsigned char nh_protocol) { |
329 | struct nhmsg *nhm; | |
330 | int r; | |
331 | ||
409856d3 | 332 | assert_return(rtnl_message_type_is_nexthop(nlmsg_type), -EINVAL); |
79893116 | 333 | switch (nlmsg_type) { |
735a3d73 YW |
334 | case RTM_DELNEXTHOP: |
335 | assert_return(nh_family == AF_UNSPEC, -EINVAL); | |
336 | _fallthrough_; | |
337 | case RTM_GETNEXTHOP: | |
338 | assert_return(nh_protocol == RTPROT_UNSPEC, -EINVAL); | |
339 | break; | |
340 | case RTM_NEWNEXTHOP: | |
341 | assert_return(IN_SET(nh_family, AF_UNSPEC, AF_INET, AF_INET6), -EINVAL); | |
342 | break; | |
343 | default: | |
04499a70 | 344 | assert_not_reached(); |
735a3d73 | 345 | } |
c16c7808 SS |
346 | assert_return(ret, -EINVAL); |
347 | ||
409856d3 | 348 | r = message_new(rtnl, ret, nlmsg_type); |
c16c7808 SS |
349 | if (r < 0) |
350 | return r; | |
351 | ||
409856d3 | 352 | if (nlmsg_type == RTM_NEWNEXTHOP) |
5f6ab795 | 353 | (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; |
c16c7808 SS |
354 | |
355 | nhm = NLMSG_DATA((*ret)->hdr); | |
356 | ||
357 | nhm->nh_family = nh_family; | |
358 | nhm->nh_scope = RT_SCOPE_UNIVERSE; | |
359 | nhm->nh_protocol = nh_protocol; | |
360 | ||
361 | return 0; | |
362 | } | |
363 | ||
dd35a61c | 364 | int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags) { |
c16c7808 SS |
365 | struct nhmsg *nhm; |
366 | ||
367 | assert_return(m, -EINVAL); | |
368 | assert_return(m->hdr, -EINVAL); | |
735a3d73 | 369 | assert_return(m->hdr->nlmsg_type == RTM_NEWNEXTHOP, -EINVAL); |
c16c7808 SS |
370 | |
371 | nhm = NLMSG_DATA(m->hdr); | |
45b1299a | 372 | nhm->nh_flags = flags; |
c16c7808 SS |
373 | |
374 | return 0; | |
375 | } | |
376 | ||
dd35a61c | 377 | int sd_rtnl_message_nexthop_get_flags(sd_netlink_message *m, uint8_t *ret) { |
5bfee718 YW |
378 | struct nhmsg *nhm; |
379 | ||
380 | assert_return(m, -EINVAL); | |
381 | assert_return(m->hdr, -EINVAL); | |
382 | assert_return(rtnl_message_type_is_nexthop(m->hdr->nlmsg_type), -EINVAL); | |
383 | assert_return(ret, -EINVAL); | |
384 | ||
385 | nhm = NLMSG_DATA(m->hdr); | |
386 | *ret = nhm->nh_flags; | |
387 | ||
388 | return 0; | |
389 | } | |
390 | ||
dd35a61c | 391 | int sd_rtnl_message_nexthop_get_family(sd_netlink_message *m, uint8_t *family) { |
c16c7808 SS |
392 | struct nhmsg *nhm; |
393 | ||
394 | assert_return(m, -EINVAL); | |
395 | assert_return(m->hdr, -EINVAL); | |
e64e052e YW |
396 | assert_return(rtnl_message_type_is_nexthop(m->hdr->nlmsg_type), -EINVAL); |
397 | assert_return(family, -EINVAL); | |
c16c7808 SS |
398 | |
399 | nhm = NLMSG_DATA(m->hdr); | |
735a3d73 | 400 | *family = nhm->nh_family; |
c16c7808 SS |
401 | |
402 | return 0; | |
403 | } | |
404 | ||
dd35a61c | 405 | int sd_rtnl_message_nexthop_get_protocol(sd_netlink_message *m, uint8_t *protocol) { |
e64e052e YW |
406 | struct nhmsg *nhm; |
407 | ||
408 | assert_return(m, -EINVAL); | |
409 | assert_return(m->hdr, -EINVAL); | |
410 | assert_return(rtnl_message_type_is_nexthop(m->hdr->nlmsg_type), -EINVAL); | |
411 | assert_return(protocol, -EINVAL); | |
412 | ||
413 | nhm = NLMSG_DATA(m->hdr); | |
414 | *protocol = nhm->nh_protocol; | |
415 | ||
416 | return 0; | |
417 | } | |
418 | ||
dd35a61c | 419 | int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags) { |
89489ef7 TG |
420 | struct ndmsg *ndm; |
421 | ||
422 | assert_return(m, -EINVAL); | |
423 | assert_return(m->hdr, -EINVAL); | |
424 | assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); | |
425 | ||
426 | ndm = NLMSG_DATA(m->hdr); | |
45b1299a | 427 | ndm->ndm_flags = flags; |
89489ef7 TG |
428 | |
429 | return 0; | |
430 | } | |
431 | ||
dd35a61c | 432 | int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state) { |
89489ef7 TG |
433 | struct ndmsg *ndm; |
434 | ||
435 | assert_return(m, -EINVAL); | |
436 | assert_return(m->hdr, -EINVAL); | |
437 | assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); | |
438 | ||
439 | ndm = NLMSG_DATA(m->hdr); | |
45b1299a | 440 | ndm->ndm_state = state; |
89489ef7 TG |
441 | |
442 | return 0; | |
443 | } | |
444 | ||
dd35a61c | 445 | int sd_rtnl_message_neigh_get_flags(sd_netlink_message *m, uint8_t *flags) { |
89489ef7 TG |
446 | struct ndmsg *ndm; |
447 | ||
448 | assert_return(m, -EINVAL); | |
449 | assert_return(m->hdr, -EINVAL); | |
450 | assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); | |
451 | ||
452 | ndm = NLMSG_DATA(m->hdr); | |
453 | *flags = ndm->ndm_flags; | |
454 | ||
455 | return 0; | |
456 | } | |
457 | ||
dd35a61c | 458 | int sd_rtnl_message_neigh_get_state(sd_netlink_message *m, uint16_t *state) { |
89489ef7 TG |
459 | struct ndmsg *ndm; |
460 | ||
461 | assert_return(m, -EINVAL); | |
462 | assert_return(m->hdr, -EINVAL); | |
463 | assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); | |
464 | ||
465 | ndm = NLMSG_DATA(m->hdr); | |
466 | *state = ndm->ndm_state; | |
467 | ||
468 | return 0; | |
469 | } | |
470 | ||
dd35a61c | 471 | int sd_rtnl_message_neigh_get_family(sd_netlink_message *m, int *family) { |
89489ef7 TG |
472 | struct ndmsg *ndm; |
473 | ||
474 | assert_return(m, -EINVAL); | |
475 | assert_return(m->hdr, -EINVAL); | |
476 | assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); | |
477 | assert_return(family, -EINVAL); | |
478 | ||
479 | ndm = NLMSG_DATA(m->hdr); | |
480 | ||
481 | *family = ndm->ndm_family; | |
482 | ||
483 | return 0; | |
484 | } | |
485 | ||
dd35a61c | 486 | int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message *m, int *index) { |
89489ef7 TG |
487 | struct ndmsg *ndm; |
488 | ||
489 | assert_return(m, -EINVAL); | |
490 | assert_return(m->hdr, -EINVAL); | |
491 | assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL); | |
492 | assert_return(index, -EINVAL); | |
493 | ||
494 | ndm = NLMSG_DATA(m->hdr); | |
495 | ||
496 | *index = ndm->ndm_ifindex; | |
497 | ||
498 | return 0; | |
499 | } | |
500 | ||
dd35a61c | 501 | int sd_rtnl_message_new_neigh( |
84e10015 ZJS |
502 | sd_netlink *rtnl, |
503 | sd_netlink_message **ret, | |
504 | uint16_t nlmsg_type, | |
505 | int index, | |
506 | int ndm_family) { | |
507 | ||
89489ef7 TG |
508 | struct ndmsg *ndm; |
509 | int r; | |
510 | ||
511 | assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL); | |
40eb1b0a | 512 | assert_return(IN_SET(ndm_family, AF_UNSPEC, AF_INET, AF_INET6, AF_BRIDGE), -EINVAL); |
89489ef7 TG |
513 | assert_return(ret, -EINVAL); |
514 | ||
515 | r = message_new(rtnl, ret, nlmsg_type); | |
516 | if (r < 0) | |
517 | return r; | |
518 | ||
74c1ab84 YW |
519 | if (nlmsg_type == RTM_NEWNEIGH) { |
520 | if (ndm_family == AF_BRIDGE) | |
521 | (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND; | |
522 | else | |
523 | (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE; | |
524 | } | |
89489ef7 TG |
525 | |
526 | ndm = NLMSG_DATA((*ret)->hdr); | |
527 | ||
528 | ndm->ndm_family = ndm_family; | |
529 | ndm->ndm_ifindex = index; | |
530 | ||
531 | return 0; | |
532 | } | |
533 | ||
dd35a61c | 534 | int sd_rtnl_message_link_set_flags(sd_netlink_message *m, unsigned flags, unsigned change) { |
89489ef7 TG |
535 | struct ifinfomsg *ifi; |
536 | ||
537 | assert_return(m, -EINVAL); | |
538 | assert_return(m->hdr, -EINVAL); | |
539 | assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); | |
22d33e80 | 540 | assert_return(change != 0, -EINVAL); |
89489ef7 TG |
541 | |
542 | ifi = NLMSG_DATA(m->hdr); | |
543 | ||
544 | ifi->ifi_flags = flags; | |
545 | ifi->ifi_change = change; | |
546 | ||
547 | return 0; | |
548 | } | |
549 | ||
dd35a61c | 550 | int sd_rtnl_message_link_set_type(sd_netlink_message *m, unsigned type) { |
89489ef7 TG |
551 | struct ifinfomsg *ifi; |
552 | ||
553 | assert_return(m, -EINVAL); | |
554 | assert_return(m->hdr, -EINVAL); | |
555 | assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); | |
556 | ||
557 | ifi = NLMSG_DATA(m->hdr); | |
558 | ||
559 | ifi->ifi_type = type; | |
560 | ||
561 | return 0; | |
562 | } | |
563 | ||
dd35a61c | 564 | int sd_rtnl_message_link_set_family(sd_netlink_message *m, unsigned family) { |
89489ef7 TG |
565 | struct ifinfomsg *ifi; |
566 | ||
567 | assert_return(m, -EINVAL); | |
568 | assert_return(m->hdr, -EINVAL); | |
569 | assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); | |
570 | ||
571 | ifi = NLMSG_DATA(m->hdr); | |
572 | ||
573 | ifi->ifi_family = family; | |
574 | ||
575 | return 0; | |
576 | } | |
577 | ||
dd35a61c | 578 | int sd_rtnl_message_new_link(sd_netlink *rtnl, sd_netlink_message **ret, |
89489ef7 TG |
579 | uint16_t nlmsg_type, int index) { |
580 | struct ifinfomsg *ifi; | |
581 | int r; | |
582 | ||
583 | assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL); | |
89489ef7 TG |
584 | assert_return(ret, -EINVAL); |
585 | ||
586 | r = message_new(rtnl, ret, nlmsg_type); | |
587 | if (r < 0) | |
588 | return r; | |
589 | ||
590 | if (nlmsg_type == RTM_NEWLINK) | |
591 | (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; | |
a26c3073 YW |
592 | else if (nlmsg_type == RTM_NEWLINKPROP) |
593 | (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL | NLM_F_APPEND; | |
89489ef7 TG |
594 | |
595 | ifi = NLMSG_DATA((*ret)->hdr); | |
596 | ||
597 | ifi->ifi_family = AF_UNSPEC; | |
598 | ifi->ifi_index = index; | |
599 | ||
600 | return 0; | |
601 | } | |
602 | ||
dd35a61c | 603 | int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen) { |
89489ef7 TG |
604 | struct ifaddrmsg *ifa; |
605 | ||
606 | assert_return(m, -EINVAL); | |
607 | assert_return(m->hdr, -EINVAL); | |
608 | assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); | |
609 | ||
610 | ifa = NLMSG_DATA(m->hdr); | |
611 | ||
612 | if ((ifa->ifa_family == AF_INET && prefixlen > 32) || | |
613 | (ifa->ifa_family == AF_INET6 && prefixlen > 128)) | |
614 | return -ERANGE; | |
615 | ||
616 | ifa->ifa_prefixlen = prefixlen; | |
617 | ||
618 | return 0; | |
619 | } | |
620 | ||
dd35a61c | 621 | int sd_rtnl_message_addr_set_flags(sd_netlink_message *m, unsigned char flags) { |
89489ef7 TG |
622 | struct ifaddrmsg *ifa; |
623 | ||
624 | assert_return(m, -EINVAL); | |
625 | assert_return(m->hdr, -EINVAL); | |
626 | assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); | |
627 | ||
628 | ifa = NLMSG_DATA(m->hdr); | |
629 | ||
630 | ifa->ifa_flags = flags; | |
631 | ||
632 | return 0; | |
633 | } | |
634 | ||
dd35a61c | 635 | int sd_rtnl_message_addr_set_scope(sd_netlink_message *m, unsigned char scope) { |
89489ef7 TG |
636 | struct ifaddrmsg *ifa; |
637 | ||
638 | assert_return(m, -EINVAL); | |
639 | assert_return(m->hdr, -EINVAL); | |
640 | assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); | |
641 | ||
642 | ifa = NLMSG_DATA(m->hdr); | |
643 | ||
644 | ifa->ifa_scope = scope; | |
645 | ||
646 | return 0; | |
647 | } | |
648 | ||
dd35a61c | 649 | int sd_rtnl_message_addr_get_family(sd_netlink_message *m, int *ret_family) { |
89489ef7 TG |
650 | struct ifaddrmsg *ifa; |
651 | ||
652 | assert_return(m, -EINVAL); | |
653 | assert_return(m->hdr, -EINVAL); | |
654 | assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); | |
b44662fe | 655 | assert_return(ret_family, -EINVAL); |
89489ef7 TG |
656 | |
657 | ifa = NLMSG_DATA(m->hdr); | |
658 | ||
b44662fe | 659 | *ret_family = ifa->ifa_family; |
89489ef7 TG |
660 | |
661 | return 0; | |
662 | } | |
663 | ||
dd35a61c | 664 | int sd_rtnl_message_addr_get_prefixlen(sd_netlink_message *m, unsigned char *ret_prefixlen) { |
89489ef7 TG |
665 | struct ifaddrmsg *ifa; |
666 | ||
667 | assert_return(m, -EINVAL); | |
668 | assert_return(m->hdr, -EINVAL); | |
669 | assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); | |
b44662fe | 670 | assert_return(ret_prefixlen, -EINVAL); |
89489ef7 TG |
671 | |
672 | ifa = NLMSG_DATA(m->hdr); | |
673 | ||
b44662fe | 674 | *ret_prefixlen = ifa->ifa_prefixlen; |
89489ef7 TG |
675 | |
676 | return 0; | |
677 | } | |
678 | ||
dd35a61c | 679 | int sd_rtnl_message_addr_get_scope(sd_netlink_message *m, unsigned char *ret_scope) { |
89489ef7 TG |
680 | struct ifaddrmsg *ifa; |
681 | ||
682 | assert_return(m, -EINVAL); | |
683 | assert_return(m->hdr, -EINVAL); | |
684 | assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); | |
b44662fe | 685 | assert_return(ret_scope, -EINVAL); |
89489ef7 TG |
686 | |
687 | ifa = NLMSG_DATA(m->hdr); | |
688 | ||
b44662fe | 689 | *ret_scope = ifa->ifa_scope; |
89489ef7 TG |
690 | |
691 | return 0; | |
692 | } | |
693 | ||
dd35a61c | 694 | int sd_rtnl_message_addr_get_flags(sd_netlink_message *m, unsigned char *ret_flags) { |
89489ef7 TG |
695 | struct ifaddrmsg *ifa; |
696 | ||
697 | assert_return(m, -EINVAL); | |
698 | assert_return(m->hdr, -EINVAL); | |
699 | assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); | |
b44662fe | 700 | assert_return(ret_flags, -EINVAL); |
89489ef7 TG |
701 | |
702 | ifa = NLMSG_DATA(m->hdr); | |
703 | ||
b44662fe | 704 | *ret_flags = ifa->ifa_flags; |
89489ef7 TG |
705 | |
706 | return 0; | |
707 | } | |
708 | ||
dd35a61c | 709 | int sd_rtnl_message_addr_get_ifindex(sd_netlink_message *m, int *ret_ifindex) { |
89489ef7 TG |
710 | struct ifaddrmsg *ifa; |
711 | ||
712 | assert_return(m, -EINVAL); | |
713 | assert_return(m->hdr, -EINVAL); | |
714 | assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL); | |
b44662fe | 715 | assert_return(ret_ifindex, -EINVAL); |
89489ef7 TG |
716 | |
717 | ifa = NLMSG_DATA(m->hdr); | |
718 | ||
b44662fe | 719 | *ret_ifindex = ifa->ifa_index; |
89489ef7 TG |
720 | |
721 | return 0; | |
722 | } | |
723 | ||
dd35a61c | 724 | int sd_rtnl_message_new_addr( |
84e10015 ZJS |
725 | sd_netlink *rtnl, |
726 | sd_netlink_message **ret, | |
727 | uint16_t nlmsg_type, | |
728 | int index, | |
729 | int family) { | |
730 | ||
89489ef7 TG |
731 | struct ifaddrmsg *ifa; |
732 | int r; | |
733 | ||
734 | assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL); | |
735 | assert_return((nlmsg_type == RTM_GETADDR && index == 0) || | |
736 | index > 0, -EINVAL); | |
737 | assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) || | |
945c2931 | 738 | IN_SET(family, AF_INET, AF_INET6), -EINVAL); |
89489ef7 TG |
739 | assert_return(ret, -EINVAL); |
740 | ||
741 | r = message_new(rtnl, ret, nlmsg_type); | |
742 | if (r < 0) | |
743 | return r; | |
744 | ||
89489ef7 TG |
745 | ifa = NLMSG_DATA((*ret)->hdr); |
746 | ||
747 | ifa->ifa_index = index; | |
748 | ifa->ifa_family = family; | |
89489ef7 TG |
749 | |
750 | return 0; | |
751 | } | |
752 | ||
dd35a61c | 753 | int sd_rtnl_message_new_addr_update( |
84e10015 ZJS |
754 | sd_netlink *rtnl, |
755 | sd_netlink_message **ret, | |
756 | int index, | |
757 | int family) { | |
89489ef7 TG |
758 | int r; |
759 | ||
760 | r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family); | |
761 | if (r < 0) | |
762 | return r; | |
763 | ||
764 | (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE; | |
765 | ||
766 | return 0; | |
767 | } | |
768 | ||
dd35a61c | 769 | int sd_rtnl_message_link_get_ifindex(sd_netlink_message *m, int *ifindex) { |
89489ef7 TG |
770 | struct ifinfomsg *ifi; |
771 | ||
772 | assert_return(m, -EINVAL); | |
773 | assert_return(m->hdr, -EINVAL); | |
774 | assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); | |
775 | assert_return(ifindex, -EINVAL); | |
776 | ||
777 | ifi = NLMSG_DATA(m->hdr); | |
778 | ||
779 | *ifindex = ifi->ifi_index; | |
780 | ||
781 | return 0; | |
782 | } | |
783 | ||
dd35a61c | 784 | int sd_rtnl_message_link_get_flags(sd_netlink_message *m, unsigned *flags) { |
89489ef7 TG |
785 | struct ifinfomsg *ifi; |
786 | ||
787 | assert_return(m, -EINVAL); | |
788 | assert_return(m->hdr, -EINVAL); | |
789 | assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); | |
790 | assert_return(flags, -EINVAL); | |
791 | ||
792 | ifi = NLMSG_DATA(m->hdr); | |
793 | ||
794 | *flags = ifi->ifi_flags; | |
795 | ||
796 | return 0; | |
797 | } | |
798 | ||
dd35a61c | 799 | int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned short *type) { |
89489ef7 TG |
800 | struct ifinfomsg *ifi; |
801 | ||
802 | assert_return(m, -EINVAL); | |
803 | assert_return(m->hdr, -EINVAL); | |
804 | assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL); | |
805 | assert_return(type, -EINVAL); | |
806 | ||
807 | ifi = NLMSG_DATA(m->hdr); | |
808 | ||
809 | *type = ifi->ifi_type; | |
810 | ||
811 | return 0; | |
812 | } | |
813 | ||
dd35a61c | 814 | int sd_rtnl_message_get_family(sd_netlink_message *m, int *family) { |
89489ef7 TG |
815 | assert_return(m, -EINVAL); |
816 | assert_return(family, -EINVAL); | |
817 | ||
818 | assert(m->hdr); | |
819 | ||
820 | if (rtnl_message_type_is_link(m->hdr->nlmsg_type)) { | |
821 | struct ifinfomsg *ifi; | |
822 | ||
823 | ifi = NLMSG_DATA(m->hdr); | |
824 | ||
825 | *family = ifi->ifi_family; | |
826 | ||
827 | return 0; | |
828 | } else if (rtnl_message_type_is_route(m->hdr->nlmsg_type)) { | |
829 | struct rtmsg *rtm; | |
830 | ||
831 | rtm = NLMSG_DATA(m->hdr); | |
832 | ||
833 | *family = rtm->rtm_family; | |
834 | ||
835 | return 0; | |
836 | } else if (rtnl_message_type_is_neigh(m->hdr->nlmsg_type)) { | |
837 | struct ndmsg *ndm; | |
838 | ||
839 | ndm = NLMSG_DATA(m->hdr); | |
840 | ||
841 | *family = ndm->ndm_family; | |
842 | ||
843 | return 0; | |
844 | } else if (rtnl_message_type_is_addr(m->hdr->nlmsg_type)) { | |
845 | struct ifaddrmsg *ifa; | |
846 | ||
847 | ifa = NLMSG_DATA(m->hdr); | |
848 | ||
849 | *family = ifa->ifa_family; | |
850 | ||
bce67bbe SS |
851 | return 0; |
852 | } else if (rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type)) { | |
853 | struct rtmsg *rtm; | |
854 | ||
855 | rtm = NLMSG_DATA(m->hdr); | |
856 | ||
857 | *family = rtm->rtm_family; | |
858 | ||
c16c7808 SS |
859 | return 0; |
860 | } else if (rtnl_message_type_is_nexthop(m->hdr->nlmsg_type)) { | |
861 | struct nhmsg *nhm; | |
862 | ||
863 | nhm = NLMSG_DATA(m->hdr); | |
864 | ||
865 | *family = nhm->nh_family; | |
866 | ||
89489ef7 TG |
867 | return 0; |
868 | } | |
869 | ||
870 | return -EOPNOTSUPP; | |
871 | } | |
30746d60 | 872 | |
dd35a61c | 873 | int sd_rtnl_message_new_addrlabel( |
84e10015 ZJS |
874 | sd_netlink *rtnl, |
875 | sd_netlink_message **ret, | |
876 | uint16_t nlmsg_type, | |
877 | int ifindex, | |
878 | int ifal_family) { | |
879 | ||
30746d60 SS |
880 | struct ifaddrlblmsg *addrlabel; |
881 | int r; | |
882 | ||
883 | assert_return(rtnl_message_type_is_addrlabel(nlmsg_type), -EINVAL); | |
884 | assert_return(ret, -EINVAL); | |
885 | ||
886 | r = message_new(rtnl, ret, nlmsg_type); | |
887 | if (r < 0) | |
888 | return r; | |
889 | ||
890 | if (nlmsg_type == RTM_NEWADDRLABEL) | |
891 | (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; | |
892 | ||
893 | addrlabel = NLMSG_DATA((*ret)->hdr); | |
894 | ||
895 | addrlabel->ifal_family = ifal_family; | |
896 | addrlabel->ifal_index = ifindex; | |
897 | ||
898 | return 0; | |
899 | } | |
900 | ||
dd35a61c | 901 | int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen) { |
30746d60 SS |
902 | struct ifaddrlblmsg *addrlabel; |
903 | ||
904 | assert_return(m, -EINVAL); | |
905 | assert_return(m->hdr, -EINVAL); | |
906 | assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL); | |
907 | ||
908 | addrlabel = NLMSG_DATA(m->hdr); | |
909 | ||
910 | if (prefixlen > 128) | |
911 | return -ERANGE; | |
912 | ||
913 | addrlabel->ifal_prefixlen = prefixlen; | |
914 | ||
915 | return 0; | |
916 | } | |
d37b7627 | 917 | |
dd35a61c | 918 | int sd_rtnl_message_addrlabel_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen) { |
d37b7627 SS |
919 | struct ifaddrlblmsg *addrlabel; |
920 | ||
921 | assert_return(m, -EINVAL); | |
922 | assert_return(m->hdr, -EINVAL); | |
923 | assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL); | |
924 | ||
925 | addrlabel = NLMSG_DATA(m->hdr); | |
926 | ||
927 | *prefixlen = addrlabel->ifal_prefixlen; | |
928 | ||
929 | return 0; | |
930 | } | |
bce67bbe | 931 | |
dd35a61c | 932 | int sd_rtnl_message_new_routing_policy_rule( |
84e10015 ZJS |
933 | sd_netlink *rtnl, |
934 | sd_netlink_message **ret, | |
935 | uint16_t nlmsg_type, | |
936 | int ifal_family) { | |
937 | ||
b43dfb6e | 938 | struct fib_rule_hdr *frh; |
bce67bbe SS |
939 | int r; |
940 | ||
941 | assert_return(rtnl_message_type_is_routing_policy_rule(nlmsg_type), -EINVAL); | |
942 | assert_return(ret, -EINVAL); | |
943 | ||
944 | r = message_new(rtnl, ret, nlmsg_type); | |
945 | if (r < 0) | |
946 | return r; | |
947 | ||
948 | if (nlmsg_type == RTM_NEWRULE) | |
949 | (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; | |
950 | ||
b43dfb6e SS |
951 | frh = NLMSG_DATA((*ret)->hdr); |
952 | frh->family = ifal_family; | |
bce67bbe SS |
953 | |
954 | return 0; | |
955 | } | |
956 | ||
dd35a61c | 957 | int sd_rtnl_message_routing_policy_rule_set_tos(sd_netlink_message *m, uint8_t tos) { |
b43dfb6e | 958 | struct fib_rule_hdr *frh; |
bce67bbe SS |
959 | |
960 | assert_return(m, -EINVAL); | |
961 | assert_return(m->hdr, -EINVAL); | |
962 | assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); | |
963 | ||
b43dfb6e | 964 | frh = NLMSG_DATA(m->hdr); |
bce67bbe | 965 | |
b43dfb6e | 966 | frh->tos = tos; |
bce67bbe SS |
967 | |
968 | return 0; | |
969 | } | |
970 | ||
dd35a61c | 971 | int sd_rtnl_message_routing_policy_rule_get_tos(sd_netlink_message *m, uint8_t *tos) { |
b43dfb6e | 972 | struct fib_rule_hdr *frh; |
bce67bbe SS |
973 | |
974 | assert_return(m, -EINVAL); | |
975 | assert_return(m->hdr, -EINVAL); | |
976 | assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); | |
977 | ||
b43dfb6e | 978 | frh = NLMSG_DATA(m->hdr); |
bce67bbe | 979 | |
b43dfb6e | 980 | *tos = frh->tos; |
bce67bbe SS |
981 | |
982 | return 0; | |
983 | } | |
984 | ||
dd35a61c | 985 | int sd_rtnl_message_routing_policy_rule_set_table(sd_netlink_message *m, uint8_t table) { |
b43dfb6e | 986 | struct fib_rule_hdr *frh; |
bce67bbe SS |
987 | |
988 | assert_return(m, -EINVAL); | |
989 | assert_return(m->hdr, -EINVAL); | |
990 | assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); | |
991 | ||
b43dfb6e | 992 | frh = NLMSG_DATA(m->hdr); |
bce67bbe | 993 | |
b43dfb6e | 994 | frh->table = table; |
bce67bbe SS |
995 | |
996 | return 0; | |
997 | } | |
998 | ||
dd35a61c | 999 | int sd_rtnl_message_routing_policy_rule_get_table(sd_netlink_message *m, uint8_t *table) { |
b43dfb6e | 1000 | struct fib_rule_hdr *frh; |
bce67bbe SS |
1001 | |
1002 | assert_return(m, -EINVAL); | |
1003 | assert_return(m->hdr, -EINVAL); | |
1004 | assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); | |
1005 | ||
b43dfb6e | 1006 | frh = NLMSG_DATA(m->hdr); |
bce67bbe | 1007 | |
b43dfb6e | 1008 | *table = frh->table; |
bce67bbe SS |
1009 | |
1010 | return 0; | |
1011 | } | |
1012 | ||
dd35a61c | 1013 | int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, uint32_t flags) { |
b43dfb6e | 1014 | struct fib_rule_hdr *frh; |
8b220643 SS |
1015 | |
1016 | assert_return(m, -EINVAL); | |
1017 | assert_return(m->hdr, -EINVAL); | |
1018 | assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); | |
1019 | ||
b43dfb6e | 1020 | frh = NLMSG_DATA(m->hdr); |
45b1299a | 1021 | frh->flags = flags; |
8b220643 SS |
1022 | |
1023 | return 0; | |
1024 | } | |
1025 | ||
dd35a61c | 1026 | int sd_rtnl_message_routing_policy_rule_get_flags(sd_netlink_message *m, uint32_t *flags) { |
b43dfb6e | 1027 | struct fib_rule_hdr *frh; |
8b220643 SS |
1028 | |
1029 | assert_return(m, -EINVAL); | |
1030 | assert_return(m->hdr, -EINVAL); | |
1031 | assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); | |
1032 | ||
b43dfb6e SS |
1033 | frh = NLMSG_DATA(m->hdr); |
1034 | *flags = frh->flags; | |
8b220643 SS |
1035 | |
1036 | return 0; | |
1037 | } | |
1038 | ||
dd35a61c | 1039 | int sd_rtnl_message_routing_policy_rule_set_fib_type(sd_netlink_message *m, uint8_t type) { |
b43dfb6e | 1040 | struct fib_rule_hdr *frh; |
bce67bbe SS |
1041 | |
1042 | assert_return(m, -EINVAL); | |
1043 | assert_return(m->hdr, -EINVAL); | |
1044 | assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); | |
1045 | ||
b43dfb6e | 1046 | frh = NLMSG_DATA(m->hdr); |
bce67bbe | 1047 | |
b43dfb6e | 1048 | frh->action = type; |
bce67bbe SS |
1049 | |
1050 | return 0; | |
1051 | } | |
1052 | ||
dd35a61c | 1053 | int sd_rtnl_message_routing_policy_rule_get_fib_type(sd_netlink_message *m, uint8_t *type) { |
b43dfb6e | 1054 | struct fib_rule_hdr *frh; |
bce67bbe SS |
1055 | |
1056 | assert_return(m, -EINVAL); | |
1057 | assert_return(m->hdr, -EINVAL); | |
1058 | assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); | |
1059 | ||
b43dfb6e | 1060 | frh = NLMSG_DATA(m->hdr); |
bce67bbe | 1061 | |
b43dfb6e | 1062 | *type = frh->action; |
bce67bbe SS |
1063 | |
1064 | return 0; | |
1065 | } | |
1066 | ||
dd35a61c | 1067 | int sd_rtnl_message_routing_policy_rule_set_fib_dst_prefixlen(sd_netlink_message *m, uint8_t len) { |
b43dfb6e | 1068 | struct fib_rule_hdr *frh; |
bce67bbe SS |
1069 | |
1070 | assert_return(m, -EINVAL); | |
1071 | assert_return(m->hdr, -EINVAL); | |
1072 | assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); | |
1073 | ||
b43dfb6e | 1074 | frh = NLMSG_DATA(m->hdr); |
bce67bbe | 1075 | |
b43dfb6e | 1076 | frh->dst_len = len; |
bce67bbe SS |
1077 | |
1078 | return 0; | |
1079 | } | |
1080 | ||
dd35a61c | 1081 | int sd_rtnl_message_routing_policy_rule_get_fib_dst_prefixlen(sd_netlink_message *m, uint8_t *len) { |
b43dfb6e | 1082 | struct fib_rule_hdr *frh; |
bce67bbe SS |
1083 | |
1084 | assert_return(m, -EINVAL); | |
1085 | assert_return(m->hdr, -EINVAL); | |
1086 | assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); | |
1087 | ||
b43dfb6e | 1088 | frh = NLMSG_DATA(m->hdr); |
bce67bbe | 1089 | |
b43dfb6e | 1090 | *len = frh->dst_len; |
bce67bbe SS |
1091 | |
1092 | return 0; | |
1093 | } | |
1094 | ||
dd35a61c | 1095 | int sd_rtnl_message_routing_policy_rule_set_fib_src_prefixlen(sd_netlink_message *m, uint8_t len) { |
b43dfb6e | 1096 | struct fib_rule_hdr *frh; |
bce67bbe SS |
1097 | |
1098 | assert_return(m, -EINVAL); | |
1099 | assert_return(m->hdr, -EINVAL); | |
1100 | assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); | |
1101 | ||
b43dfb6e | 1102 | frh = NLMSG_DATA(m->hdr); |
bce67bbe | 1103 | |
b43dfb6e | 1104 | frh->src_len = len; |
bce67bbe SS |
1105 | |
1106 | return 0; | |
1107 | } | |
1108 | ||
dd35a61c | 1109 | int sd_rtnl_message_routing_policy_rule_get_fib_src_prefixlen(sd_netlink_message *m, uint8_t *len) { |
b43dfb6e | 1110 | struct fib_rule_hdr *frh; |
bce67bbe SS |
1111 | |
1112 | assert_return(m, -EINVAL); | |
1113 | assert_return(m->hdr, -EINVAL); | |
1114 | assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL); | |
1115 | ||
b43dfb6e | 1116 | frh = NLMSG_DATA(m->hdr); |
bce67bbe | 1117 | |
b43dfb6e | 1118 | *len = frh->src_len; |
bce67bbe SS |
1119 | |
1120 | return 0; | |
1121 | } | |
0f5bd7fe | 1122 | |
dd35a61c | 1123 | int sd_rtnl_message_new_traffic_control( |
f50b93fe YW |
1124 | sd_netlink *rtnl, |
1125 | sd_netlink_message **ret, | |
1126 | uint16_t nlmsg_type, | |
1127 | int ifindex, | |
1128 | uint32_t handle, | |
1129 | uint32_t parent) { | |
0f5bd7fe | 1130 | |
0ebb76de YW |
1131 | struct tcmsg *tcm; |
1132 | int r; | |
1133 | ||
f50b93fe | 1134 | assert_return(rtnl_message_type_is_traffic_control(nlmsg_type), -EINVAL); |
0ebb76de YW |
1135 | assert_return(ret, -EINVAL); |
1136 | ||
1137 | r = message_new(rtnl, ret, nlmsg_type); | |
1138 | if (r < 0) | |
1139 | return r; | |
1140 | ||
f50b93fe | 1141 | if (IN_SET(nlmsg_type, RTM_NEWQDISC, RTM_NEWTCLASS)) |
0ebb76de YW |
1142 | (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; |
1143 | ||
1144 | tcm = NLMSG_DATA((*ret)->hdr); | |
f50b93fe | 1145 | tcm->tcm_ifindex = ifindex; |
0ebb76de | 1146 | tcm->tcm_handle = handle; |
f50b93fe | 1147 | tcm->tcm_parent = parent; |
0ebb76de YW |
1148 | |
1149 | return 0; | |
1150 | } | |
1903c9bb | 1151 | |
dd35a61c | 1152 | int sd_rtnl_message_traffic_control_get_ifindex(sd_netlink_message *m, int *ret) { |
1f38b6f9 YW |
1153 | struct tcmsg *tcm; |
1154 | ||
1155 | assert_return(m, -EINVAL); | |
1156 | assert_return(m->hdr, -EINVAL); | |
1157 | assert_return(rtnl_message_type_is_traffic_control(m->hdr->nlmsg_type), -EINVAL); | |
1158 | assert_return(ret, -EINVAL); | |
1159 | ||
1160 | tcm = NLMSG_DATA(m->hdr); | |
1161 | *ret = tcm->tcm_ifindex; | |
1162 | ||
1163 | return 0; | |
1164 | } | |
1165 | ||
dd35a61c | 1166 | int sd_rtnl_message_traffic_control_get_handle(sd_netlink_message *m, uint32_t *ret) { |
1f38b6f9 YW |
1167 | struct tcmsg *tcm; |
1168 | ||
1169 | assert_return(m, -EINVAL); | |
1170 | assert_return(m->hdr, -EINVAL); | |
1171 | assert_return(rtnl_message_type_is_traffic_control(m->hdr->nlmsg_type), -EINVAL); | |
1172 | assert_return(ret, -EINVAL); | |
1173 | ||
1174 | tcm = NLMSG_DATA(m->hdr); | |
1175 | *ret = tcm->tcm_handle; | |
1176 | ||
1177 | return 0; | |
1178 | } | |
1179 | ||
dd35a61c | 1180 | int sd_rtnl_message_traffic_control_get_parent(sd_netlink_message *m, uint32_t *ret) { |
1f38b6f9 YW |
1181 | struct tcmsg *tcm; |
1182 | ||
1183 | assert_return(m, -EINVAL); | |
1184 | assert_return(m->hdr, -EINVAL); | |
1185 | assert_return(rtnl_message_type_is_traffic_control(m->hdr->nlmsg_type), -EINVAL); | |
1186 | assert_return(ret, -EINVAL); | |
1187 | ||
1188 | tcm = NLMSG_DATA(m->hdr); | |
1189 | *ret = tcm->tcm_parent; | |
1190 | ||
1191 | return 0; | |
1192 | } | |
1193 | ||
dd35a61c | 1194 | int sd_rtnl_message_new_mdb( |
84e10015 ZJS |
1195 | sd_netlink *rtnl, |
1196 | sd_netlink_message **ret, | |
1197 | uint16_t nlmsg_type, | |
1198 | int mdb_ifindex) { | |
1199 | ||
1903c9bb DM |
1200 | struct br_port_msg *bpm; |
1201 | int r; | |
1202 | ||
1203 | assert_return(rtnl_message_type_is_mdb(nlmsg_type), -EINVAL); | |
1204 | assert_return(ret, -EINVAL); | |
1205 | ||
1206 | r = message_new(rtnl, ret, nlmsg_type); | |
1207 | if (r < 0) | |
1208 | return r; | |
1209 | ||
1210 | if (nlmsg_type == RTM_NEWMDB) | |
1211 | (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL; | |
1212 | ||
1213 | bpm = NLMSG_DATA((*ret)->hdr); | |
1214 | bpm->family = AF_BRIDGE; | |
1215 | bpm->ifindex = mdb_ifindex; | |
1216 | ||
1217 | return 0; | |
1218 | } |