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