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