]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-netlink/netlink-message-rtnl.c
basic/include: replace _Static_assert() with static_assert()
[thirdparty/systemd.git] / src / libsystemd / sd-netlink / netlink-message-rtnl.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
89489ef7 2
b43dfb6e 3#include <linux/fib_rules.h>
30746d60 4#include <linux/if_addrlabel.h>
1903c9bb 5#include <linux/if_bridge.h>
c16c7808 6#include <linux/nexthop.h>
89489ef7 7
07630cea
LP
8#include "sd-netlink.h"
9
5cdf13c7 10#include "in-addr-util.h"
89489ef7 11#include "netlink-internal.h"
89489ef7 12
13c026ca
YW
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
10786280
LP
53static bool rtnl_message_type_is_nsid(uint16_t type) {
54 return IN_SET(type, RTM_NEWNSID, RTM_DELNSID, RTM_GETNSID);
55}
56
2bc1d783
YW
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 }
ad70f789 67
2bc1d783
YW
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 }
ad70f789 82
2bc1d783
YW
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 }
ad70f789 111
2bc1d783
YW
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);
2bc1d783
YW
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);
ba8d48be 138DEFINE_RTNL_MESSAGE_LINK_GETTER(ifi_family, family, int);
2bc1d783
YW
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);
ad70f789 142
2bc1d783
YW
143int sd_rtnl_message_link_set_flags(sd_netlink_message *m, uint32_t flags, uint32_t change) {
144 struct ifinfomsg *ifi;
ad70f789
TG
145
146 assert_return(m, -EINVAL);
147 assert_return(m->hdr, -EINVAL);
2bc1d783
YW
148 assert_return(rtnl_message_type_is_link(m->hdr->nlmsg_type), -EINVAL);
149 assert_return(change != 0, -EINVAL);
ad70f789 150
2bc1d783 151 ifi = NLMSG_DATA(m->hdr);
ad70f789 152
2bc1d783
YW
153 ifi->ifi_flags = flags;
154 ifi->ifi_change = change;
ad70f789
TG
155
156 return 0;
157}
158
2bc1d783
YW
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);
ad70f789 175
2bc1d783
YW
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);
ad70f789 180
2bc1d783
YW
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);
ad70f789 187
2bc1d783 188DEFINE_RTNL_MESSAGE_ADDRLABEL_GETTER(ifal_prefixlen, prefixlen, uint8_t);
ad70f789 189
2bc1d783
YW
190int sd_rtnl_message_addrlabel_set_prefixlen(sd_netlink_message *m, uint8_t prefixlen) {
191 struct ifaddrlblmsg *addrlabel;
ad70f789
TG
192
193 assert_return(m, -EINVAL);
194 assert_return(m->hdr, -EINVAL);
2bc1d783 195 assert_return(rtnl_message_type_is_addrlabel(m->hdr->nlmsg_type), -EINVAL);
89489ef7 196
2bc1d783 197 addrlabel = NLMSG_DATA(m->hdr);
89489ef7 198
2bc1d783
YW
199 if (prefixlen > 128)
200 return -ERANGE;
89489ef7 201
2bc1d783 202 addrlabel->ifal_prefixlen = prefixlen;
89489ef7
TG
203
204 return 0;
205}
206
ba8d48be 207DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_GETTER(family, family, int);
9b8cb789
YW
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);
2bc1d783
YW
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);
9b8cb789
YW
216DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_SETTER(action, action, uint8_t);
217DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_GETTER(action, action, uint8_t);
2bc1d783
YW
218DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_SETTER(flags, flags, uint32_t);
219DEFINE_RTNL_MESSAGE_ROUTING_POLICY_RULE_GETTER(flags, flags, uint32_t);
89489ef7 220
2bc1d783
YW
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);
89489ef7 224
ae298c93
YW
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
89489ef7
TG
232 struct rtmsg *rtm;
233 int r;
234
235 assert_return(rtnl_message_type_is_route(nlmsg_type), -EINVAL);
ae298c93
YW
236 assert_return((nlmsg_type == RTM_GETROUTE && family == AF_UNSPEC) ||
237 IN_SET(family, AF_INET, AF_INET6), -EINVAL);
89489ef7
TG
238 assert_return(ret, -EINVAL);
239
6e196011
LP
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));
89489ef7
TG
244 if (r < 0)
245 return r;
246
89489ef7
TG
247 rtm = NLMSG_DATA((*ret)->hdr);
248
ae298c93
YW
249 rtm->rtm_family = family;
250 rtm->rtm_protocol = protocol;
89489ef7
TG
251
252 return 0;
253}
254
dd35a61c 255int sd_rtnl_message_new_nexthop(sd_netlink *rtnl, sd_netlink_message **ret,
ae298c93
YW
256 uint16_t nlmsg_type, int family,
257 uint8_t protocol) {
c16c7808
SS
258 struct nhmsg *nhm;
259 int r;
260
409856d3 261 assert_return(rtnl_message_type_is_nexthop(nlmsg_type), -EINVAL);
79893116 262 switch (nlmsg_type) {
735a3d73 263 case RTM_DELNEXTHOP:
ae298c93 264 assert_return(family == AF_UNSPEC, -EINVAL);
735a3d73
YW
265 _fallthrough_;
266 case RTM_GETNEXTHOP:
ae298c93 267 assert_return(protocol == RTPROT_UNSPEC, -EINVAL);
735a3d73
YW
268 break;
269 case RTM_NEWNEXTHOP:
ae298c93 270 assert_return(IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6), -EINVAL);
735a3d73
YW
271 break;
272 default:
04499a70 273 assert_not_reached();
735a3d73 274 }
c16c7808
SS
275 assert_return(ret, -EINVAL);
276
6e196011
LP
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));
c16c7808
SS
281 if (r < 0)
282 return r;
283
c16c7808
SS
284 nhm = NLMSG_DATA((*ret)->hdr);
285
ae298c93 286 nhm->nh_family = family;
c16c7808 287 nhm->nh_scope = RT_SCOPE_UNIVERSE;
ae298c93 288 nhm->nh_protocol = protocol;
c16c7808
SS
289
290 return 0;
291}
292
dd35a61c 293int sd_rtnl_message_new_neigh(
84e10015
ZJS
294 sd_netlink *rtnl,
295 sd_netlink_message **ret,
296 uint16_t nlmsg_type,
ae298c93
YW
297 int ifindex,
298 int family) {
84e10015 299
89489ef7
TG
300 struct ndmsg *ndm;
301 int r;
302
303 assert_return(rtnl_message_type_is_neigh(nlmsg_type), -EINVAL);
ae298c93 304 assert_return(IN_SET(family, AF_UNSPEC, AF_INET, AF_INET6, AF_BRIDGE), -EINVAL);
89489ef7
TG
305 assert_return(ret, -EINVAL);
306
6e196011 307 uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
74c1ab84 308 if (nlmsg_type == RTM_NEWNEIGH) {
ae298c93 309 if (family == AF_BRIDGE)
6e196011 310 flags |= NLM_F_CREATE | NLM_F_APPEND;
2bc1d783 311 else
6e196011 312 flags |= NLM_F_CREATE | NLM_F_REPLACE;
2bc1d783 313 }
89489ef7 314
6e196011
LP
315 r = message_new(rtnl, ret, nlmsg_type, flags);
316 if (r < 0)
317 return r;
318
2bc1d783 319 ndm = NLMSG_DATA((*ret)->hdr);
89489ef7 320
2bc1d783
YW
321 ndm->ndm_family = family;
322 ndm->ndm_ifindex = ifindex;
89489ef7
TG
323
324 return 0;
325}
326
2bc1d783
YW
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;
89489ef7 330
2bc1d783 331 assert_return(rtnl_message_type_is_link(nlmsg_type), -EINVAL);
ae298c93 332 assert_return(ret, -EINVAL);
89489ef7 333
6e196011 334 uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
7e322c3d 335 if (nlmsg_type == RTM_NEWLINK && ifindex == 0)
6e196011 336 flags |= NLM_F_CREATE | NLM_F_EXCL;
2bc1d783 337 else if (nlmsg_type == RTM_NEWLINKPROP)
6e196011
LP
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;
89489ef7 343
2bc1d783 344 ifi = NLMSG_DATA((*ret)->hdr);
89489ef7 345
2bc1d783
YW
346 ifi->ifi_family = AF_UNSPEC;
347 ifi->ifi_index = ifindex;
89489ef7
TG
348
349 return 0;
350}
351
dd35a61c 352int sd_rtnl_message_new_addr(
84e10015
ZJS
353 sd_netlink *rtnl,
354 sd_netlink_message **ret,
355 uint16_t nlmsg_type,
ae298c93 356 int ifindex,
84e10015
ZJS
357 int family) {
358
89489ef7
TG
359 struct ifaddrmsg *ifa;
360 int r;
361
362 assert_return(rtnl_message_type_is_addr(nlmsg_type), -EINVAL);
ae298c93
YW
363 assert_return((nlmsg_type == RTM_GETADDR && ifindex == 0) ||
364 ifindex > 0, -EINVAL);
89489ef7 365 assert_return((nlmsg_type == RTM_GETADDR && family == AF_UNSPEC) ||
945c2931 366 IN_SET(family, AF_INET, AF_INET6), -EINVAL);
89489ef7
TG
367 assert_return(ret, -EINVAL);
368
6e196011 369 r = message_new(rtnl, ret, nlmsg_type, NLM_F_REQUEST | NLM_F_ACK);
89489ef7
TG
370 if (r < 0)
371 return r;
372
89489ef7
TG
373 ifa = NLMSG_DATA((*ret)->hdr);
374
ae298c93 375 ifa->ifa_index = ifindex;
89489ef7 376 ifa->ifa_family = family;
89489ef7
TG
377
378 return 0;
379}
380
dd35a61c 381int sd_rtnl_message_new_addr_update(
84e10015
ZJS
382 sd_netlink *rtnl,
383 sd_netlink_message **ret,
ae298c93 384 int ifindex,
84e10015 385 int family) {
89489ef7
TG
386 int r;
387
ae298c93 388 r = sd_rtnl_message_new_addr(rtnl, ret, RTM_NEWADDR, ifindex, family);
89489ef7
TG
389 if (r < 0)
390 return r;
391
392 (*ret)->hdr->nlmsg_flags |= NLM_F_REPLACE;
393
394 return 0;
395}
396
ae298c93 397int sd_rtnl_message_get_family(sd_netlink_message *m, int *ret) {
89489ef7 398 assert_return(m, -EINVAL);
ae298c93 399 assert_return(ret, -EINVAL);
89489ef7
TG
400
401 assert(m->hdr);
402
ba8d48be
YW
403 if (rtnl_message_type_is_link(m->hdr->nlmsg_type))
404 return sd_rtnl_message_link_get_family(m, ret);
89489ef7 405
ba8d48be
YW
406 if (rtnl_message_type_is_route(m->hdr->nlmsg_type))
407 return sd_rtnl_message_route_get_family(m, ret);
89489ef7 408
ba8d48be
YW
409 if (rtnl_message_type_is_neigh(m->hdr->nlmsg_type))
410 return sd_rtnl_message_neigh_get_family(m, ret);
89489ef7 411
ba8d48be
YW
412 if (rtnl_message_type_is_addr(m->hdr->nlmsg_type))
413 return sd_rtnl_message_addr_get_family(m, ret);
89489ef7 414
ba8d48be
YW
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);
89489ef7 417
ba8d48be
YW
418 if (rtnl_message_type_is_nexthop(m->hdr->nlmsg_type))
419 return sd_rtnl_message_nexthop_get_family(m, ret);
89489ef7
TG
420
421 return -EOPNOTSUPP;
422}
30746d60 423
dd35a61c 424int sd_rtnl_message_new_addrlabel(
84e10015
ZJS
425 sd_netlink *rtnl,
426 sd_netlink_message **ret,
427 uint16_t nlmsg_type,
428 int ifindex,
ae298c93 429 int family) {
84e10015 430
30746d60
SS
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
6e196011
LP
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));
30746d60
SS
441 if (r < 0)
442 return r;
443
30746d60
SS
444 addrlabel = NLMSG_DATA((*ret)->hdr);
445
ae298c93 446 addrlabel->ifal_family = family;
30746d60
SS
447 addrlabel->ifal_index = ifindex;
448
449 return 0;
450}
451
dd35a61c 452int sd_rtnl_message_new_routing_policy_rule(
84e10015
ZJS
453 sd_netlink *rtnl,
454 sd_netlink_message **ret,
455 uint16_t nlmsg_type,
ae298c93 456 int family) {
84e10015 457
b43dfb6e 458 struct fib_rule_hdr *frh;
bce67bbe
SS
459 int r;
460
461 assert_return(rtnl_message_type_is_routing_policy_rule(nlmsg_type), -EINVAL);
462 assert_return(ret, -EINVAL);
463
6e196011
LP
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));
bce67bbe
SS
468 if (r < 0)
469 return r;
470
b43dfb6e 471 frh = NLMSG_DATA((*ret)->hdr);
ae298c93 472 frh->family = family;
bce67bbe
SS
473
474 return 0;
475}
476
dd35a61c 477int sd_rtnl_message_new_traffic_control(
f50b93fe
YW
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) {
0f5bd7fe 484
0ebb76de
YW
485 struct tcmsg *tcm;
486 int r;
487
f50b93fe 488 assert_return(rtnl_message_type_is_traffic_control(nlmsg_type), -EINVAL);
0ebb76de
YW
489 assert_return(ret, -EINVAL);
490
6e196011
LP
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));
0ebb76de
YW
495 if (r < 0)
496 return r;
497
0ebb76de 498 tcm = NLMSG_DATA((*ret)->hdr);
f50b93fe 499 tcm->tcm_ifindex = ifindex;
0ebb76de 500 tcm->tcm_handle = handle;
f50b93fe 501 tcm->tcm_parent = parent;
0ebb76de
YW
502
503 return 0;
504}
1903c9bb 505
dd35a61c 506int sd_rtnl_message_new_mdb(
84e10015
ZJS
507 sd_netlink *rtnl,
508 sd_netlink_message **ret,
509 uint16_t nlmsg_type,
ae298c93 510 int ifindex) {
84e10015 511
1903c9bb
DM
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
6e196011
LP
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));
1903c9bb
DM
522 if (r < 0)
523 return r;
524
1903c9bb
DM
525 bpm = NLMSG_DATA((*ret)->hdr);
526 bpm->family = AF_BRIDGE;
ae298c93 527 bpm->ifindex = ifindex;
1903c9bb
DM
528
529 return 0;
530}
10786280
LP
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
6e196011 543 r = message_new(rtnl, ret, nlmsg_type, NLM_F_REQUEST | NLM_F_ACK);
10786280
LP
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}