Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
2 :
3 : #include <netinet/in.h>
4 : #include <linux/if_addrlabel.h>
5 : #include <stdbool.h>
6 : #include <unistd.h>
7 :
8 : #include "sd-netlink.h"
9 :
10 : #include "format-util.h"
11 : #include "missing.h"
12 : #include "netlink-internal.h"
13 : #include "netlink-types.h"
14 : #include "netlink-util.h"
15 : #include "socket-util.h"
16 : #include "util.h"
17 :
18 0 : int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message *m, unsigned char prefixlen) {
19 : struct rtmsg *rtm;
20 :
21 0 : assert_return(m, -EINVAL);
22 0 : assert_return(m->hdr, -EINVAL);
23 0 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
24 :
25 0 : rtm = NLMSG_DATA(m->hdr);
26 :
27 0 : if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
28 0 : (rtm->rtm_family == AF_INET6 && prefixlen > 128))
29 0 : return -ERANGE;
30 :
31 0 : rtm->rtm_dst_len = prefixlen;
32 :
33 0 : return 0;
34 : }
35 :
36 0 : int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message *m, unsigned char prefixlen) {
37 : struct rtmsg *rtm;
38 :
39 0 : assert_return(m, -EINVAL);
40 0 : assert_return(m->hdr, -EINVAL);
41 0 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
42 :
43 0 : rtm = NLMSG_DATA(m->hdr);
44 :
45 0 : if ((rtm->rtm_family == AF_INET && prefixlen > 32) ||
46 0 : (rtm->rtm_family == AF_INET6 && prefixlen > 128))
47 0 : return -ERANGE;
48 :
49 0 : rtm->rtm_src_len = prefixlen;
50 :
51 0 : return 0;
52 : }
53 :
54 0 : int sd_rtnl_message_route_set_scope(sd_netlink_message *m, unsigned char scope) {
55 : struct rtmsg *rtm;
56 :
57 0 : assert_return(m, -EINVAL);
58 0 : assert_return(m->hdr, -EINVAL);
59 0 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
60 :
61 0 : rtm = NLMSG_DATA(m->hdr);
62 :
63 0 : rtm->rtm_scope = scope;
64 :
65 0 : return 0;
66 : }
67 :
68 0 : int sd_rtnl_message_route_set_flags(sd_netlink_message *m, unsigned flags) {
69 : struct rtmsg *rtm;
70 :
71 0 : assert_return(m, -EINVAL);
72 0 : assert_return(m->hdr, -EINVAL);
73 0 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
74 :
75 0 : rtm = NLMSG_DATA(m->hdr);
76 :
77 0 : rtm->rtm_flags = flags;
78 :
79 0 : return 0;
80 : }
81 :
82 0 : int sd_rtnl_message_route_get_flags(sd_netlink_message *m, unsigned *flags) {
83 : struct rtmsg *rtm;
84 :
85 0 : assert_return(m, -EINVAL);
86 0 : assert_return(m->hdr, -EINVAL);
87 0 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
88 0 : assert_return(flags, -EINVAL);
89 :
90 0 : rtm = NLMSG_DATA(m->hdr);
91 :
92 0 : *flags = rtm->rtm_flags;
93 :
94 0 : return 0;
95 : }
96 :
97 0 : int sd_rtnl_message_route_set_table(sd_netlink_message *m, unsigned char table) {
98 : struct rtmsg *rtm;
99 :
100 0 : assert_return(m, -EINVAL);
101 0 : assert_return(m->hdr, -EINVAL);
102 0 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
103 :
104 0 : rtm = NLMSG_DATA(m->hdr);
105 :
106 0 : rtm->rtm_table = table;
107 :
108 0 : return 0;
109 : }
110 :
111 2 : int sd_rtnl_message_route_get_family(sd_netlink_message *m, int *family) {
112 : struct rtmsg *rtm;
113 :
114 2 : assert_return(m, -EINVAL);
115 2 : assert_return(m->hdr, -EINVAL);
116 2 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
117 2 : assert_return(family, -EINVAL);
118 :
119 2 : rtm = NLMSG_DATA(m->hdr);
120 :
121 2 : *family = rtm->rtm_family;
122 :
123 2 : return 0;
124 : }
125 :
126 0 : int sd_rtnl_message_route_set_family(sd_netlink_message *m, int family) {
127 : struct rtmsg *rtm;
128 :
129 0 : assert_return(m, -EINVAL);
130 0 : assert_return(m->hdr, -EINVAL);
131 0 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
132 :
133 0 : rtm = NLMSG_DATA(m->hdr);
134 :
135 0 : rtm->rtm_family = family;
136 :
137 0 : return 0;
138 : }
139 :
140 0 : int sd_rtnl_message_route_get_type(sd_netlink_message *m, unsigned char *type) {
141 : struct rtmsg *rtm;
142 :
143 0 : assert_return(m, -EINVAL);
144 0 : assert_return(m->hdr, -EINVAL);
145 0 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
146 0 : assert_return(type, -EINVAL);
147 :
148 0 : rtm = NLMSG_DATA(m->hdr);
149 :
150 0 : *type = rtm->rtm_type;
151 :
152 0 : return 0;
153 : }
154 :
155 0 : int sd_rtnl_message_route_set_type(sd_netlink_message *m, unsigned char type) {
156 : struct rtmsg *rtm;
157 :
158 0 : assert_return(m, -EINVAL);
159 0 : assert_return(m->hdr, -EINVAL);
160 0 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
161 :
162 0 : rtm = NLMSG_DATA(m->hdr);
163 :
164 0 : rtm->rtm_type = type;
165 :
166 0 : return 0;
167 : }
168 :
169 0 : int sd_rtnl_message_route_get_protocol(sd_netlink_message *m, unsigned char *protocol) {
170 : struct rtmsg *rtm;
171 :
172 0 : assert_return(m, -EINVAL);
173 0 : assert_return(m->hdr, -EINVAL);
174 0 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
175 0 : assert_return(protocol, -EINVAL);
176 :
177 0 : rtm = NLMSG_DATA(m->hdr);
178 :
179 0 : *protocol = rtm->rtm_protocol;
180 :
181 0 : return 0;
182 : }
183 :
184 0 : int sd_rtnl_message_route_get_scope(sd_netlink_message *m, unsigned char *scope) {
185 : struct rtmsg *rtm;
186 :
187 0 : assert_return(m, -EINVAL);
188 0 : assert_return(m->hdr, -EINVAL);
189 0 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
190 0 : assert_return(scope, -EINVAL);
191 :
192 0 : rtm = NLMSG_DATA(m->hdr);
193 :
194 0 : *scope = rtm->rtm_scope;
195 :
196 0 : return 0;
197 : }
198 :
199 0 : int sd_rtnl_message_route_get_tos(sd_netlink_message *m, unsigned char *tos) {
200 : struct rtmsg *rtm;
201 :
202 0 : assert_return(m, -EINVAL);
203 0 : assert_return(m->hdr, -EINVAL);
204 0 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
205 0 : assert_return(tos, -EINVAL);
206 :
207 0 : rtm = NLMSG_DATA(m->hdr);
208 :
209 0 : *tos = rtm->rtm_tos;
210 :
211 0 : return 0;
212 : }
213 :
214 2 : int sd_rtnl_message_route_get_table(sd_netlink_message *m, unsigned char *table) {
215 : struct rtmsg *rtm;
216 :
217 2 : assert_return(m, -EINVAL);
218 2 : assert_return(m->hdr, -EINVAL);
219 2 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
220 2 : assert_return(table, -EINVAL);
221 :
222 2 : rtm = NLMSG_DATA(m->hdr);
223 :
224 2 : *table = rtm->rtm_table;
225 :
226 2 : return 0;
227 : }
228 :
229 28 : int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message *m, unsigned char *dst_len) {
230 : struct rtmsg *rtm;
231 :
232 28 : assert_return(m, -EINVAL);
233 28 : assert_return(m->hdr, -EINVAL);
234 28 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
235 28 : assert_return(dst_len, -EINVAL);
236 :
237 28 : rtm = NLMSG_DATA(m->hdr);
238 :
239 28 : *dst_len = rtm->rtm_dst_len;
240 :
241 28 : return 0;
242 : }
243 :
244 2 : int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message *m, unsigned char *src_len) {
245 : struct rtmsg *rtm;
246 :
247 2 : assert_return(m, -EINVAL);
248 2 : assert_return(m->hdr, -EINVAL);
249 2 : assert_return(rtnl_message_type_is_route(m->hdr->nlmsg_type), -EINVAL);
250 2 : assert_return(src_len, -EINVAL);
251 :
252 2 : rtm = NLMSG_DATA(m->hdr);
253 :
254 2 : *src_len = rtm->rtm_src_len;
255 :
256 2 : return 0;
257 : }
258 :
259 2 : int sd_rtnl_message_new_route(sd_netlink *rtnl, sd_netlink_message **ret,
260 : uint16_t nlmsg_type, int rtm_family,
261 : unsigned char rtm_protocol) {
262 : struct rtmsg *rtm;
263 : int r;
264 :
265 2 : assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
266 2 : assert_return((nlmsg_type == RTM_GETROUTE && rtm_family == AF_UNSPEC) ||
267 : IN_SET(rtm_family, AF_INET, AF_INET6), -EINVAL);
268 2 : assert_return(ret, -EINVAL);
269 :
270 2 : r = message_new(rtnl, ret, nlmsg_type);
271 2 : if (r < 0)
272 0 : return r;
273 :
274 2 : if (nlmsg_type == RTM_NEWROUTE)
275 1 : (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
276 :
277 2 : rtm = NLMSG_DATA((*ret)->hdr);
278 :
279 2 : rtm->rtm_family = rtm_family;
280 2 : rtm->rtm_scope = RT_SCOPE_UNIVERSE;
281 2 : rtm->rtm_type = RTN_UNICAST;
282 2 : rtm->rtm_table = RT_TABLE_MAIN;
283 2 : rtm->rtm_protocol = rtm_protocol;
284 :
285 2 : return 0;
286 : }
287 :
288 0 : int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags) {
289 : struct ndmsg *ndm;
290 :
291 0 : assert_return(m, -EINVAL);
292 0 : assert_return(m->hdr, -EINVAL);
293 0 : assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
294 :
295 0 : ndm = NLMSG_DATA(m->hdr);
296 0 : ndm->ndm_flags |= flags;
297 :
298 0 : return 0;
299 : }
300 :
301 0 : int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state) {
302 : struct ndmsg *ndm;
303 :
304 0 : assert_return(m, -EINVAL);
305 0 : assert_return(m->hdr, -EINVAL);
306 0 : assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
307 :
308 0 : ndm = NLMSG_DATA(m->hdr);
309 0 : ndm->ndm_state |= state;
310 :
311 0 : return 0;
312 : }
313 :
314 0 : int sd_rtnl_message_neigh_get_flags(sd_netlink_message *m, uint8_t *flags) {
315 : struct ndmsg *ndm;
316 :
317 0 : assert_return(m, -EINVAL);
318 0 : assert_return(m->hdr, -EINVAL);
319 0 : assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
320 :
321 0 : ndm = NLMSG_DATA(m->hdr);
322 0 : *flags = ndm->ndm_flags;
323 :
324 0 : return 0;
325 : }
326 :
327 0 : int sd_rtnl_message_neigh_get_state(sd_netlink_message *m, uint16_t *state) {
328 : struct ndmsg *ndm;
329 :
330 0 : assert_return(m, -EINVAL);
331 0 : assert_return(m->hdr, -EINVAL);
332 0 : assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
333 :
334 0 : ndm = NLMSG_DATA(m->hdr);
335 0 : *state = ndm->ndm_state;
336 :
337 0 : return 0;
338 : }
339 :
340 0 : int sd_rtnl_message_neigh_get_family(sd_netlink_message *m, int *family) {
341 : struct ndmsg *ndm;
342 :
343 0 : assert_return(m, -EINVAL);
344 0 : assert_return(m->hdr, -EINVAL);
345 0 : assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
346 0 : assert_return(family, -EINVAL);
347 :
348 0 : ndm = NLMSG_DATA(m->hdr);
349 :
350 0 : *family = ndm->ndm_family;
351 :
352 0 : return 0;
353 : }
354 :
355 0 : int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message *m, int *index) {
356 : struct ndmsg *ndm;
357 :
358 0 : assert_return(m, -EINVAL);
359 0 : assert_return(m->hdr, -EINVAL);
360 0 : assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
361 0 : assert_return(index, -EINVAL);
362 :
363 0 : ndm = NLMSG_DATA(m->hdr);
364 :
365 0 : *index = ndm->ndm_ifindex;
366 :
367 0 : return 0;
368 : }
369 :
370 0 : int sd_rtnl_message_new_neigh(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
371 : struct ndmsg *ndm;
372 : int r;
373 :
374 0 : assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
375 0 : assert_return(IN_SET(ndm_family, AF_UNSPEC, AF_INET, AF_INET6, PF_BRIDGE), -EINVAL);
376 0 : assert_return(ret, -EINVAL);
377 :
378 0 : r = message_new(rtnl, ret, nlmsg_type);
379 0 : if (r < 0)
380 0 : return r;
381 :
382 0 : if (nlmsg_type == RTM_NEWNEIGH)
383 0 : (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
384 :
385 0 : ndm = NLMSG_DATA((*ret)->hdr);
386 :
387 0 : ndm->ndm_family = ndm_family;
388 0 : ndm->ndm_ifindex = index;
389 :
390 0 : return 0;
391 : }
392 :
393 1 : int sd_rtnl_message_link_set_flags(sd_netlink_message *m, unsigned flags, unsigned change) {
394 : struct ifinfomsg *ifi;
395 :
396 1 : assert_return(m, -EINVAL);
397 1 : assert_return(m->hdr, -EINVAL);
398 1 : assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
399 1 : assert_return(change, -EINVAL);
400 :
401 1 : ifi = NLMSG_DATA(m->hdr);
402 :
403 1 : ifi->ifi_flags = flags;
404 1 : ifi->ifi_change = change;
405 :
406 1 : return 0;
407 : }
408 :
409 0 : int sd_rtnl_message_link_set_type(sd_netlink_message *m, unsigned type) {
410 : struct ifinfomsg *ifi;
411 :
412 0 : assert_return(m, -EINVAL);
413 0 : assert_return(m->hdr, -EINVAL);
414 0 : assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
415 :
416 0 : ifi = NLMSG_DATA(m->hdr);
417 :
418 0 : ifi->ifi_type = type;
419 :
420 0 : return 0;
421 : }
422 :
423 1 : int sd_rtnl_message_link_set_family(sd_netlink_message *m, unsigned family) {
424 : struct ifinfomsg *ifi;
425 :
426 1 : assert_return(m, -EINVAL);
427 1 : assert_return(m->hdr, -EINVAL);
428 1 : assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
429 :
430 1 : ifi = NLMSG_DATA(m->hdr);
431 :
432 1 : ifi->ifi_family = family;
433 :
434 1 : return 0;
435 : }
436 :
437 22 : int sd_rtnl_message_new_link(sd_netlink *rtnl, sd_netlink_message **ret,
438 : uint16_t nlmsg_type, int index) {
439 : struct ifinfomsg *ifi;
440 : int r;
441 :
442 22 : assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
443 22 : assert_return(ret, -EINVAL);
444 :
445 22 : r = message_new(rtnl, ret, nlmsg_type);
446 22 : if (r < 0)
447 0 : return r;
448 :
449 22 : if (nlmsg_type == RTM_NEWLINK)
450 2 : (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
451 :
452 22 : ifi = NLMSG_DATA((*ret)->hdr);
453 :
454 22 : ifi->ifi_family = AF_UNSPEC;
455 22 : ifi->ifi_index = index;
456 :
457 22 : return 0;
458 : }
459 :
460 2 : int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen) {
461 : struct ifaddrmsg *ifa;
462 :
463 2 : assert_return(m, -EINVAL);
464 2 : assert_return(m->hdr, -EINVAL);
465 2 : assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
466 :
467 2 : ifa = NLMSG_DATA(m->hdr);
468 :
469 2 : if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
470 2 : (ifa->ifa_family == AF_INET6 && prefixlen > 128))
471 0 : return -ERANGE;
472 :
473 2 : ifa->ifa_prefixlen = prefixlen;
474 :
475 2 : return 0;
476 : }
477 :
478 2 : int sd_rtnl_message_addr_set_flags(sd_netlink_message *m, unsigned char flags) {
479 : struct ifaddrmsg *ifa;
480 :
481 2 : assert_return(m, -EINVAL);
482 2 : assert_return(m->hdr, -EINVAL);
483 2 : assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
484 :
485 2 : ifa = NLMSG_DATA(m->hdr);
486 :
487 2 : ifa->ifa_flags = flags;
488 :
489 2 : return 0;
490 : }
491 :
492 2 : int sd_rtnl_message_addr_set_scope(sd_netlink_message *m, unsigned char scope) {
493 : struct ifaddrmsg *ifa;
494 :
495 2 : assert_return(m, -EINVAL);
496 2 : assert_return(m->hdr, -EINVAL);
497 2 : assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
498 :
499 2 : ifa = NLMSG_DATA(m->hdr);
500 :
501 2 : ifa->ifa_scope = scope;
502 :
503 2 : return 0;
504 : }
505 :
506 16 : int sd_rtnl_message_addr_get_family(sd_netlink_message *m, int *family) {
507 : struct ifaddrmsg *ifa;
508 :
509 16 : assert_return(m, -EINVAL);
510 16 : assert_return(m->hdr, -EINVAL);
511 16 : assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
512 16 : assert_return(family, -EINVAL);
513 :
514 16 : ifa = NLMSG_DATA(m->hdr);
515 :
516 16 : *family = ifa->ifa_family;
517 :
518 16 : return 0;
519 : }
520 :
521 0 : int sd_rtnl_message_addr_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen) {
522 : struct ifaddrmsg *ifa;
523 :
524 0 : assert_return(m, -EINVAL);
525 0 : assert_return(m->hdr, -EINVAL);
526 0 : assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
527 0 : assert_return(prefixlen, -EINVAL);
528 :
529 0 : ifa = NLMSG_DATA(m->hdr);
530 :
531 0 : *prefixlen = ifa->ifa_prefixlen;
532 :
533 0 : return 0;
534 : }
535 :
536 16 : int sd_rtnl_message_addr_get_scope(sd_netlink_message *m, unsigned char *scope) {
537 : struct ifaddrmsg *ifa;
538 :
539 16 : assert_return(m, -EINVAL);
540 16 : assert_return(m->hdr, -EINVAL);
541 16 : assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
542 16 : assert_return(scope, -EINVAL);
543 :
544 16 : ifa = NLMSG_DATA(m->hdr);
545 :
546 16 : *scope = ifa->ifa_scope;
547 :
548 16 : return 0;
549 : }
550 :
551 16 : int sd_rtnl_message_addr_get_flags(sd_netlink_message *m, unsigned char *flags) {
552 : struct ifaddrmsg *ifa;
553 :
554 16 : assert_return(m, -EINVAL);
555 16 : assert_return(m->hdr, -EINVAL);
556 16 : assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
557 16 : assert_return(flags, -EINVAL);
558 :
559 16 : ifa = NLMSG_DATA(m->hdr);
560 :
561 16 : *flags = ifa->ifa_flags;
562 :
563 16 : return 0;
564 : }
565 :
566 16 : int sd_rtnl_message_addr_get_ifindex(sd_netlink_message *m, int *ifindex) {
567 : struct ifaddrmsg *ifa;
568 :
569 16 : assert_return(m, -EINVAL);
570 16 : assert_return(m->hdr, -EINVAL);
571 16 : assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
572 16 : assert_return(ifindex, -EINVAL);
573 :
574 16 : ifa = NLMSG_DATA(m->hdr);
575 :
576 16 : *ifindex = ifa->ifa_index;
577 :
578 16 : return 0;
579 : }
580 :
581 5 : int sd_rtnl_message_new_addr(sd_netlink *rtnl, sd_netlink_message **ret,
582 : uint16_t nlmsg_type, int index,
583 : int family) {
584 : struct ifaddrmsg *ifa;
585 : int r;
586 :
587 5 : assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
588 5 : assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
589 : index > 0, -EINVAL);
590 5 : assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
591 : IN_SET(family, AF_INET, AF_INET6), -EINVAL);
592 5 : assert_return(ret, -EINVAL);
593 :
594 5 : r = message_new(rtnl, ret, nlmsg_type);
595 5 : if (r < 0)
596 0 : return r;
597 :
598 5 : if (nlmsg_type == RTM_GETADDR)
599 3 : (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
600 :
601 5 : ifa = NLMSG_DATA((*ret)->hdr);
602 :
603 5 : ifa->ifa_index = index;
604 5 : ifa->ifa_family = family;
605 5 : if (family == AF_INET)
606 2 : ifa->ifa_prefixlen = 32;
607 3 : else if (family == AF_INET6)
608 1 : ifa->ifa_prefixlen = 128;
609 :
610 5 : return 0;
611 : }
612 :
613 0 : int sd_rtnl_message_new_addr_update(sd_netlink *rtnl, sd_netlink_message **ret,
614 : int index, int family) {
615 : int r;
616 :
617 0 : r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
618 0 : if (r < 0)
619 0 : return r;
620 :
621 0 : (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
622 :
623 0 : return 0;
624 : }
625 :
626 12 : int sd_rtnl_message_link_get_ifindex(sd_netlink_message *m, int *ifindex) {
627 : struct ifinfomsg *ifi;
628 :
629 12 : assert_return(m, -EINVAL);
630 12 : assert_return(m->hdr, -EINVAL);
631 12 : assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
632 12 : assert_return(ifindex, -EINVAL);
633 :
634 12 : ifi = NLMSG_DATA(m->hdr);
635 :
636 12 : *ifindex = ifi->ifi_index;
637 :
638 12 : return 0;
639 : }
640 :
641 13 : int sd_rtnl_message_link_get_flags(sd_netlink_message *m, unsigned *flags) {
642 : struct ifinfomsg *ifi;
643 :
644 13 : assert_return(m, -EINVAL);
645 13 : assert_return(m->hdr, -EINVAL);
646 13 : assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
647 13 : assert_return(flags, -EINVAL);
648 :
649 13 : ifi = NLMSG_DATA(m->hdr);
650 :
651 13 : *flags = ifi->ifi_flags;
652 :
653 13 : return 0;
654 : }
655 :
656 6 : int sd_rtnl_message_link_get_type(sd_netlink_message *m, unsigned short *type) {
657 : struct ifinfomsg *ifi;
658 :
659 6 : assert_return(m, -EINVAL);
660 6 : assert_return(m->hdr, -EINVAL);
661 6 : assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
662 6 : assert_return(type, -EINVAL);
663 :
664 6 : ifi = NLMSG_DATA(m->hdr);
665 :
666 6 : *type = ifi->ifi_type;
667 :
668 6 : return 0;
669 : }
670 :
671 2 : int sd_rtnl_message_get_family(sd_netlink_message *m, int *family) {
672 2 : assert_return(m, -EINVAL);
673 2 : assert_return(family, -EINVAL);
674 :
675 2 : assert(m->hdr);
676 :
677 2 : if (rtnl_message_type_is_link(m->hdr->nlmsg_type)) {
678 : struct ifinfomsg *ifi;
679 :
680 2 : ifi = NLMSG_DATA(m->hdr);
681 :
682 2 : *family = ifi->ifi_family;
683 :
684 2 : return 0;
685 0 : } else if (rtnl_message_type_is_route(m->hdr->nlmsg_type)) {
686 : struct rtmsg *rtm;
687 :
688 0 : rtm = NLMSG_DATA(m->hdr);
689 :
690 0 : *family = rtm->rtm_family;
691 :
692 0 : return 0;
693 0 : } else if (rtnl_message_type_is_neigh(m->hdr->nlmsg_type)) {
694 : struct ndmsg *ndm;
695 :
696 0 : ndm = NLMSG_DATA(m->hdr);
697 :
698 0 : *family = ndm->ndm_family;
699 :
700 0 : return 0;
701 0 : } else if (rtnl_message_type_is_addr(m->hdr->nlmsg_type)) {
702 : struct ifaddrmsg *ifa;
703 :
704 0 : ifa = NLMSG_DATA(m->hdr);
705 :
706 0 : *family = ifa->ifa_family;
707 :
708 0 : return 0;
709 0 : } else if (rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type)) {
710 : struct rtmsg *rtm;
711 :
712 0 : rtm = NLMSG_DATA(m->hdr);
713 :
714 0 : *family = rtm->rtm_family;
715 :
716 0 : return 0;
717 : }
718 :
719 0 : return -EOPNOTSUPP;
720 : }
721 :
722 0 : int sd_rtnl_message_new_addrlabel(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex, int ifal_family) {
723 : struct ifaddrlblmsg *addrlabel;
724 : int r;
725 :
726 0 : assert_return(rtnl_message_type_is_addrlabel(nlmsg_type), -EINVAL);
727 0 : assert_return(ret, -EINVAL);
728 :
729 0 : r = message_new(rtnl, ret, nlmsg_type);
730 0 : if (r < 0)
731 0 : return r;
732 :
733 0 : if (nlmsg_type == RTM_NEWADDRLABEL)
734 0 : (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
735 :
736 0 : addrlabel = NLMSG_DATA((*ret)->hdr);
737 :
738 0 : addrlabel->ifal_family = ifal_family;
739 0 : addrlabel->ifal_index = ifindex;
740 :
741 0 : return 0;
742 : }
743 :
744 0 : int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen) {
745 : struct ifaddrlblmsg *addrlabel;
746 :
747 0 : assert_return(m, -EINVAL);
748 0 : assert_return(m->hdr, -EINVAL);
749 0 : assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL);
750 :
751 0 : addrlabel = NLMSG_DATA(m->hdr);
752 :
753 0 : if (prefixlen > 128)
754 0 : return -ERANGE;
755 :
756 0 : addrlabel->ifal_prefixlen = prefixlen;
757 :
758 0 : return 0;
759 : }
760 :
761 0 : int sd_rtnl_message_addrlabel_get_prefixlen(sd_netlink_message *m, unsigned char *prefixlen) {
762 : struct ifaddrlblmsg *addrlabel;
763 :
764 0 : assert_return(m, -EINVAL);
765 0 : assert_return(m->hdr, -EINVAL);
766 0 : assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL);
767 :
768 0 : addrlabel = NLMSG_DATA(m->hdr);
769 :
770 0 : *prefixlen = addrlabel->ifal_prefixlen;
771 :
772 0 : return 0;
773 : }
774 :
775 0 : int sd_rtnl_message_new_routing_policy_rule(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifal_family) {
776 : struct rtmsg *rtm;
777 : int r;
778 :
779 0 : assert_return(rtnl_message_type_is_routing_policy_rule(nlmsg_type), -EINVAL);
780 0 : assert_return(ret, -EINVAL);
781 :
782 0 : r = message_new(rtnl, ret, nlmsg_type);
783 0 : if (r < 0)
784 0 : return r;
785 :
786 0 : if (nlmsg_type == RTM_NEWRULE)
787 0 : (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
788 :
789 0 : rtm = NLMSG_DATA((*ret)->hdr);
790 0 : rtm->rtm_family = ifal_family;
791 0 : rtm->rtm_protocol = RTPROT_BOOT;
792 0 : rtm->rtm_scope = RT_SCOPE_UNIVERSE;
793 0 : rtm->rtm_type = RTN_UNICAST;
794 :
795 0 : return 0;
796 : }
797 :
798 0 : int sd_rtnl_message_routing_policy_rule_set_tos(sd_netlink_message *m, unsigned char tos) {
799 : struct rtmsg *routing_policy_rule;
800 :
801 0 : assert_return(m, -EINVAL);
802 0 : assert_return(m->hdr, -EINVAL);
803 0 : assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
804 :
805 0 : routing_policy_rule = NLMSG_DATA(m->hdr);
806 :
807 0 : routing_policy_rule->rtm_tos = tos;
808 :
809 0 : return 0;
810 : }
811 :
812 0 : int sd_rtnl_message_routing_policy_rule_get_tos(sd_netlink_message *m, unsigned char *tos) {
813 : struct rtmsg *routing_policy_rule;
814 :
815 0 : assert_return(m, -EINVAL);
816 0 : assert_return(m->hdr, -EINVAL);
817 0 : assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
818 :
819 0 : routing_policy_rule = NLMSG_DATA(m->hdr);
820 :
821 0 : *tos = routing_policy_rule->rtm_tos;
822 :
823 0 : return 0;
824 : }
825 :
826 0 : int sd_rtnl_message_routing_policy_rule_set_table(sd_netlink_message *m, unsigned char table) {
827 : struct rtmsg *routing_policy_rule;
828 :
829 0 : assert_return(m, -EINVAL);
830 0 : assert_return(m->hdr, -EINVAL);
831 0 : assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
832 :
833 0 : routing_policy_rule = NLMSG_DATA(m->hdr);
834 :
835 0 : routing_policy_rule->rtm_table = table;
836 :
837 0 : return 0;
838 : }
839 :
840 0 : int sd_rtnl_message_routing_policy_rule_get_table(sd_netlink_message *m, unsigned char *table) {
841 : struct rtmsg *routing_policy_rule;
842 :
843 0 : assert_return(m, -EINVAL);
844 0 : assert_return(m->hdr, -EINVAL);
845 0 : assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
846 :
847 0 : routing_policy_rule = NLMSG_DATA(m->hdr);
848 :
849 0 : *table = routing_policy_rule->rtm_table;
850 :
851 0 : return 0;
852 : }
853 :
854 0 : int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, unsigned flags) {
855 : struct rtmsg *routing_policy_rule;
856 :
857 0 : assert_return(m, -EINVAL);
858 0 : assert_return(m->hdr, -EINVAL);
859 0 : assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
860 :
861 0 : routing_policy_rule = NLMSG_DATA(m->hdr);
862 0 : routing_policy_rule->rtm_flags |= flags;
863 :
864 0 : return 0;
865 : }
866 :
867 0 : int sd_rtnl_message_routing_policy_rule_get_flags(sd_netlink_message *m, unsigned *flags) {
868 : struct rtmsg *routing_policy_rule;
869 :
870 0 : assert_return(m, -EINVAL);
871 0 : assert_return(m->hdr, -EINVAL);
872 0 : assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
873 :
874 0 : routing_policy_rule = NLMSG_DATA(m->hdr);
875 0 : *flags = routing_policy_rule->rtm_flags;
876 :
877 0 : return 0;
878 : }
879 :
880 0 : int sd_rtnl_message_routing_policy_rule_set_rtm_type(sd_netlink_message *m, unsigned char type) {
881 : struct rtmsg *routing_policy_rule;
882 :
883 0 : assert_return(m, -EINVAL);
884 0 : assert_return(m->hdr, -EINVAL);
885 0 : assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
886 :
887 0 : routing_policy_rule = NLMSG_DATA(m->hdr);
888 :
889 0 : routing_policy_rule->rtm_type = type;
890 :
891 0 : return 0;
892 : }
893 :
894 0 : int sd_rtnl_message_routing_policy_rule_get_rtm_type(sd_netlink_message *m, unsigned char *type) {
895 : struct rtmsg *routing_policy_rule;
896 :
897 0 : assert_return(m, -EINVAL);
898 0 : assert_return(m->hdr, -EINVAL);
899 0 : assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
900 :
901 0 : routing_policy_rule = NLMSG_DATA(m->hdr);
902 :
903 0 : *type = routing_policy_rule->rtm_type;
904 :
905 0 : return 0;
906 : }
907 :
908 0 : int sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(sd_netlink_message *m, unsigned char len) {
909 : struct rtmsg *routing_policy_rule;
910 :
911 0 : assert_return(m, -EINVAL);
912 0 : assert_return(m->hdr, -EINVAL);
913 0 : assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
914 :
915 0 : routing_policy_rule = NLMSG_DATA(m->hdr);
916 :
917 0 : routing_policy_rule->rtm_dst_len = len;
918 :
919 0 : return 0;
920 : }
921 :
922 0 : int sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(sd_netlink_message *m, unsigned char *len) {
923 : struct rtmsg *routing_policy_rule;
924 :
925 0 : assert_return(m, -EINVAL);
926 0 : assert_return(m->hdr, -EINVAL);
927 0 : assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
928 :
929 0 : routing_policy_rule = NLMSG_DATA(m->hdr);
930 :
931 0 : *len = routing_policy_rule->rtm_dst_len;
932 :
933 0 : return 0;
934 : }
935 :
936 0 : int sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(sd_netlink_message *m, unsigned char len) {
937 : struct rtmsg *routing_policy_rule;
938 :
939 0 : assert_return(m, -EINVAL);
940 0 : assert_return(m->hdr, -EINVAL);
941 0 : assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
942 :
943 0 : routing_policy_rule = NLMSG_DATA(m->hdr);
944 :
945 0 : routing_policy_rule->rtm_src_len = len;
946 :
947 0 : return 0;
948 : }
949 :
950 0 : int sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(sd_netlink_message *m, unsigned char *len) {
951 : struct rtmsg *routing_policy_rule;
952 :
953 0 : assert_return(m, -EINVAL);
954 0 : assert_return(m->hdr, -EINVAL);
955 0 : assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
956 :
957 0 : routing_policy_rule = NLMSG_DATA(m->hdr);
958 :
959 0 : *len = routing_policy_rule->rtm_src_len;
960 :
961 0 : return 0;
962 : }
|