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