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