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