]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd/sd-netlink/rtnl-message.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2013 Tom Gundersen <teg@jklm.no>
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include <netinet/in.h>
26 #include "sd-netlink.h"
28 #include "formats-util.h"
30 #include "netlink-internal.h"
31 #include "netlink-types.h"
32 #include "netlink-util.h"
34 #include "socket-util.h"
37 int sd_rtnl_message_route_set_dst_prefixlen(sd_netlink_message
*m
, unsigned char prefixlen
) {
40 assert_return(m
, -EINVAL
);
41 assert_return(m
->hdr
, -EINVAL
);
42 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
44 rtm
= NLMSG_DATA(m
->hdr
);
46 if ((rtm
->rtm_family
== AF_INET
&& prefixlen
> 32) ||
47 (rtm
->rtm_family
== AF_INET6
&& prefixlen
> 128))
50 rtm
->rtm_dst_len
= prefixlen
;
55 int sd_rtnl_message_route_set_src_prefixlen(sd_netlink_message
*m
, unsigned char prefixlen
) {
58 assert_return(m
, -EINVAL
);
59 assert_return(m
->hdr
, -EINVAL
);
60 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
62 rtm
= NLMSG_DATA(m
->hdr
);
64 if ((rtm
->rtm_family
== AF_INET
&& prefixlen
> 32) ||
65 (rtm
->rtm_family
== AF_INET6
&& prefixlen
> 128))
68 rtm
->rtm_src_len
= prefixlen
;
73 int sd_rtnl_message_route_set_scope(sd_netlink_message
*m
, unsigned char scope
) {
76 assert_return(m
, -EINVAL
);
77 assert_return(m
->hdr
, -EINVAL
);
78 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
80 rtm
= NLMSG_DATA(m
->hdr
);
82 rtm
->rtm_scope
= scope
;
87 int sd_rtnl_message_route_set_flags(sd_netlink_message
*m
, unsigned flags
) {
90 assert_return(m
, -EINVAL
);
91 assert_return(m
->hdr
, -EINVAL
);
92 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
94 rtm
= NLMSG_DATA(m
->hdr
);
96 rtm
->rtm_flags
= flags
;
101 int sd_rtnl_message_route_get_flags(sd_netlink_message
*m
, unsigned *flags
) {
104 assert_return(m
, -EINVAL
);
105 assert_return(m
->hdr
, -EINVAL
);
106 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
107 assert_return(flags
, -EINVAL
);
109 rtm
= NLMSG_DATA(m
->hdr
);
111 *flags
= rtm
->rtm_flags
;
116 int sd_rtnl_message_route_get_family(sd_netlink_message
*m
, int *family
) {
119 assert_return(m
, -EINVAL
);
120 assert_return(m
->hdr
, -EINVAL
);
121 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
122 assert_return(family
, -EINVAL
);
124 rtm
= NLMSG_DATA(m
->hdr
);
126 *family
= rtm
->rtm_family
;
131 int sd_rtnl_message_route_get_protocol(sd_netlink_message
*m
, unsigned char *protocol
) {
134 assert_return(m
, -EINVAL
);
135 assert_return(m
->hdr
, -EINVAL
);
136 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
137 assert_return(protocol
, -EINVAL
);
139 rtm
= NLMSG_DATA(m
->hdr
);
141 *protocol
= rtm
->rtm_protocol
;
146 int sd_rtnl_message_route_get_scope(sd_netlink_message
*m
, unsigned char *scope
) {
149 assert_return(m
, -EINVAL
);
150 assert_return(m
->hdr
, -EINVAL
);
151 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
152 assert_return(scope
, -EINVAL
);
154 rtm
= NLMSG_DATA(m
->hdr
);
156 *scope
= rtm
->rtm_scope
;
161 int sd_rtnl_message_route_get_tos(sd_netlink_message
*m
, unsigned char *tos
) {
164 assert_return(m
, -EINVAL
);
165 assert_return(m
->hdr
, -EINVAL
);
166 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
167 assert_return(tos
, -EINVAL
);
169 rtm
= NLMSG_DATA(m
->hdr
);
176 int sd_rtnl_message_route_get_table(sd_netlink_message
*m
, unsigned char *table
) {
179 assert_return(m
, -EINVAL
);
180 assert_return(m
->hdr
, -EINVAL
);
181 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
182 assert_return(table
, -EINVAL
);
184 rtm
= NLMSG_DATA(m
->hdr
);
186 *table
= rtm
->rtm_table
;
191 int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message
*m
, unsigned char *dst_len
) {
194 assert_return(m
, -EINVAL
);
195 assert_return(m
->hdr
, -EINVAL
);
196 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
197 assert_return(dst_len
, -EINVAL
);
199 rtm
= NLMSG_DATA(m
->hdr
);
201 *dst_len
= rtm
->rtm_dst_len
;
206 int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message
*m
, unsigned char *src_len
) {
209 assert_return(m
, -EINVAL
);
210 assert_return(m
->hdr
, -EINVAL
);
211 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
212 assert_return(src_len
, -EINVAL
);
214 rtm
= NLMSG_DATA(m
->hdr
);
216 *src_len
= rtm
->rtm_src_len
;
221 int sd_rtnl_message_new_route(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
222 uint16_t nlmsg_type
, int rtm_family
,
223 unsigned char rtm_protocol
) {
227 assert_return(rtnl_message_type_is_route(nlmsg_type
), -EINVAL
);
228 assert_return((nlmsg_type
== RTM_GETROUTE
&& rtm_family
== AF_UNSPEC
) ||
229 rtm_family
== AF_INET
|| rtm_family
== AF_INET6
, -EINVAL
);
230 assert_return(ret
, -EINVAL
);
232 r
= message_new(rtnl
, ret
, nlmsg_type
);
236 if (nlmsg_type
== RTM_NEWROUTE
)
237 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_CREATE
| NLM_F_APPEND
;
239 rtm
= NLMSG_DATA((*ret
)->hdr
);
241 rtm
->rtm_family
= rtm_family
;
242 rtm
->rtm_scope
= RT_SCOPE_UNIVERSE
;
243 rtm
->rtm_type
= RTN_UNICAST
;
244 rtm
->rtm_table
= RT_TABLE_MAIN
;
245 rtm
->rtm_protocol
= rtm_protocol
;
250 int sd_rtnl_message_neigh_set_flags(sd_netlink_message
*m
, uint8_t flags
) {
253 assert_return(m
, -EINVAL
);
254 assert_return(m
->hdr
, -EINVAL
);
255 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
257 ndm
= NLMSG_DATA(m
->hdr
);
258 ndm
->ndm_flags
|= flags
;
263 int sd_rtnl_message_neigh_set_state(sd_netlink_message
*m
, uint16_t state
) {
266 assert_return(m
, -EINVAL
);
267 assert_return(m
->hdr
, -EINVAL
);
268 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
270 ndm
= NLMSG_DATA(m
->hdr
);
271 ndm
->ndm_state
|= state
;
276 int sd_rtnl_message_neigh_get_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 *flags
= ndm
->ndm_flags
;
289 int sd_rtnl_message_neigh_get_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 *state
= ndm
->ndm_state
;
302 int sd_rtnl_message_neigh_get_family(sd_netlink_message
*m
, int *family
) {
305 assert_return(m
, -EINVAL
);
306 assert_return(m
->hdr
, -EINVAL
);
307 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
308 assert_return(family
, -EINVAL
);
310 ndm
= NLMSG_DATA(m
->hdr
);
312 *family
= ndm
->ndm_family
;
317 int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message
*m
, int *index
) {
320 assert_return(m
, -EINVAL
);
321 assert_return(m
->hdr
, -EINVAL
);
322 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
323 assert_return(index
, -EINVAL
);
325 ndm
= NLMSG_DATA(m
->hdr
);
327 *index
= ndm
->ndm_ifindex
;
332 int sd_rtnl_message_new_neigh(sd_netlink
*rtnl
, sd_netlink_message
**ret
, uint16_t nlmsg_type
, int index
, int ndm_family
) {
336 assert_return(rtnl_message_type_is_neigh(nlmsg_type
), -EINVAL
);
337 assert_return(ndm_family
== AF_INET
||
338 ndm_family
== AF_INET6
||
339 ndm_family
== PF_BRIDGE
, -EINVAL
);
340 assert_return(ret
, -EINVAL
);
342 r
= message_new(rtnl
, ret
, nlmsg_type
);
346 if (nlmsg_type
== RTM_NEWNEIGH
)
347 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_CREATE
| NLM_F_APPEND
;
349 ndm
= NLMSG_DATA((*ret
)->hdr
);
351 ndm
->ndm_family
= ndm_family
;
352 ndm
->ndm_ifindex
= index
;
357 int sd_rtnl_message_link_set_flags(sd_netlink_message
*m
, unsigned flags
, unsigned change
) {
358 struct ifinfomsg
*ifi
;
360 assert_return(m
, -EINVAL
);
361 assert_return(m
->hdr
, -EINVAL
);
362 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
363 assert_return(change
, -EINVAL
);
365 ifi
= NLMSG_DATA(m
->hdr
);
367 ifi
->ifi_flags
= flags
;
368 ifi
->ifi_change
= change
;
373 int sd_rtnl_message_link_set_type(sd_netlink_message
*m
, unsigned type
) {
374 struct ifinfomsg
*ifi
;
376 assert_return(m
, -EINVAL
);
377 assert_return(m
->hdr
, -EINVAL
);
378 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
380 ifi
= NLMSG_DATA(m
->hdr
);
382 ifi
->ifi_type
= type
;
387 int sd_rtnl_message_link_set_family(sd_netlink_message
*m
, unsigned family
) {
388 struct ifinfomsg
*ifi
;
390 assert_return(m
, -EINVAL
);
391 assert_return(m
->hdr
, -EINVAL
);
392 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
394 ifi
= NLMSG_DATA(m
->hdr
);
396 ifi
->ifi_family
= family
;
401 int sd_rtnl_message_new_link(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
402 uint16_t nlmsg_type
, int index
) {
403 struct ifinfomsg
*ifi
;
406 assert_return(rtnl_message_type_is_link(nlmsg_type
), -EINVAL
);
407 assert_return(nlmsg_type
!= RTM_DELLINK
|| index
> 0, -EINVAL
);
408 assert_return(ret
, -EINVAL
);
410 r
= message_new(rtnl
, ret
, nlmsg_type
);
414 if (nlmsg_type
== RTM_NEWLINK
)
415 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_CREATE
| NLM_F_EXCL
;
417 ifi
= NLMSG_DATA((*ret
)->hdr
);
419 ifi
->ifi_family
= AF_UNSPEC
;
420 ifi
->ifi_index
= index
;
425 int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message
*m
, unsigned char prefixlen
) {
426 struct ifaddrmsg
*ifa
;
428 assert_return(m
, -EINVAL
);
429 assert_return(m
->hdr
, -EINVAL
);
430 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
432 ifa
= NLMSG_DATA(m
->hdr
);
434 if ((ifa
->ifa_family
== AF_INET
&& prefixlen
> 32) ||
435 (ifa
->ifa_family
== AF_INET6
&& prefixlen
> 128))
438 ifa
->ifa_prefixlen
= prefixlen
;
443 int sd_rtnl_message_addr_set_flags(sd_netlink_message
*m
, unsigned char flags
) {
444 struct ifaddrmsg
*ifa
;
446 assert_return(m
, -EINVAL
);
447 assert_return(m
->hdr
, -EINVAL
);
448 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
450 ifa
= NLMSG_DATA(m
->hdr
);
452 ifa
->ifa_flags
= flags
;
457 int sd_rtnl_message_addr_set_scope(sd_netlink_message
*m
, unsigned char scope
) {
458 struct ifaddrmsg
*ifa
;
460 assert_return(m
, -EINVAL
);
461 assert_return(m
->hdr
, -EINVAL
);
462 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
464 ifa
= NLMSG_DATA(m
->hdr
);
466 ifa
->ifa_scope
= scope
;
471 int sd_rtnl_message_addr_get_family(sd_netlink_message
*m
, int *family
) {
472 struct ifaddrmsg
*ifa
;
474 assert_return(m
, -EINVAL
);
475 assert_return(m
->hdr
, -EINVAL
);
476 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
477 assert_return(family
, -EINVAL
);
479 ifa
= NLMSG_DATA(m
->hdr
);
481 *family
= ifa
->ifa_family
;
486 int sd_rtnl_message_addr_get_prefixlen(sd_netlink_message
*m
, unsigned char *prefixlen
) {
487 struct ifaddrmsg
*ifa
;
489 assert_return(m
, -EINVAL
);
490 assert_return(m
->hdr
, -EINVAL
);
491 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
492 assert_return(prefixlen
, -EINVAL
);
494 ifa
= NLMSG_DATA(m
->hdr
);
496 *prefixlen
= ifa
->ifa_prefixlen
;
501 int sd_rtnl_message_addr_get_scope(sd_netlink_message
*m
, unsigned char *scope
) {
502 struct ifaddrmsg
*ifa
;
504 assert_return(m
, -EINVAL
);
505 assert_return(m
->hdr
, -EINVAL
);
506 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
507 assert_return(scope
, -EINVAL
);
509 ifa
= NLMSG_DATA(m
->hdr
);
511 *scope
= ifa
->ifa_scope
;
516 int sd_rtnl_message_addr_get_flags(sd_netlink_message
*m
, unsigned char *flags
) {
517 struct ifaddrmsg
*ifa
;
519 assert_return(m
, -EINVAL
);
520 assert_return(m
->hdr
, -EINVAL
);
521 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
522 assert_return(flags
, -EINVAL
);
524 ifa
= NLMSG_DATA(m
->hdr
);
526 *flags
= ifa
->ifa_flags
;
531 int sd_rtnl_message_addr_get_ifindex(sd_netlink_message
*m
, int *ifindex
) {
532 struct ifaddrmsg
*ifa
;
534 assert_return(m
, -EINVAL
);
535 assert_return(m
->hdr
, -EINVAL
);
536 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
537 assert_return(ifindex
, -EINVAL
);
539 ifa
= NLMSG_DATA(m
->hdr
);
541 *ifindex
= ifa
->ifa_index
;
546 int sd_rtnl_message_new_addr(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
547 uint16_t nlmsg_type
, int index
,
549 struct ifaddrmsg
*ifa
;
552 assert_return(rtnl_message_type_is_addr(nlmsg_type
), -EINVAL
);
553 assert_return((nlmsg_type
== RTM_GETADDR
&& index
== 0) ||
555 assert_return((nlmsg_type
== RTM_GETADDR
&& family
== AF_UNSPEC
) ||
556 family
== AF_INET
|| family
== AF_INET6
, -EINVAL
);
557 assert_return(ret
, -EINVAL
);
559 r
= message_new(rtnl
, ret
, nlmsg_type
);
563 if (nlmsg_type
== RTM_GETADDR
)
564 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_DUMP
;
566 ifa
= NLMSG_DATA((*ret
)->hdr
);
568 ifa
->ifa_index
= index
;
569 ifa
->ifa_family
= family
;
570 if (family
== AF_INET
)
571 ifa
->ifa_prefixlen
= 32;
572 else if (family
== AF_INET6
)
573 ifa
->ifa_prefixlen
= 128;
578 int sd_rtnl_message_new_addr_update(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
579 int index
, int family
) {
582 r
= sd_rtnl_message_new_addr(rtnl
, ret
, RTM_NEWADDR
, index
, family
);
586 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_REPLACE
;
591 int sd_rtnl_message_link_get_ifindex(sd_netlink_message
*m
, int *ifindex
) {
592 struct ifinfomsg
*ifi
;
594 assert_return(m
, -EINVAL
);
595 assert_return(m
->hdr
, -EINVAL
);
596 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
597 assert_return(ifindex
, -EINVAL
);
599 ifi
= NLMSG_DATA(m
->hdr
);
601 *ifindex
= ifi
->ifi_index
;
606 int sd_rtnl_message_link_get_flags(sd_netlink_message
*m
, unsigned *flags
) {
607 struct ifinfomsg
*ifi
;
609 assert_return(m
, -EINVAL
);
610 assert_return(m
->hdr
, -EINVAL
);
611 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
612 assert_return(flags
, -EINVAL
);
614 ifi
= NLMSG_DATA(m
->hdr
);
616 *flags
= ifi
->ifi_flags
;
621 int sd_rtnl_message_link_get_type(sd_netlink_message
*m
, unsigned *type
) {
622 struct ifinfomsg
*ifi
;
624 assert_return(m
, -EINVAL
);
625 assert_return(m
->hdr
, -EINVAL
);
626 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
627 assert_return(type
, -EINVAL
);
629 ifi
= NLMSG_DATA(m
->hdr
);
631 *type
= ifi
->ifi_type
;
636 int sd_rtnl_message_get_family(sd_netlink_message
*m
, int *family
) {
637 assert_return(m
, -EINVAL
);
638 assert_return(family
, -EINVAL
);
642 if (rtnl_message_type_is_link(m
->hdr
->nlmsg_type
)) {
643 struct ifinfomsg
*ifi
;
645 ifi
= NLMSG_DATA(m
->hdr
);
647 *family
= ifi
->ifi_family
;
650 } else if (rtnl_message_type_is_route(m
->hdr
->nlmsg_type
)) {
653 rtm
= NLMSG_DATA(m
->hdr
);
655 *family
= rtm
->rtm_family
;
658 } else if (rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
)) {
661 ndm
= NLMSG_DATA(m
->hdr
);
663 *family
= ndm
->ndm_family
;
666 } else if (rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
)) {
667 struct ifaddrmsg
*ifa
;
669 ifa
= NLMSG_DATA(m
->hdr
);
671 *family
= ifa
->ifa_family
;