]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-netlink/rtnl-message.c
2 This file is part of systemd.
4 Copyright 2013 Tom Gundersen <teg@jklm.no>
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include <netinet/in.h>
24 #include "sd-netlink.h"
26 #include "formats-util.h"
28 #include "netlink-internal.h"
29 #include "netlink-types.h"
30 #include "netlink-util.h"
32 #include "socket-util.h"
35 int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message
*m
, unsigned char prefixlen
) {
38 assert_return(m
, -EINVAL
);
39 assert_return(m
->hdr
, -EINVAL
);
40 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
42 rtm
= NLMSG_DATA(m
->hdr
);
44 if ((rtm
->rtm_family
== AF_INET
&& prefixlen
> 32) ||
45 (rtm
->rtm_family
== AF_INET6
&& prefixlen
> 128))
48 rtm
->rtm_dst_len
= prefixlen
;
53 int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message
*m
, unsigned char prefixlen
) {
56 assert_return(m
, -EINVAL
);
57 assert_return(m
->hdr
, -EINVAL
);
58 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
60 rtm
= NLMSG_DATA(m
->hdr
);
62 if ((rtm
->rtm_family
== AF_INET
&& prefixlen
> 32) ||
63 (rtm
->rtm_family
== AF_INET6
&& prefixlen
> 128))
66 rtm
->rtm_src_len
= prefixlen
;
71 int sd_rtnl_message_route_set_scope(sd_netlink_message
*m
, unsigned char scope
) {
74 assert_return(m
, -EINVAL
);
75 assert_return(m
->hdr
, -EINVAL
);
76 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
78 rtm
= NLMSG_DATA(m
->hdr
);
80 rtm
->rtm_scope
= scope
;
85 int sd_rtnl_message_route_set_flags(sd_netlink_message
*m
, unsigned flags
) {
88 assert_return(m
, -EINVAL
);
89 assert_return(m
->hdr
, -EINVAL
);
90 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
92 rtm
= NLMSG_DATA(m
->hdr
);
94 rtm
->rtm_flags
= flags
;
99 int sd_rtnl_message_route_get_flags(sd_netlink_message
*m
, unsigned *flags
) {
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 assert_return(flags
, -EINVAL
);
107 rtm
= NLMSG_DATA(m
->hdr
);
109 *flags
= rtm
->rtm_flags
;
114 int sd_rtnl_message_route_set_table(sd_netlink_message
*m
, unsigned char table
) {
117 assert_return(m
, -EINVAL
);
118 assert_return(m
->hdr
, -EINVAL
);
119 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
121 rtm
= NLMSG_DATA(m
->hdr
);
123 rtm
->rtm_table
= table
;
128 int sd_rtnl_message_route_get_family(sd_netlink_message
*m
, int *family
) {
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(family
, -EINVAL
);
136 rtm
= NLMSG_DATA(m
->hdr
);
138 *family
= rtm
->rtm_family
;
143 int sd_rtnl_message_route_set_family(sd_netlink_message
*m
, int family
) {
146 assert_return(m
, -EINVAL
);
147 assert_return(m
->hdr
, -EINVAL
);
148 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
150 rtm
= NLMSG_DATA(m
->hdr
);
152 rtm
->rtm_family
= family
;
157 int sd_rtnl_message_route_get_protocol(sd_netlink_message
*m
, unsigned char *protocol
) {
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
);
165 rtm
= NLMSG_DATA(m
->hdr
);
167 *protocol
= rtm
->rtm_protocol
;
172 int sd_rtnl_message_route_get_scope(sd_netlink_message
*m
, unsigned char *scope
) {
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
);
180 rtm
= NLMSG_DATA(m
->hdr
);
182 *scope
= rtm
->rtm_scope
;
187 int sd_rtnl_message_route_get_tos(sd_netlink_message
*m
, unsigned char *tos
) {
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
);
195 rtm
= NLMSG_DATA(m
->hdr
);
202 int sd_rtnl_message_route_get_table(sd_netlink_message
*m
, unsigned char *table
) {
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
);
210 rtm
= NLMSG_DATA(m
->hdr
);
212 *table
= rtm
->rtm_table
;
217 int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message
*m
, unsigned char *dst_len
) {
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
);
225 rtm
= NLMSG_DATA(m
->hdr
);
227 *dst_len
= rtm
->rtm_dst_len
;
232 int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message
*m
, unsigned char *src_len
) {
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
);
240 rtm
= NLMSG_DATA(m
->hdr
);
242 *src_len
= rtm
->rtm_src_len
;
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
) {
253 assert_return(rtnl_message_type_is_route(nlmsg_type
), -EINVAL
);
254 assert_return((nlmsg_type
== RTM_GETROUTE
&& rtm_family
== AF_UNSPEC
) ||
255 rtm_family
== AF_INET
|| rtm_family
== AF_INET6
, -EINVAL
);
256 assert_return(ret
, -EINVAL
);
258 r
= message_new(rtnl
, ret
, nlmsg_type
);
262 if (nlmsg_type
== RTM_NEWROUTE
)
263 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_CREATE
| NLM_F_APPEND
;
265 rtm
= NLMSG_DATA((*ret
)->hdr
);
267 rtm
->rtm_family
= rtm_family
;
268 rtm
->rtm_scope
= RT_SCOPE_UNIVERSE
;
269 rtm
->rtm_type
= RTN_UNICAST
;
270 rtm
->rtm_table
= RT_TABLE_MAIN
;
271 rtm
->rtm_protocol
= rtm_protocol
;
276 int sd_rtnl_message_neigh_set_flags(sd_netlink_message
*m
, uint8_t flags
) {
279 assert_return(m
, -EINVAL
);
280 assert_return(m
->hdr
, -EINVAL
);
281 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
283 ndm
= NLMSG_DATA(m
->hdr
);
284 ndm
->ndm_flags
|= flags
;
289 int sd_rtnl_message_neigh_set_state(sd_netlink_message
*m
, uint16_t state
) {
292 assert_return(m
, -EINVAL
);
293 assert_return(m
->hdr
, -EINVAL
);
294 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
296 ndm
= NLMSG_DATA(m
->hdr
);
297 ndm
->ndm_state
|= state
;
302 int sd_rtnl_message_neigh_get_flags(sd_netlink_message
*m
, uint8_t *flags
) {
305 assert_return(m
, -EINVAL
);
306 assert_return(m
->hdr
, -EINVAL
);
307 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
309 ndm
= NLMSG_DATA(m
->hdr
);
310 *flags
= ndm
->ndm_flags
;
315 int sd_rtnl_message_neigh_get_state(sd_netlink_message
*m
, uint16_t *state
) {
318 assert_return(m
, -EINVAL
);
319 assert_return(m
->hdr
, -EINVAL
);
320 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
322 ndm
= NLMSG_DATA(m
->hdr
);
323 *state
= ndm
->ndm_state
;
328 int sd_rtnl_message_neigh_get_family(sd_netlink_message
*m
, int *family
) {
331 assert_return(m
, -EINVAL
);
332 assert_return(m
->hdr
, -EINVAL
);
333 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
334 assert_return(family
, -EINVAL
);
336 ndm
= NLMSG_DATA(m
->hdr
);
338 *family
= ndm
->ndm_family
;
343 int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message
*m
, int *index
) {
346 assert_return(m
, -EINVAL
);
347 assert_return(m
->hdr
, -EINVAL
);
348 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
349 assert_return(index
, -EINVAL
);
351 ndm
= NLMSG_DATA(m
->hdr
);
353 *index
= ndm
->ndm_ifindex
;
358 int sd_rtnl_message_new_neigh(sd_netlink
*rtnl
, sd_netlink_message
**ret
, uint16_t nlmsg_type
, int index
, int ndm_family
) {
362 assert_return(rtnl_message_type_is_neigh(nlmsg_type
), -EINVAL
);
363 assert_return(ndm_family
== AF_INET
||
364 ndm_family
== AF_INET6
||
365 ndm_family
== PF_BRIDGE
, -EINVAL
);
366 assert_return(ret
, -EINVAL
);
368 r
= message_new(rtnl
, ret
, nlmsg_type
);
372 if (nlmsg_type
== RTM_NEWNEIGH
)
373 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_CREATE
| NLM_F_APPEND
;
375 ndm
= NLMSG_DATA((*ret
)->hdr
);
377 ndm
->ndm_family
= ndm_family
;
378 ndm
->ndm_ifindex
= index
;
383 int sd_rtnl_message_link_set_flags(sd_netlink_message
*m
, unsigned flags
, unsigned change
) {
384 struct ifinfomsg
*ifi
;
386 assert_return(m
, -EINVAL
);
387 assert_return(m
->hdr
, -EINVAL
);
388 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
389 assert_return(change
, -EINVAL
);
391 ifi
= NLMSG_DATA(m
->hdr
);
393 ifi
->ifi_flags
= flags
;
394 ifi
->ifi_change
= change
;
399 int sd_rtnl_message_link_set_type(sd_netlink_message
*m
, unsigned type
) {
400 struct ifinfomsg
*ifi
;
402 assert_return(m
, -EINVAL
);
403 assert_return(m
->hdr
, -EINVAL
);
404 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
406 ifi
= NLMSG_DATA(m
->hdr
);
408 ifi
->ifi_type
= type
;
413 int sd_rtnl_message_link_set_family(sd_netlink_message
*m
, unsigned family
) {
414 struct ifinfomsg
*ifi
;
416 assert_return(m
, -EINVAL
);
417 assert_return(m
->hdr
, -EINVAL
);
418 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
420 ifi
= NLMSG_DATA(m
->hdr
);
422 ifi
->ifi_family
= family
;
427 int sd_rtnl_message_new_link(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
428 uint16_t nlmsg_type
, int index
) {
429 struct ifinfomsg
*ifi
;
432 assert_return(rtnl_message_type_is_link(nlmsg_type
), -EINVAL
);
433 assert_return(ret
, -EINVAL
);
435 r
= message_new(rtnl
, ret
, nlmsg_type
);
439 if (nlmsg_type
== RTM_NEWLINK
)
440 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_CREATE
| NLM_F_EXCL
;
442 ifi
= NLMSG_DATA((*ret
)->hdr
);
444 ifi
->ifi_family
= AF_UNSPEC
;
445 ifi
->ifi_index
= index
;
450 int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message
*m
, unsigned char prefixlen
) {
451 struct ifaddrmsg
*ifa
;
453 assert_return(m
, -EINVAL
);
454 assert_return(m
->hdr
, -EINVAL
);
455 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
457 ifa
= NLMSG_DATA(m
->hdr
);
459 if ((ifa
->ifa_family
== AF_INET
&& prefixlen
> 32) ||
460 (ifa
->ifa_family
== AF_INET6
&& prefixlen
> 128))
463 ifa
->ifa_prefixlen
= prefixlen
;
468 int sd_rtnl_message_addr_set_flags(sd_netlink_message
*m
, unsigned char flags
) {
469 struct ifaddrmsg
*ifa
;
471 assert_return(m
, -EINVAL
);
472 assert_return(m
->hdr
, -EINVAL
);
473 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
475 ifa
= NLMSG_DATA(m
->hdr
);
477 ifa
->ifa_flags
= flags
;
482 int sd_rtnl_message_addr_set_scope(sd_netlink_message
*m
, unsigned char scope
) {
483 struct ifaddrmsg
*ifa
;
485 assert_return(m
, -EINVAL
);
486 assert_return(m
->hdr
, -EINVAL
);
487 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
489 ifa
= NLMSG_DATA(m
->hdr
);
491 ifa
->ifa_scope
= scope
;
496 int sd_rtnl_message_addr_get_family(sd_netlink_message
*m
, int *family
) {
497 struct ifaddrmsg
*ifa
;
499 assert_return(m
, -EINVAL
);
500 assert_return(m
->hdr
, -EINVAL
);
501 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
502 assert_return(family
, -EINVAL
);
504 ifa
= NLMSG_DATA(m
->hdr
);
506 *family
= ifa
->ifa_family
;
511 int sd_rtnl_message_addr_get_prefixlen(sd_netlink_message
*m
, unsigned char *prefixlen
) {
512 struct ifaddrmsg
*ifa
;
514 assert_return(m
, -EINVAL
);
515 assert_return(m
->hdr
, -EINVAL
);
516 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
517 assert_return(prefixlen
, -EINVAL
);
519 ifa
= NLMSG_DATA(m
->hdr
);
521 *prefixlen
= ifa
->ifa_prefixlen
;
526 int sd_rtnl_message_addr_get_scope(sd_netlink_message
*m
, unsigned char *scope
) {
527 struct ifaddrmsg
*ifa
;
529 assert_return(m
, -EINVAL
);
530 assert_return(m
->hdr
, -EINVAL
);
531 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
532 assert_return(scope
, -EINVAL
);
534 ifa
= NLMSG_DATA(m
->hdr
);
536 *scope
= ifa
->ifa_scope
;
541 int sd_rtnl_message_addr_get_flags(sd_netlink_message
*m
, unsigned char *flags
) {
542 struct ifaddrmsg
*ifa
;
544 assert_return(m
, -EINVAL
);
545 assert_return(m
->hdr
, -EINVAL
);
546 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
547 assert_return(flags
, -EINVAL
);
549 ifa
= NLMSG_DATA(m
->hdr
);
551 *flags
= ifa
->ifa_flags
;
556 int sd_rtnl_message_addr_get_ifindex(sd_netlink_message
*m
, int *ifindex
) {
557 struct ifaddrmsg
*ifa
;
559 assert_return(m
, -EINVAL
);
560 assert_return(m
->hdr
, -EINVAL
);
561 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
562 assert_return(ifindex
, -EINVAL
);
564 ifa
= NLMSG_DATA(m
->hdr
);
566 *ifindex
= ifa
->ifa_index
;
571 int sd_rtnl_message_new_addr(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
572 uint16_t nlmsg_type
, int index
,
574 struct ifaddrmsg
*ifa
;
577 assert_return(rtnl_message_type_is_addr(nlmsg_type
), -EINVAL
);
578 assert_return((nlmsg_type
== RTM_GETADDR
&& index
== 0) ||
580 assert_return((nlmsg_type
== RTM_GETADDR
&& family
== AF_UNSPEC
) ||
581 family
== AF_INET
|| family
== AF_INET6
, -EINVAL
);
582 assert_return(ret
, -EINVAL
);
584 r
= message_new(rtnl
, ret
, nlmsg_type
);
588 if (nlmsg_type
== RTM_GETADDR
)
589 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_DUMP
;
591 ifa
= NLMSG_DATA((*ret
)->hdr
);
593 ifa
->ifa_index
= index
;
594 ifa
->ifa_family
= family
;
595 if (family
== AF_INET
)
596 ifa
->ifa_prefixlen
= 32;
597 else if (family
== AF_INET6
)
598 ifa
->ifa_prefixlen
= 128;
603 int sd_rtnl_message_new_addr_update(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
604 int index
, int family
) {
607 r
= sd_rtnl_message_new_addr(rtnl
, ret
, RTM_NEWADDR
, index
, family
);
611 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_REPLACE
;
616 int sd_rtnl_message_link_get_ifindex(sd_netlink_message
*m
, int *ifindex
) {
617 struct ifinfomsg
*ifi
;
619 assert_return(m
, -EINVAL
);
620 assert_return(m
->hdr
, -EINVAL
);
621 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
622 assert_return(ifindex
, -EINVAL
);
624 ifi
= NLMSG_DATA(m
->hdr
);
626 *ifindex
= ifi
->ifi_index
;
631 int sd_rtnl_message_link_get_flags(sd_netlink_message
*m
, unsigned *flags
) {
632 struct ifinfomsg
*ifi
;
634 assert_return(m
, -EINVAL
);
635 assert_return(m
->hdr
, -EINVAL
);
636 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
637 assert_return(flags
, -EINVAL
);
639 ifi
= NLMSG_DATA(m
->hdr
);
641 *flags
= ifi
->ifi_flags
;
646 int sd_rtnl_message_link_get_type(sd_netlink_message
*m
, unsigned short *type
) {
647 struct ifinfomsg
*ifi
;
649 assert_return(m
, -EINVAL
);
650 assert_return(m
->hdr
, -EINVAL
);
651 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
652 assert_return(type
, -EINVAL
);
654 ifi
= NLMSG_DATA(m
->hdr
);
656 *type
= ifi
->ifi_type
;
661 int sd_rtnl_message_get_family(sd_netlink_message
*m
, int *family
) {
662 assert_return(m
, -EINVAL
);
663 assert_return(family
, -EINVAL
);
667 if (rtnl_message_type_is_link(m
->hdr
->nlmsg_type
)) {
668 struct ifinfomsg
*ifi
;
670 ifi
= NLMSG_DATA(m
->hdr
);
672 *family
= ifi
->ifi_family
;
675 } else if (rtnl_message_type_is_route(m
->hdr
->nlmsg_type
)) {
678 rtm
= NLMSG_DATA(m
->hdr
);
680 *family
= rtm
->rtm_family
;
683 } else if (rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
)) {
686 ndm
= NLMSG_DATA(m
->hdr
);
688 *family
= ndm
->ndm_family
;
691 } else if (rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
)) {
692 struct ifaddrmsg
*ifa
;
694 ifa
= NLMSG_DATA(m
->hdr
);
696 *family
= ifa
->ifa_family
;