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