]> git.ipfire.org Git - thirdparty/systemd.git/blame_incremental - src/libsystemd/sd-netlink/netlink-message-rtnl.c
man: improve Description= documentation (#38101)
[thirdparty/systemd.git] / src / libsystemd / sd-netlink / netlink-message-rtnl.c
... / ...
CommitLineData
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3#include <linux/fib_rules.h>
4#include <linux/if_addrlabel.h>
5#include <linux/if_bridge.h>
6#include <linux/nexthop.h>
7
8#include "sd-netlink.h"
9
10#include "in-addr-util.h"
11#include "netlink-internal.h"
12
13static bool rtnl_message_type_is_neigh(uint16_t type) {
14 return IN_SET(type, RTM_NEWNEIGH, RTM_GETNEIGH, RTM_DELNEIGH);
15}
16
17static bool rtnl_message_type_is_route(uint16_t type) {
18 return IN_SET(type, RTM_NEWROUTE, RTM_GETROUTE, RTM_DELROUTE);
19}
20
21static bool rtnl_message_type_is_nexthop(uint16_t type) {
22 return IN_SET(type, RTM_NEWNEXTHOP, RTM_GETNEXTHOP, RTM_DELNEXTHOP);
23}
24
25static bool rtnl_message_type_is_link(uint16_t type) {
26 return IN_SET(type,
27 RTM_NEWLINK, RTM_SETLINK, RTM_GETLINK, RTM_DELLINK,
28 RTM_NEWLINKPROP, RTM_DELLINKPROP, RTM_GETLINKPROP);
29}
30
31static bool rtnl_message_type_is_addr(uint16_t type) {
32 return IN_SET(type, RTM_NEWADDR, RTM_GETADDR, RTM_DELADDR);
33}
34
35static bool rtnl_message_type_is_addrlabel(uint16_t type) {
36 return IN_SET(type, RTM_NEWADDRLABEL, RTM_DELADDRLABEL, RTM_GETADDRLABEL);
37}
38
39static bool rtnl_message_type_is_routing_policy_rule(uint16_t type) {
40 return IN_SET(type, RTM_NEWRULE, RTM_DELRULE, RTM_GETRULE);
41}
42
43static bool rtnl_message_type_is_traffic_control(uint16_t type) {
44 return IN_SET(type,
45 RTM_NEWQDISC, RTM_DELQDISC, RTM_GETQDISC,
46 RTM_NEWTCLASS, RTM_DELTCLASS, RTM_GETTCLASS);
47}
48
49static bool rtnl_message_type_is_mdb(uint16_t type) {
50 return IN_SET(type, RTM_NEWMDB, RTM_DELMDB, RTM_GETMDB);
51}
52
53static bool rtnl_message_type_is_nsid(uint16_t type) {
54 return IN_SET(type, RTM_NEWNSID, RTM_DELNSID, RTM_GETNSID);
55}
56
57#define DEFINE_RTNL_MESSAGE_SETTER(class, header_type, element, name, value_type) \
58 int sd_rtnl_message_##class##_set_##name(sd_netlink_message *m, value_type value) { \
59 assert_return(m, -EINVAL); \
60 assert_return(m->hdr, -EINVAL); \
61 assert_return(rtnl_message_type_is_##class(m->hdr->nlmsg_type), -EINVAL); \
62 \
63 header_type *hdr = NLMSG_DATA(m->hdr); \
64 hdr->element = value; \
65 return 0; \
66 }
67
68#define DEFINE_RTNL_MESSAGE_PREFIXLEN_SETTER(class, header_type, family_element, element, name, value_type) \
69 int sd_rtnl_message_##class##_set_##name(sd_netlink_message *m, value_type value) { \
70 assert_return(m, -EINVAL); \
71 assert_return(m->hdr, -EINVAL); \
72 assert_return(rtnl_message_type_is_##class(m->hdr->nlmsg_type), -EINVAL); \
73 \
74 header_type *hdr = NLMSG_DATA(m->hdr); \
75 \
76 if (value > FAMILY_ADDRESS_SIZE_SAFE(hdr->family_element) * 8) \
77 return -ERANGE; \
78 \
79 hdr->element = value; \
80 return 0; \
81 }
82
83#define DEFINE_RTNL_MESSAGE_ADDR_SETTER(element, name, value_type) \
84 DEFINE_RTNL_MESSAGE_SETTER(addr, struct ifaddrmsg, element, name, value_type)
85#define DEFINE_RTNL_MESSAGE_LINK_SETTER(element, name, value_type) \
86 DEFINE_RTNL_MESSAGE_SETTER(link, struct ifinfomsg, element, name, value_type)
87#define DEFINE_RTNL_MESSAGE_ROUTE_SETTER(element, name, value_type) \
88 DEFINE_RTNL_MESSAGE_SETTER(route, struct rtmsg, element, name, value_type)
89#define DEFINE_RTNL_MESSAGE_NEXTHOP_SETTER(element, name, value_type) \
90 DEFINE_RTNL_MESSAGE_SETTER(nexthop, struct nhmsg, element, name, value_type)
91#define DEFINE_RTNL_MESSAGE_NEIGH_SETTER(element, name, value_type) \
92 DEFINE_RTNL_MESSAGE_SETTER(neigh, struct ndmsg, element, name, value_type)
93#define DEFINE_RTNL_MESSAGE_ADDRLABEL_SETTER(element, name, value_type) \
94 DEFINE_RTNL_MESSAGE_SETTER(addrlabel, struct ifaddrlblmsg, element, name, value_type)
95#define DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_SETTER(element, name, value_type) \
96 DEFINE_RTNL_MESSAGE_SETTER(routing_policy_rule, struct fib_rule_hdr, element, name, value_type)
97#define DEFINE_RTNL_MESSAGE_TRAFFIC_CONTROL_SETTER(element, name, value_type) \
98 DEFINE_RTNL_MESSAGE_SETTER(traffic_control, struct tcmsg, element, name, value_type)
99
100#define DEFINE_RTNL_MESSAGE_GETTER(class, header_type, element, name, value_type) \
101 int sd_rtnl_message_##class##_get_##name(sd_netlink_message *m, value_type *ret) { \
102 assert_return(m, -EINVAL); \
103 assert_return(m->hdr, -EINVAL); \
104 assert_return(rtnl_message_type_is_##class(m->hdr->nlmsg_type), -EINVAL); \
105 assert_return(ret, -EINVAL); \
106 \
107 header_type *hdr = NLMSG_DATA(m->hdr); \
108 *ret = hdr->element; \
109 return 0; \
110 }
111
112#define DEFINE_RTNL_MESSAGE_ADDR_GETTER(element, name, value_type) \
113 DEFINE_RTNL_MESSAGE_GETTER(addr, struct ifaddrmsg, element, name, value_type)
114#define DEFINE_RTNL_MESSAGE_LINK_GETTER(element, name, value_type) \
115 DEFINE_RTNL_MESSAGE_GETTER(link, struct ifinfomsg, element, name, value_type)
116#define DEFINE_RTNL_MESSAGE_ROUTE_GETTER(element, name, value_type) \
117 DEFINE_RTNL_MESSAGE_GETTER(route, struct rtmsg, element, name, value_type)
118#define DEFINE_RTNL_MESSAGE_NEXTHOP_GETTER(element, name, value_type) \
119 DEFINE_RTNL_MESSAGE_GETTER(nexthop, struct nhmsg, element, name, value_type)
120#define DEFINE_RTNL_MESSAGE_NEIGH_GETTER(element, name, value_type) \
121 DEFINE_RTNL_MESSAGE_GETTER(neigh, struct ndmsg, element, name, value_type)
122#define DEFINE_RTNL_MESSAGE_ADDRLABEL_GETTER(element, name, value_type) \
123 DEFINE_RTNL_MESSAGE_GETTER(addrlabel, struct ifaddrlblmsg, element, name, value_type)
124#define DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_GETTER(element, name, value_type) \
125 DEFINE_RTNL_MESSAGE_GETTER(routing_policy_rule, struct fib_rule_hdr, element, name, value_type)
126#define DEFINE_RTNL_MESSAGE_TRAFFIC_CONTROL_GETTER(element, name, value_type) \
127 DEFINE_RTNL_MESSAGE_GETTER(traffic_control, struct tcmsg, element, name, value_type)
128
129DEFINE_RTNL_MESSAGE_ADDR_GETTER(ifa_index, ifindex, int);
130DEFINE_RTNL_MESSAGE_ADDR_GETTER(ifa_family, family, int);
131DEFINE_RTNL_MESSAGE_PREFIXLEN_SETTER(addr, struct ifaddrmsg, ifa_family, ifa_prefixlen, prefixlen, uint8_t);
132DEFINE_RTNL_MESSAGE_ADDR_GETTER(ifa_prefixlen, prefixlen, uint8_t);
133DEFINE_RTNL_MESSAGE_ADDR_SETTER(ifa_scope, scope, uint8_t);
134DEFINE_RTNL_MESSAGE_ADDR_GETTER(ifa_scope, scope, uint8_t);
135
136DEFINE_RTNL_MESSAGE_LINK_GETTER(ifi_index, ifindex, int);
137DEFINE_RTNL_MESSAGE_LINK_SETTER(ifi_family, family, int);
138DEFINE_RTNL_MESSAGE_LINK_GETTER(ifi_family, family, int);
139DEFINE_RTNL_MESSAGE_LINK_SETTER(ifi_type, type, uint16_t);
140DEFINE_RTNL_MESSAGE_LINK_GETTER(ifi_type, type, uint16_t);
141DEFINE_RTNL_MESSAGE_LINK_GETTER(ifi_flags, flags, uint32_t);
142
143int sd_rtnl_message_link_set_flags(sd_netlink_message *m, uint32_t flags, uint32_t change) {
144 struct ifinfomsg *ifi;
145
146 assert_return(m, -EINVAL);
147 assert_return(m->hdr, -EINVAL);
148 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
149 assert_return(change != 0, -EINVAL);
150
151 ifi = NLMSG_DATA(m->hdr);
152
153 ifi->ifi_flags = flags;
154 ifi->ifi_change = change;
155
156 return 0;
157}
158
159DEFINE_RTNL_MESSAGE_ROUTE_GETTER(rtm_family, family, int);
160DEFINE_RTNL_MESSAGE_PREFIXLEN_SETTER(route, struct rtmsg, rtm_family, rtm_dst_len, dst_prefixlen, uint8_t);
161DEFINE_RTNL_MESSAGE_ROUTE_GETTER(rtm_dst_len, dst_prefixlen, uint8_t);
162DEFINE_RTNL_MESSAGE_PREFIXLEN_SETTER(route, struct rtmsg, rtm_family, rtm_src_len, src_prefixlen, uint8_t);
163DEFINE_RTNL_MESSAGE_ROUTE_GETTER(rtm_src_len, src_prefixlen, uint8_t);
164DEFINE_RTNL_MESSAGE_ROUTE_SETTER(rtm_tos, tos, uint8_t);
165DEFINE_RTNL_MESSAGE_ROUTE_GETTER(rtm_tos, tos, uint8_t);
166DEFINE_RTNL_MESSAGE_ROUTE_SETTER(rtm_table, table, uint8_t);
167DEFINE_RTNL_MESSAGE_ROUTE_GETTER(rtm_table, table, uint8_t);
168DEFINE_RTNL_MESSAGE_ROUTE_GETTER(rtm_protocol, protocol, uint8_t);
169DEFINE_RTNL_MESSAGE_ROUTE_SETTER(rtm_scope, scope, uint8_t);
170DEFINE_RTNL_MESSAGE_ROUTE_GETTER(rtm_scope, scope, uint8_t);
171DEFINE_RTNL_MESSAGE_ROUTE_SETTER(rtm_type, type, uint8_t);
172DEFINE_RTNL_MESSAGE_ROUTE_GETTER(rtm_type, type, uint8_t);
173DEFINE_RTNL_MESSAGE_ROUTE_SETTER(rtm_flags, flags, uint32_t);
174DEFINE_RTNL_MESSAGE_ROUTE_GETTER(rtm_flags, flags, uint32_t);
175
176DEFINE_RTNL_MESSAGE_NEXTHOP_GETTER(nh_family, family, int);
177DEFINE_RTNL_MESSAGE_NEXTHOP_SETTER(nh_flags, flags, uint32_t);
178DEFINE_RTNL_MESSAGE_NEXTHOP_GETTER(nh_flags, flags, uint32_t);
179DEFINE_RTNL_MESSAGE_NEXTHOP_GETTER(nh_protocol, protocol, uint8_t);
180
181DEFINE_RTNL_MESSAGE_NEIGH_GETTER(ndm_ifindex, ifindex, int);
182DEFINE_RTNL_MESSAGE_NEIGH_GETTER(ndm_family, family, int);
183DEFINE_RTNL_MESSAGE_NEIGH_SETTER(ndm_state, state, uint16_t);
184DEFINE_RTNL_MESSAGE_NEIGH_GETTER(ndm_state, state, uint16_t);
185DEFINE_RTNL_MESSAGE_NEIGH_SETTER(ndm_flags, flags, uint8_t);
186DEFINE_RTNL_MESSAGE_NEIGH_GETTER(ndm_flags, flags, uint8_t);
187
188DEFINE_RTNL_MESSAGE_ADDRLABEL_GETTER(ifal_prefixlen, prefixlen, uint8_t);
189
190int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, uint8_t prefixlen) {
191 struct ifaddrlblmsg *addrlabel;
192
193 assert_return(m, -EINVAL);
194 assert_return(m->hdr, -EINVAL);
195 assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL);
196
197 addrlabel = NLMSG_DATA(m->hdr);
198
199 if (prefixlen > 128)
200 return -ERANGE;
201
202 addrlabel->ifal_prefixlen = prefixlen;
203
204 return 0;
205}
206
207DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_GETTER(family, family, int);
208DEFINE_RTNL_MESSAGE_PREFIXLEN_SETTER(routing_policy_rule, struct fib_rule_hdr, family, dst_len, dst_prefixlen, uint8_t);
209DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_GETTER(dst_len, dst_prefixlen, uint8_t);
210DEFINE_RTNL_MESSAGE_PREFIXLEN_SETTER(routing_policy_rule, struct fib_rule_hdr, family, src_len, src_prefixlen, uint8_t);
211DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_GETTER(src_len, src_prefixlen, uint8_t);
212DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_SETTER(tos, tos, uint8_t);
213DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_GETTER(tos, tos, uint8_t);
214DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_SETTER(table, table, uint8_t);
215DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_GETTER(table, table, uint8_t);
216DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_SETTER(action, action, uint8_t);
217DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_GETTER(action, action, uint8_t);
218DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_SETTER(flags, flags, uint32_t);
219DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_GETTER(flags, flags, uint32_t);
220
221DEFINE_RTNL_MESSAGE_TRAFFIC_CONTROL_GETTER(tcm_ifindex, ifindex, int);
222DEFINE_RTNL_MESSAGE_TRAFFIC_CONTROL_GETTER(tcm_handle, handle, uint32_t);
223DEFINE_RTNL_MESSAGE_TRAFFIC_CONTROL_GETTER(tcm_parent, parent, uint32_t);
224
225int sd_rtnl_message_new_route(
226 sd_netlink *rtnl,
227 sd_netlink_message **ret,
228 uint16_t nlmsg_type,
229 int family,
230 uint8_t protocol) {
231
232 struct rtmsg *rtm;
233 int r;
234
235 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
236 assert_return((nlmsg_type == RTM_GETROUTE && family == AF_UNSPEC) ||
237 IN_SET(family, AF_INET, AF_INET6), -EINVAL);
238 assert_return(ret, -EINVAL);
239
240 r = message_new(rtnl,
241 ret,
242 nlmsg_type,
243 NLM_F_REQUEST|NLM_F_ACK|(nlmsg_type == RTM_NEWROUTE ? NLM_F_CREATE | NLM_F_APPEND : 0));
244 if (r < 0)
245 return r;
246
247 rtm = NLMSG_DATA((*ret)->hdr);
248
249 rtm->rtm_family = family;
250 rtm->rtm_protocol = protocol;
251
252 return 0;
253}
254
255int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret,
256 uint16_t nlmsg_type, int family,
257 uint8_t protocol) {
258 struct nhmsg *nhm;
259 int r;
260
261 assert_return(rtnl_message_type_is_nexthop(nlmsg_type), -EINVAL);
262 switch (nlmsg_type) {
263 case RTM_DELNEXTHOP:
264 assert_return(family == AF_UNSPEC, -EINVAL);
265 _fallthrough_;
266 case RTM_GETNEXTHOP:
267 assert_return(protocol == RTPROT_UNSPEC, -EINVAL);
268 break;
269 case RTM_NEWNEXTHOP:
270 assert_return(IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6), -EINVAL);
271 break;
272 default:
273 assert_not_reached();
274 }
275 assert_return(ret, -EINVAL);
276
277 r = message_new(rtnl,
278 ret,
279 nlmsg_type,
280 NLM_F_REQUEST | NLM_F_ACK | (nlmsg_type == RTM_NEWNEXTHOP ? NLM_F_CREATE | NLM_F_REPLACE : 0));
281 if (r < 0)
282 return r;
283
284 nhm = NLMSG_DATA((*ret)->hdr);
285
286 nhm->nh_family = family;
287 nhm->nh_scope = RT_SCOPE_UNIVERSE;
288 nhm->nh_protocol = protocol;
289
290 return 0;
291}
292
293int sd_rtnl_message_new_neigh(
294 sd_netlink *rtnl,
295 sd_netlink_message **ret,
296 uint16_t nlmsg_type,
297 int ifindex,
298 int family) {
299
300 struct ndmsg *ndm;
301 int r;
302
303 assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
304 assert_return(IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6, AF_BRIDGE), -EINVAL);
305 assert_return(ret, -EINVAL);
306
307 uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
308 if (nlmsg_type == RTM_NEWNEIGH) {
309 if (family == AF_BRIDGE)
310 flags |= NLM_F_CREATE | NLM_F_APPEND;
311 else
312 flags |= NLM_F_CREATE | NLM_F_REPLACE;
313 }
314
315 r = message_new(rtnl, ret, nlmsg_type, flags);
316 if (r < 0)
317 return r;
318
319 ndm = NLMSG_DATA((*ret)->hdr);
320
321 ndm->ndm_family = family;
322 ndm->ndm_ifindex = ifindex;
323
324 return 0;
325}
326
327int sd_rtnl_message_new_link(sd_netlink *rtnl, sd_netlink_message **ret, uint16_t nlmsg_type, int ifindex) {
328 struct ifinfomsg *ifi;
329 int r;
330
331 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
332 assert_return(ret, -EINVAL);
333
334 uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
335 if (nlmsg_type == RTM_NEWLINK && ifindex == 0)
336 flags |= NLM_F_CREATE | NLM_F_EXCL;
337 else if (nlmsg_type == RTM_NEWLINKPROP)
338 flags |= NLM_F_CREATE | NLM_F_EXCL | NLM_F_APPEND;
339
340 r = message_new(rtnl, ret, nlmsg_type, flags);
341 if (r < 0)
342 return r;
343
344 ifi = NLMSG_DATA((*ret)->hdr);
345
346 ifi->ifi_family = AF_UNSPEC;
347 ifi->ifi_index = ifindex;
348
349 return 0;
350}
351
352int sd_rtnl_message_new_addr(
353 sd_netlink *rtnl,
354 sd_netlink_message **ret,
355 uint16_t nlmsg_type,
356 int ifindex,
357 int family) {
358
359 struct ifaddrmsg *ifa;
360 int r;
361
362 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
363 assert_return((nlmsg_type == RTM_GETADDR && ifindex == 0) ||
364 ifindex > 0, -EINVAL);
365 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
366 IN_SET(family, AF_INET, AF_INET6), -EINVAL);
367 assert_return(ret, -EINVAL);
368
369 r = message_new(rtnl, ret, nlmsg_type, NLM_F_REQUEST | NLM_F_ACK);
370 if (r < 0)
371 return r;
372
373 ifa = NLMSG_DATA((*ret)->hdr);
374
375 ifa->ifa_index = ifindex;
376 ifa->ifa_family = family;
377
378 return 0;
379}
380
381int sd_rtnl_message_new_addr_update(
382 sd_netlink *rtnl,
383 sd_netlink_message **ret,
384 int ifindex,
385 int family) {
386 int r;
387
388 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, ifindex, family);
389 if (r < 0)
390 return r;
391
392 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
393
394 return 0;
395}
396
397int sd_rtnl_message_get_family(sd_netlink_message *m, int *ret) {
398 assert_return(m, -EINVAL);
399 assert_return(ret, -EINVAL);
400
401 assert(m->hdr);
402
403 if (rtnl_message_type_is_link(m->hdr->nlmsg_type))
404 return sd_rtnl_message_link_get_family(m, ret);
405
406 if (rtnl_message_type_is_route(m->hdr->nlmsg_type))
407 return sd_rtnl_message_route_get_family(m, ret);
408
409 if (rtnl_message_type_is_neigh(m->hdr->nlmsg_type))
410 return sd_rtnl_message_neigh_get_family(m, ret);
411
412 if (rtnl_message_type_is_addr(m->hdr->nlmsg_type))
413 return sd_rtnl_message_addr_get_family(m, ret);
414
415 if (rtnl_message_type_is_routing_policy_rule(m->hdr->nlmsg_type))
416 return sd_rtnl_message_routing_policy_rule_get_family(m, ret);
417
418 if (rtnl_message_type_is_nexthop(m->hdr->nlmsg_type))
419 return sd_rtnl_message_nexthop_get_family(m, ret);
420
421 return -EOPNOTSUPP;
422}
423
424int sd_rtnl_message_new_addrlabel(
425 sd_netlink *rtnl,
426 sd_netlink_message **ret,
427 uint16_t nlmsg_type,
428 int ifindex,
429 int family) {
430
431 struct ifaddrlblmsg *addrlabel;
432 int r;
433
434 assert_return(rtnl_message_type_is_addrlabel(nlmsg_type), -EINVAL);
435 assert_return(ret, -EINVAL);
436
437 r = message_new(rtnl,
438 ret,
439 nlmsg_type,
440 NLM_F_REQUEST | NLM_F_ACK | (nlmsg_type == RTM_NEWADDRLABEL ? NLM_F_CREATE | NLM_F_REPLACE : 0));
441 if (r < 0)
442 return r;
443
444 addrlabel = NLMSG_DATA((*ret)->hdr);
445
446 addrlabel->ifal_family = family;
447 addrlabel->ifal_index = ifindex;
448
449 return 0;
450}
451
452int sd_rtnl_message_new_routing_policy_rule(
453 sd_netlink *rtnl,
454 sd_netlink_message **ret,
455 uint16_t nlmsg_type,
456 int family) {
457
458 struct fib_rule_hdr *frh;
459 int r;
460
461 assert_return(rtnl_message_type_is_routing_policy_rule(nlmsg_type), -EINVAL);
462 assert_return(ret, -EINVAL);
463
464 r = message_new(rtnl,
465 ret,
466 nlmsg_type,
467 NLM_F_REQUEST | NLM_F_ACK | (nlmsg_type == RTM_NEWRULE ? NLM_F_CREATE | NLM_F_EXCL : 0));
468 if (r < 0)
469 return r;
470
471 frh = NLMSG_DATA((*ret)->hdr);
472 frh->family = family;
473
474 return 0;
475}
476
477int sd_rtnl_message_new_traffic_control(
478 sd_netlink *rtnl,
479 sd_netlink_message **ret,
480 uint16_t nlmsg_type,
481 int ifindex,
482 uint32_t handle,
483 uint32_t parent) {
484
485 struct tcmsg *tcm;
486 int r;
487
488 assert_return(rtnl_message_type_is_traffic_control(nlmsg_type), -EINVAL);
489 assert_return(ret, -EINVAL);
490
491 r = message_new(rtnl,
492 ret,
493 nlmsg_type,
494 NLM_F_REQUEST | NLM_F_ACK | (IN_SET(nlmsg_type, RTM_NEWQDISC, RTM_NEWTCLASS) ? NLM_F_CREATE | NLM_F_REPLACE : 0));
495 if (r < 0)
496 return r;
497
498 tcm = NLMSG_DATA((*ret)->hdr);
499 tcm->tcm_ifindex = ifindex;
500 tcm->tcm_handle = handle;
501 tcm->tcm_parent = parent;
502
503 return 0;
504}
505
506int sd_rtnl_message_new_mdb(
507 sd_netlink *rtnl,
508 sd_netlink_message **ret,
509 uint16_t nlmsg_type,
510 int ifindex) {
511
512 struct br_port_msg *bpm;
513 int r;
514
515 assert_return(rtnl_message_type_is_mdb(nlmsg_type), -EINVAL);
516 assert_return(ret, -EINVAL);
517
518 r = message_new(rtnl,
519 ret,
520 nlmsg_type,
521 NLM_F_REQUEST | NLM_F_ACK | (nlmsg_type == RTM_NEWMDB ? NLM_F_CREATE | NLM_F_REPLACE : 0));
522 if (r < 0)
523 return r;
524
525 bpm = NLMSG_DATA((*ret)->hdr);
526 bpm->family = AF_BRIDGE;
527 bpm->ifindex = ifindex;
528
529 return 0;
530}
531
532int sd_rtnl_message_new_nsid(
533 sd_netlink *rtnl,
534 sd_netlink_message **ret,
535 uint16_t nlmsg_type) {
536
537 struct rtgenmsg *rt;
538 int r;
539
540 assert_return(rtnl_message_type_is_nsid(nlmsg_type), -EINVAL);
541 assert_return(ret, -EINVAL);
542
543 r = message_new(rtnl, ret, nlmsg_type, NLM_F_REQUEST | NLM_F_ACK);
544 if (r < 0)
545 return r;
546
547 rt = NLMSG_DATA((*ret)->hdr);
548 rt->rtgen_family = AF_UNSPEC;
549
550 return 0;
551}