]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-netlink/rtnl-message.c
license: LGPL-2.1+ -> LGPL-2.1-or-later
[thirdparty/systemd.git] / src / libsystemd / sd-netlink / rtnl-message.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
89489ef7
TG
2
3#include <netinet/in.h>
30746d60 4#include <linux/if_addrlabel.h>
1903c9bb 5#include <linux/if_bridge.h>
c16c7808 6#include <linux/nexthop.h>
89489ef7
TG
7#include <stdbool.h>
8#include <unistd.h>
9
07630cea
LP
10#include "sd-netlink.h"
11
f97b34a6 12#include "format-util.h"
89489ef7
TG
13#include "netlink-internal.h"
14#include "netlink-types.h"
07630cea 15#include "netlink-util.h"
07630cea
LP
16#include "socket-util.h"
17#include "util.h"
89489ef7
TG
18
19int 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
37int 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
55int 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
6b9e85a7
TG
69int 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
de157fe2 83int sd_rtnl_message_route_get_flags(const sd_netlink_message *m, unsigned *flags) {
6b9e85a7
TG
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
ec1bb279
SS
98int 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
de157fe2 112int sd_rtnl_message_route_get_family(const sd_netlink_message *m, int *family) {
89489ef7
TG
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
ec1bb279
SS
127int 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
de157fe2 141int sd_rtnl_message_route_get_type(const sd_netlink_message *m, unsigned char *type) {
983226f3
SS
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
156int 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
de157fe2 170int sd_rtnl_message_route_get_protocol(const sd_netlink_message *m, unsigned char *protocol) {
ad70f789
TG
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
de157fe2 185int sd_rtnl_message_route_get_scope(const sd_netlink_message *m, unsigned char *scope) {
ad70f789
TG
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
de157fe2 200int sd_rtnl_message_route_get_tos(const sd_netlink_message *m, unsigned char *tos) {
ad70f789
TG
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
de157fe2 215int sd_rtnl_message_route_get_table(const sd_netlink_message *m, unsigned char *table) {
ad70f789
TG
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
de157fe2 230int sd_rtnl_message_route_get_dst_prefixlen(const sd_netlink_message *m, unsigned char *dst_len) {
89489ef7
TG
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
de157fe2 245int sd_rtnl_message_route_get_src_prefixlen(const sd_netlink_message *m, unsigned char *src_len) {
89489ef7
TG
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
260int 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) ||
945c2931 268 IN_SET(rtm_family, AF_INET, AF_INET6), -EINVAL);
89489ef7
TG
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
c16c7808
SS
289int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret,
290 uint16_t nhmsg_type, int nh_family,
291 unsigned char nh_protocol) {
292 struct nhmsg *nhm;
293 int r;
294
295 assert_return(rtnl_message_type_is_nexthop(nhmsg_type), -EINVAL);
296 assert_return((nhmsg_type == RTM_GETNEXTHOP && nh_family == AF_UNSPEC) ||
297 IN_SET(nh_family, AF_INET, AF_INET6), -EINVAL);
298 assert_return(ret, -EINVAL);
299
300 r = message_new(rtnl, ret, nhmsg_type);
301 if (r < 0)
302 return r;
303
304 if (nhmsg_type == RTM_NEWNEXTHOP)
305 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
306
307 nhm = NLMSG_DATA((*ret)->hdr);
308
309 nhm->nh_family = nh_family;
310 nhm->nh_scope = RT_SCOPE_UNIVERSE;
311 nhm->nh_protocol = nh_protocol;
312
313 return 0;
314}
315
316int sd_rtnl_message_nexthop_set_flags(sd_netlink_message *m, uint8_t flags) {
317 struct nhmsg *nhm;
318
319 assert_return(m, -EINVAL);
320 assert_return(m->hdr, -EINVAL);
321 assert_return(rtnl_message_type_is_nexthop(m->hdr->nlmsg_type), -EINVAL);
322
323 nhm = NLMSG_DATA(m->hdr);
324 nhm->nh_flags |= flags;
325
326 return 0;
327}
328
329int sd_rtnl_message_nexthop_set_family(sd_netlink_message *m, uint8_t family) {
330 struct nhmsg *nhm;
331
332 assert_return(m, -EINVAL);
333 assert_return(m->hdr, -EINVAL);
334
335 nhm = NLMSG_DATA(m->hdr);
336 nhm->nh_family = family;
337
338 return 0;
339}
340
de157fe2 341int sd_rtnl_message_nexthop_get_family(const sd_netlink_message *m, uint8_t *family) {
c16c7808
SS
342 struct nhmsg *nhm;
343
344 assert_return(m, -EINVAL);
345 assert_return(m->hdr, -EINVAL);
346
347 nhm = NLMSG_DATA(m->hdr);
348 *family = nhm->nh_family ;
349
350 return 0;
351}
352
89489ef7
TG
353int sd_rtnl_message_neigh_set_flags(sd_netlink_message *m, uint8_t flags) {
354 struct ndmsg *ndm;
355
356 assert_return(m, -EINVAL);
357 assert_return(m->hdr, -EINVAL);
358 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
359
360 ndm = NLMSG_DATA(m->hdr);
361 ndm->ndm_flags |= flags;
362
363 return 0;
364}
365
366int sd_rtnl_message_neigh_set_state(sd_netlink_message *m, uint16_t state) {
367 struct ndmsg *ndm;
368
369 assert_return(m, -EINVAL);
370 assert_return(m->hdr, -EINVAL);
371 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
372
373 ndm = NLMSG_DATA(m->hdr);
374 ndm->ndm_state |= state;
375
376 return 0;
377}
378
de157fe2 379int sd_rtnl_message_neigh_get_flags(const sd_netlink_message *m, uint8_t *flags) {
89489ef7
TG
380 struct ndmsg *ndm;
381
382 assert_return(m, -EINVAL);
383 assert_return(m->hdr, -EINVAL);
384 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
385
386 ndm = NLMSG_DATA(m->hdr);
387 *flags = ndm->ndm_flags;
388
389 return 0;
390}
391
de157fe2 392int sd_rtnl_message_neigh_get_state(const sd_netlink_message *m, uint16_t *state) {
89489ef7
TG
393 struct ndmsg *ndm;
394
395 assert_return(m, -EINVAL);
396 assert_return(m->hdr, -EINVAL);
397 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
398
399 ndm = NLMSG_DATA(m->hdr);
400 *state = ndm->ndm_state;
401
402 return 0;
403}
404
de157fe2 405int sd_rtnl_message_neigh_get_family(const sd_netlink_message *m, int *family) {
89489ef7
TG
406 struct ndmsg *ndm;
407
408 assert_return(m, -EINVAL);
409 assert_return(m->hdr, -EINVAL);
410 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
411 assert_return(family, -EINVAL);
412
413 ndm = NLMSG_DATA(m->hdr);
414
415 *family = ndm->ndm_family;
416
417 return 0;
418}
419
de157fe2 420int sd_rtnl_message_neigh_get_ifindex(const sd_netlink_message *m, int *index) {
89489ef7
TG
421 struct ndmsg *ndm;
422
423 assert_return(m, -EINVAL);
424 assert_return(m->hdr, -EINVAL);
425 assert_return(rtnl_message_type_is_neigh(m->hdr->nlmsg_type), -EINVAL);
426 assert_return(index, -EINVAL);
427
428 ndm = NLMSG_DATA(m->hdr);
429
430 *index = ndm->ndm_ifindex;
431
432 return 0;
433}
434
435int sd_rtnl_message_new_neigh(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int index, int ndm_family) {
436 struct ndmsg *ndm;
437 int r;
438
439 assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
40eb1b0a 440 assert_return(IN_SET(ndm_family, AF_UNSPEC, AF_INET, AF_INET6, AF_BRIDGE), -EINVAL);
89489ef7
TG
441 assert_return(ret, -EINVAL);
442
443 r = message_new(rtnl, ret, nlmsg_type);
444 if (r < 0)
445 return r;
446
447 if (nlmsg_type == RTM_NEWNEIGH)
448 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_APPEND;
449
450 ndm = NLMSG_DATA((*ret)->hdr);
451
452 ndm->ndm_family = ndm_family;
453 ndm->ndm_ifindex = index;
454
455 return 0;
456}
457
458int sd_rtnl_message_link_set_flags(sd_netlink_message *m, unsigned flags, unsigned change) {
459 struct ifinfomsg *ifi;
460
461 assert_return(m, -EINVAL);
462 assert_return(m->hdr, -EINVAL);
463 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
464 assert_return(change, -EINVAL);
465
466 ifi = NLMSG_DATA(m->hdr);
467
468 ifi->ifi_flags = flags;
469 ifi->ifi_change = change;
470
471 return 0;
472}
473
474int sd_rtnl_message_link_set_type(sd_netlink_message *m, unsigned type) {
475 struct ifinfomsg *ifi;
476
477 assert_return(m, -EINVAL);
478 assert_return(m->hdr, -EINVAL);
479 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
480
481 ifi = NLMSG_DATA(m->hdr);
482
483 ifi->ifi_type = type;
484
485 return 0;
486}
487
488int sd_rtnl_message_link_set_family(sd_netlink_message *m, unsigned family) {
489 struct ifinfomsg *ifi;
490
491 assert_return(m, -EINVAL);
492 assert_return(m->hdr, -EINVAL);
493 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
494
495 ifi = NLMSG_DATA(m->hdr);
496
497 ifi->ifi_family = family;
498
499 return 0;
500}
501
502int sd_rtnl_message_new_link(sd_netlink *rtnl, sd_netlink_message **ret,
503 uint16_t nlmsg_type, int index) {
504 struct ifinfomsg *ifi;
505 int r;
506
507 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
89489ef7
TG
508 assert_return(ret, -EINVAL);
509
510 r = message_new(rtnl, ret, nlmsg_type);
511 if (r < 0)
512 return r;
513
514 if (nlmsg_type == RTM_NEWLINK)
515 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
a26c3073
YW
516 else if (nlmsg_type == RTM_NEWLINKPROP)
517 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL | NLM_F_APPEND;
89489ef7
TG
518
519 ifi = NLMSG_DATA((*ret)->hdr);
520
521 ifi->ifi_family = AF_UNSPEC;
522 ifi->ifi_index = index;
523
524 return 0;
525}
526
527int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen) {
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
534 ifa = NLMSG_DATA(m->hdr);
535
536 if ((ifa->ifa_family == AF_INET && prefixlen > 32) ||
537 (ifa->ifa_family == AF_INET6 && prefixlen > 128))
538 return -ERANGE;
539
540 ifa->ifa_prefixlen = prefixlen;
541
542 return 0;
543}
544
545int sd_rtnl_message_addr_set_flags(sd_netlink_message *m, unsigned char flags) {
546 struct ifaddrmsg *ifa;
547
548 assert_return(m, -EINVAL);
549 assert_return(m->hdr, -EINVAL);
550 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
551
552 ifa = NLMSG_DATA(m->hdr);
553
554 ifa->ifa_flags = flags;
555
556 return 0;
557}
558
559int sd_rtnl_message_addr_set_scope(sd_netlink_message *m, unsigned char scope) {
560 struct ifaddrmsg *ifa;
561
562 assert_return(m, -EINVAL);
563 assert_return(m->hdr, -EINVAL);
564 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
565
566 ifa = NLMSG_DATA(m->hdr);
567
568 ifa->ifa_scope = scope;
569
570 return 0;
571}
572
de157fe2 573int sd_rtnl_message_addr_get_family(const sd_netlink_message *m, int *family) {
89489ef7
TG
574 struct ifaddrmsg *ifa;
575
576 assert_return(m, -EINVAL);
577 assert_return(m->hdr, -EINVAL);
578 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
579 assert_return(family, -EINVAL);
580
581 ifa = NLMSG_DATA(m->hdr);
582
583 *family = ifa->ifa_family;
584
585 return 0;
586}
587
de157fe2 588int sd_rtnl_message_addr_get_prefixlen(const sd_netlink_message *m, unsigned char *prefixlen) {
89489ef7
TG
589 struct ifaddrmsg *ifa;
590
591 assert_return(m, -EINVAL);
592 assert_return(m->hdr, -EINVAL);
593 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
594 assert_return(prefixlen, -EINVAL);
595
596 ifa = NLMSG_DATA(m->hdr);
597
598 *prefixlen = ifa->ifa_prefixlen;
599
600 return 0;
601}
602
de157fe2 603int sd_rtnl_message_addr_get_scope(const sd_netlink_message *m, unsigned char *scope) {
89489ef7
TG
604 struct ifaddrmsg *ifa;
605
606 assert_return(m, -EINVAL);
607 assert_return(m->hdr, -EINVAL);
608 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
609 assert_return(scope, -EINVAL);
610
611 ifa = NLMSG_DATA(m->hdr);
612
613 *scope = ifa->ifa_scope;
614
615 return 0;
616}
617
de157fe2 618int sd_rtnl_message_addr_get_flags(const sd_netlink_message *m, unsigned char *flags) {
89489ef7
TG
619 struct ifaddrmsg *ifa;
620
621 assert_return(m, -EINVAL);
622 assert_return(m->hdr, -EINVAL);
623 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
624 assert_return(flags, -EINVAL);
625
626 ifa = NLMSG_DATA(m->hdr);
627
628 *flags = ifa->ifa_flags;
629
630 return 0;
631}
632
de157fe2 633int sd_rtnl_message_addr_get_ifindex(const sd_netlink_message *m, int *ifindex) {
89489ef7
TG
634 struct ifaddrmsg *ifa;
635
636 assert_return(m, -EINVAL);
637 assert_return(m->hdr, -EINVAL);
638 assert_return(rtnl_message_type_is_addr(m->hdr->nlmsg_type), -EINVAL);
639 assert_return(ifindex, -EINVAL);
640
641 ifa = NLMSG_DATA(m->hdr);
642
643 *ifindex = ifa->ifa_index;
644
645 return 0;
646}
647
648int sd_rtnl_message_new_addr(sd_netlink *rtnl, sd_netlink_message **ret,
649 uint16_t nlmsg_type, int index,
650 int family) {
651 struct ifaddrmsg *ifa;
652 int r;
653
654 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
655 assert_return((nlmsg_type == RTM_GETADDR && index == 0) ||
656 index > 0, -EINVAL);
657 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
945c2931 658 IN_SET(family, AF_INET, AF_INET6), -EINVAL);
89489ef7
TG
659 assert_return(ret, -EINVAL);
660
661 r = message_new(rtnl, ret, nlmsg_type);
662 if (r < 0)
663 return r;
664
665 if (nlmsg_type == RTM_GETADDR)
666 (*ret)->hdr->nlmsg_flags |= NLM_F_DUMP;
667
668 ifa = NLMSG_DATA((*ret)->hdr);
669
670 ifa->ifa_index = index;
671 ifa->ifa_family = family;
672 if (family == AF_INET)
673 ifa->ifa_prefixlen = 32;
674 else if (family == AF_INET6)
675 ifa->ifa_prefixlen = 128;
676
677 return 0;
678}
679
680int sd_rtnl_message_new_addr_update(sd_netlink *rtnl, sd_netlink_message **ret,
681 int index, int family) {
682 int r;
683
684 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, index, family);
685 if (r < 0)
686 return r;
687
688 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
689
690 return 0;
691}
692
de157fe2 693int sd_rtnl_message_link_get_ifindex(const sd_netlink_message *m, int *ifindex) {
89489ef7
TG
694 struct ifinfomsg *ifi;
695
696 assert_return(m, -EINVAL);
697 assert_return(m->hdr, -EINVAL);
698 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
699 assert_return(ifindex, -EINVAL);
700
701 ifi = NLMSG_DATA(m->hdr);
702
703 *ifindex = ifi->ifi_index;
704
705 return 0;
706}
707
de157fe2 708int sd_rtnl_message_link_get_flags(const sd_netlink_message *m, unsigned *flags) {
89489ef7
TG
709 struct ifinfomsg *ifi;
710
711 assert_return(m, -EINVAL);
712 assert_return(m->hdr, -EINVAL);
713 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
714 assert_return(flags, -EINVAL);
715
716 ifi = NLMSG_DATA(m->hdr);
717
718 *flags = ifi->ifi_flags;
719
720 return 0;
721}
722
de157fe2 723int sd_rtnl_message_link_get_type(const sd_netlink_message *m, unsigned short *type) {
89489ef7
TG
724 struct ifinfomsg *ifi;
725
726 assert_return(m, -EINVAL);
727 assert_return(m->hdr, -EINVAL);
728 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
729 assert_return(type, -EINVAL);
730
731 ifi = NLMSG_DATA(m->hdr);
732
733 *type = ifi->ifi_type;
734
735 return 0;
736}
737
de157fe2 738int sd_rtnl_message_get_family(const sd_netlink_message *m, int *family) {
89489ef7
TG
739 assert_return(m, -EINVAL);
740 assert_return(family, -EINVAL);
741
742 assert(m->hdr);
743
744 if (rtnl_message_type_is_link(m->hdr->nlmsg_type)) {
745 struct ifinfomsg *ifi;
746
747 ifi = NLMSG_DATA(m->hdr);
748
749 *family = ifi->ifi_family;
750
751 return 0;
752 } else if (rtnl_message_type_is_route(m->hdr->nlmsg_type)) {
753 struct rtmsg *rtm;
754
755 rtm = NLMSG_DATA(m->hdr);
756
757 *family = rtm->rtm_family;
758
759 return 0;
760 } else if (rtnl_message_type_is_neigh(m->hdr->nlmsg_type)) {
761 struct ndmsg *ndm;
762
763 ndm = NLMSG_DATA(m->hdr);
764
765 *family = ndm->ndm_family;
766
767 return 0;
768 } else if (rtnl_message_type_is_addr(m->hdr->nlmsg_type)) {
769 struct ifaddrmsg *ifa;
770
771 ifa = NLMSG_DATA(m->hdr);
772
773 *family = ifa->ifa_family;
774
bce67bbe
SS
775 return 0;
776 } else if (rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type)) {
777 struct rtmsg *rtm;
778
779 rtm = NLMSG_DATA(m->hdr);
780
781 *family = rtm->rtm_family;
782
c16c7808
SS
783 return 0;
784 } else if (rtnl_message_type_is_nexthop(m->hdr->nlmsg_type)) {
785 struct nhmsg *nhm;
786
787 nhm = NLMSG_DATA(m->hdr);
788
789 *family = nhm->nh_family;
790
89489ef7
TG
791 return 0;
792 }
793
794 return -EOPNOTSUPP;
795}
30746d60
SS
796
797int sd_rtnl_message_new_addrlabel(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex, int ifal_family) {
798 struct ifaddrlblmsg *addrlabel;
799 int r;
800
801 assert_return(rtnl_message_type_is_addrlabel(nlmsg_type), -EINVAL);
802 assert_return(ret, -EINVAL);
803
804 r = message_new(rtnl, ret, nlmsg_type);
805 if (r < 0)
806 return r;
807
808 if (nlmsg_type == RTM_NEWADDRLABEL)
809 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
810
811 addrlabel = NLMSG_DATA((*ret)->hdr);
812
813 addrlabel->ifal_family = ifal_family;
814 addrlabel->ifal_index = ifindex;
815
816 return 0;
817}
818
819int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, unsigned char prefixlen) {
820 struct ifaddrlblmsg *addrlabel;
821
822 assert_return(m, -EINVAL);
823 assert_return(m->hdr, -EINVAL);
824 assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL);
825
826 addrlabel = NLMSG_DATA(m->hdr);
827
828 if (prefixlen > 128)
829 return -ERANGE;
830
831 addrlabel->ifal_prefixlen = prefixlen;
832
833 return 0;
834}
d37b7627 835
de157fe2 836int sd_rtnl_message_addrlabel_get_prefixlen(const sd_netlink_message *m, unsigned char *prefixlen) {
d37b7627
SS
837 struct ifaddrlblmsg *addrlabel;
838
839 assert_return(m, -EINVAL);
840 assert_return(m->hdr, -EINVAL);
841 assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL);
842
843 addrlabel = NLMSG_DATA(m->hdr);
844
845 *prefixlen = addrlabel->ifal_prefixlen;
846
847 return 0;
848}
bce67bbe
SS
849
850int sd_rtnl_message_new_routing_policy_rule(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifal_family) {
851 struct rtmsg *rtm;
852 int r;
853
854 assert_return(rtnl_message_type_is_routing_policy_rule(nlmsg_type), -EINVAL);
855 assert_return(ret, -EINVAL);
856
857 r = message_new(rtnl, ret, nlmsg_type);
858 if (r < 0)
859 return r;
860
861 if (nlmsg_type == RTM_NEWRULE)
862 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
863
864 rtm = NLMSG_DATA((*ret)->hdr);
865 rtm->rtm_family = ifal_family;
866 rtm->rtm_protocol = RTPROT_BOOT;
867 rtm->rtm_scope = RT_SCOPE_UNIVERSE;
868 rtm->rtm_type = RTN_UNICAST;
869
870 return 0;
871}
872
873int sd_rtnl_message_routing_policy_rule_set_tos(sd_netlink_message *m, unsigned char tos) {
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_tos = tos;
883
884 return 0;
885}
886
de157fe2 887int sd_rtnl_message_routing_policy_rule_get_tos(const sd_netlink_message *m, unsigned char *tos) {
bce67bbe
SS
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 *tos = routing_policy_rule->rtm_tos;
897
898 return 0;
899}
900
901int sd_rtnl_message_routing_policy_rule_set_table(sd_netlink_message *m, unsigned char table) {
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_table = table;
911
912 return 0;
913}
914
de157fe2 915int sd_rtnl_message_routing_policy_rule_get_table(const sd_netlink_message *m, unsigned char *table) {
bce67bbe
SS
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 *table = routing_policy_rule->rtm_table;
925
926 return 0;
927}
928
8b220643
SS
929int sd_rtnl_message_routing_policy_rule_set_flags(sd_netlink_message *m, unsigned flags) {
930 struct rtmsg *routing_policy_rule;
931
932 assert_return(m, -EINVAL);
933 assert_return(m->hdr, -EINVAL);
934 assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
935
936 routing_policy_rule = NLMSG_DATA(m->hdr);
937 routing_policy_rule->rtm_flags |= flags;
938
939 return 0;
940}
941
de157fe2 942int sd_rtnl_message_routing_policy_rule_get_flags(const sd_netlink_message *m, unsigned *flags) {
8b220643
SS
943 struct rtmsg *routing_policy_rule;
944
945 assert_return(m, -EINVAL);
946 assert_return(m->hdr, -EINVAL);
947 assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
948
949 routing_policy_rule = NLMSG_DATA(m->hdr);
950 *flags = routing_policy_rule->rtm_flags;
951
952 return 0;
953}
954
bce67bbe
SS
955int sd_rtnl_message_routing_policy_rule_set_rtm_type(sd_netlink_message *m, unsigned char type) {
956 struct rtmsg *routing_policy_rule;
957
958 assert_return(m, -EINVAL);
959 assert_return(m->hdr, -EINVAL);
960 assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
961
962 routing_policy_rule = NLMSG_DATA(m->hdr);
963
964 routing_policy_rule->rtm_type = type;
965
966 return 0;
967}
968
de157fe2 969int sd_rtnl_message_routing_policy_rule_get_rtm_type(const sd_netlink_message *m, unsigned char *type) {
bce67bbe
SS
970 struct rtmsg *routing_policy_rule;
971
972 assert_return(m, -EINVAL);
973 assert_return(m->hdr, -EINVAL);
974 assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
975
976 routing_policy_rule = NLMSG_DATA(m->hdr);
977
978 *type = routing_policy_rule->rtm_type;
979
980 return 0;
981}
982
983int sd_rtnl_message_routing_policy_rule_set_rtm_dst_prefixlen(sd_netlink_message *m, unsigned char len) {
984 struct rtmsg *routing_policy_rule;
985
986 assert_return(m, -EINVAL);
987 assert_return(m->hdr, -EINVAL);
988 assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
989
990 routing_policy_rule = NLMSG_DATA(m->hdr);
991
992 routing_policy_rule->rtm_dst_len = len;
993
994 return 0;
995}
996
de157fe2 997int sd_rtnl_message_routing_policy_rule_get_rtm_dst_prefixlen(const sd_netlink_message *m, unsigned char *len) {
bce67bbe
SS
998 struct rtmsg *routing_policy_rule;
999
1000 assert_return(m, -EINVAL);
1001 assert_return(m->hdr, -EINVAL);
1002 assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
1003
1004 routing_policy_rule = NLMSG_DATA(m->hdr);
1005
1006 *len = routing_policy_rule->rtm_dst_len;
1007
1008 return 0;
1009}
1010
1011int sd_rtnl_message_routing_policy_rule_set_rtm_src_prefixlen(sd_netlink_message *m, unsigned char len) {
1012 struct rtmsg *routing_policy_rule;
1013
1014 assert_return(m, -EINVAL);
1015 assert_return(m->hdr, -EINVAL);
1016 assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
1017
1018 routing_policy_rule = NLMSG_DATA(m->hdr);
1019
1020 routing_policy_rule->rtm_src_len = len;
1021
1022 return 0;
1023}
1024
de157fe2 1025int sd_rtnl_message_routing_policy_rule_get_rtm_src_prefixlen(const sd_netlink_message *m, unsigned char *len) {
bce67bbe
SS
1026 struct rtmsg *routing_policy_rule;
1027
1028 assert_return(m, -EINVAL);
1029 assert_return(m->hdr, -EINVAL);
1030 assert_return(rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type), -EINVAL);
1031
1032 routing_policy_rule = NLMSG_DATA(m->hdr);
1033
1034 *len = routing_policy_rule->rtm_src_len;
1035
1036 return 0;
1037}
0f5bd7fe
SS
1038
1039int sd_rtnl_message_new_qdisc(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int tcm_family, int tcm_ifindex) {
1040 struct tcmsg *tcm;
1041 int r;
1042
1043 assert_return(rtnl_message_type_is_qdisc(nlmsg_type), -EINVAL);
1044 assert_return(ret, -EINVAL);
1045
1046 r = message_new(rtnl, ret, nlmsg_type);
1047 if (r < 0)
1048 return r;
1049
1050 if (nlmsg_type == RTM_NEWQDISC)
1051 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
1052
1053 tcm = NLMSG_DATA((*ret)->hdr);
1054 tcm->tcm_family = tcm_family;
1055 tcm->tcm_ifindex = tcm_ifindex;
1056
1057 return 0;
1058}
1059
1060int sd_rtnl_message_set_qdisc_parent(sd_netlink_message *m, uint32_t parent) {
1061 struct tcmsg *tcm;
1062
1063 assert_return(rtnl_message_type_is_qdisc(m->hdr->nlmsg_type), -EINVAL);
1064
1065 tcm = NLMSG_DATA(m->hdr);
1066 tcm->tcm_parent = parent;
1067
1068 return 0;
1069}
1070
1071int sd_rtnl_message_set_qdisc_handle(sd_netlink_message *m, uint32_t handle) {
1072 struct tcmsg *tcm;
1073
1074 assert_return(rtnl_message_type_is_qdisc(m->hdr->nlmsg_type), -EINVAL);
1075
1076 tcm = NLMSG_DATA(m->hdr);
1077 tcm->tcm_handle = handle;
1078
1079 return 0;
1080}
0ebb76de
YW
1081
1082int sd_rtnl_message_new_tclass(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int tcm_family, int tcm_ifindex) {
1083 struct tcmsg *tcm;
1084 int r;
1085
1086 assert_return(rtnl_message_type_is_tclass(nlmsg_type), -EINVAL);
1087 assert_return(ret, -EINVAL);
1088
1089 r = message_new(rtnl, ret, nlmsg_type);
1090 if (r < 0)
1091 return r;
1092
1093 if (nlmsg_type == RTM_NEWTCLASS)
1094 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
1095
1096 tcm = NLMSG_DATA((*ret)->hdr);
1097 tcm->tcm_family = tcm_family;
1098 tcm->tcm_ifindex = tcm_ifindex;
1099
1100 return 0;
1101}
1102
1103int sd_rtnl_message_set_tclass_parent(sd_netlink_message *m, uint32_t parent) {
1104 struct tcmsg *tcm;
1105
1106 assert_return(rtnl_message_type_is_tclass(m->hdr->nlmsg_type), -EINVAL);
1107
1108 tcm = NLMSG_DATA(m->hdr);
1109 tcm->tcm_parent = parent;
1110
1111 return 0;
1112}
1113
1114int sd_rtnl_message_set_tclass_handle(sd_netlink_message *m, uint32_t handle) {
1115 struct tcmsg *tcm;
1116
1117 assert_return(rtnl_message_type_is_tclass(m->hdr->nlmsg_type), -EINVAL);
1118
1119 tcm = NLMSG_DATA(m->hdr);
1120 tcm->tcm_handle = handle;
1121
1122 return 0;
1123}
1903c9bb
DM
1124
1125int sd_rtnl_message_new_mdb(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int mdb_ifindex) {
1126 struct br_port_msg *bpm;
1127 int r;
1128
1129 assert_return(rtnl_message_type_is_mdb(nlmsg_type), -EINVAL);
1130 assert_return(ret, -EINVAL);
1131
1132 r = message_new(rtnl, ret, nlmsg_type);
1133 if (r < 0)
1134 return r;
1135
1136 if (nlmsg_type == RTM_NEWMDB)
1137 (*ret)->hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
1138
1139 bpm = NLMSG_DATA((*ret)->hdr);
1140 bpm->family = AF_BRIDGE;
1141 bpm->ifindex = mdb_ifindex;
1142
1143 return 0;
1144}