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