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