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