]>
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_get_family(sd_netlink_message
*m
, int *family
) {
90 assert_return(m
, -EINVAL
);
91 assert_return(m
->hdr
, -EINVAL
);
92 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
93 assert_return(family
, -EINVAL
);
95 rtm
= NLMSG_DATA(m
->hdr
);
97 *family
= rtm
->rtm_family
;
102 int sd_rtnl_message_route_get_protocol(sd_netlink_message
*m
, unsigned char *protocol
) {
105 assert_return(m
, -EINVAL
);
106 assert_return(m
->hdr
, -EINVAL
);
107 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
108 assert_return(protocol
, -EINVAL
);
110 rtm
= NLMSG_DATA(m
->hdr
);
112 *protocol
= rtm
->rtm_protocol
;
117 int sd_rtnl_message_route_get_scope(sd_netlink_message
*m
, unsigned char *scope
) {
120 assert_return(m
, -EINVAL
);
121 assert_return(m
->hdr
, -EINVAL
);
122 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
123 assert_return(scope
, -EINVAL
);
125 rtm
= NLMSG_DATA(m
->hdr
);
127 *scope
= rtm
->rtm_scope
;
132 int sd_rtnl_message_route_get_tos(sd_netlink_message
*m
, unsigned char *tos
) {
135 assert_return(m
, -EINVAL
);
136 assert_return(m
->hdr
, -EINVAL
);
137 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
138 assert_return(tos
, -EINVAL
);
140 rtm
= NLMSG_DATA(m
->hdr
);
147 int sd_rtnl_message_route_get_table(sd_netlink_message
*m
, unsigned char *table
) {
150 assert_return(m
, -EINVAL
);
151 assert_return(m
->hdr
, -EINVAL
);
152 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
153 assert_return(table
, -EINVAL
);
155 rtm
= NLMSG_DATA(m
->hdr
);
157 *table
= rtm
->rtm_table
;
162 int sd_rtnl_message_route_get_dst_prefixlen(sd_netlink_message
*m
, unsigned char *dst_len
) {
165 assert_return(m
, -EINVAL
);
166 assert_return(m
->hdr
, -EINVAL
);
167 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
168 assert_return(dst_len
, -EINVAL
);
170 rtm
= NLMSG_DATA(m
->hdr
);
172 *dst_len
= rtm
->rtm_dst_len
;
177 int sd_rtnl_message_route_get_src_prefixlen(sd_netlink_message
*m
, unsigned char *src_len
) {
180 assert_return(m
, -EINVAL
);
181 assert_return(m
->hdr
, -EINVAL
);
182 assert_return(rtnl_message_type_is_route(m
->hdr
->nlmsg_type
), -EINVAL
);
183 assert_return(src_len
, -EINVAL
);
185 rtm
= NLMSG_DATA(m
->hdr
);
187 *src_len
= rtm
->rtm_src_len
;
192 int sd_rtnl_message_new_route(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
193 uint16_t nlmsg_type
, int rtm_family
,
194 unsigned char rtm_protocol
) {
198 assert_return(rtnl_message_type_is_route(nlmsg_type
), -EINVAL
);
199 assert_return((nlmsg_type
== RTM_GETROUTE
&& rtm_family
== AF_UNSPEC
) ||
200 rtm_family
== AF_INET
|| rtm_family
== AF_INET6
, -EINVAL
);
201 assert_return(ret
, -EINVAL
);
203 r
= message_new(rtnl
, ret
, nlmsg_type
);
207 if (nlmsg_type
== RTM_NEWROUTE
)
208 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_CREATE
| NLM_F_APPEND
;
210 rtm
= NLMSG_DATA((*ret
)->hdr
);
212 rtm
->rtm_family
= rtm_family
;
213 rtm
->rtm_scope
= RT_SCOPE_UNIVERSE
;
214 rtm
->rtm_type
= RTN_UNICAST
;
215 rtm
->rtm_table
= RT_TABLE_MAIN
;
216 rtm
->rtm_protocol
= rtm_protocol
;
221 int sd_rtnl_message_neigh_set_flags(sd_netlink_message
*m
, uint8_t flags
) {
224 assert_return(m
, -EINVAL
);
225 assert_return(m
->hdr
, -EINVAL
);
226 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
228 ndm
= NLMSG_DATA(m
->hdr
);
229 ndm
->ndm_flags
|= flags
;
234 int sd_rtnl_message_neigh_set_state(sd_netlink_message
*m
, uint16_t state
) {
237 assert_return(m
, -EINVAL
);
238 assert_return(m
->hdr
, -EINVAL
);
239 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
241 ndm
= NLMSG_DATA(m
->hdr
);
242 ndm
->ndm_state
|= state
;
247 int sd_rtnl_message_neigh_get_flags(sd_netlink_message
*m
, uint8_t *flags
) {
250 assert_return(m
, -EINVAL
);
251 assert_return(m
->hdr
, -EINVAL
);
252 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
254 ndm
= NLMSG_DATA(m
->hdr
);
255 *flags
= ndm
->ndm_flags
;
260 int sd_rtnl_message_neigh_get_state(sd_netlink_message
*m
, uint16_t *state
) {
263 assert_return(m
, -EINVAL
);
264 assert_return(m
->hdr
, -EINVAL
);
265 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
267 ndm
= NLMSG_DATA(m
->hdr
);
268 *state
= ndm
->ndm_state
;
273 int sd_rtnl_message_neigh_get_family(sd_netlink_message
*m
, int *family
) {
276 assert_return(m
, -EINVAL
);
277 assert_return(m
->hdr
, -EINVAL
);
278 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
279 assert_return(family
, -EINVAL
);
281 ndm
= NLMSG_DATA(m
->hdr
);
283 *family
= ndm
->ndm_family
;
288 int sd_rtnl_message_neigh_get_ifindex(sd_netlink_message
*m
, int *index
) {
291 assert_return(m
, -EINVAL
);
292 assert_return(m
->hdr
, -EINVAL
);
293 assert_return(rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
), -EINVAL
);
294 assert_return(index
, -EINVAL
);
296 ndm
= NLMSG_DATA(m
->hdr
);
298 *index
= ndm
->ndm_ifindex
;
303 int sd_rtnl_message_new_neigh(sd_netlink
*rtnl
, sd_netlink_message
**ret
, uint16_t nlmsg_type
, int index
, int ndm_family
) {
307 assert_return(rtnl_message_type_is_neigh(nlmsg_type
), -EINVAL
);
308 assert_return(ndm_family
== AF_INET
||
309 ndm_family
== AF_INET6
||
310 ndm_family
== PF_BRIDGE
, -EINVAL
);
311 assert_return(ret
, -EINVAL
);
313 r
= message_new(rtnl
, ret
, nlmsg_type
);
317 if (nlmsg_type
== RTM_NEWNEIGH
)
318 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_CREATE
| NLM_F_APPEND
;
320 ndm
= NLMSG_DATA((*ret
)->hdr
);
322 ndm
->ndm_family
= ndm_family
;
323 ndm
->ndm_ifindex
= index
;
328 int sd_rtnl_message_link_set_flags(sd_netlink_message
*m
, unsigned flags
, unsigned change
) {
329 struct ifinfomsg
*ifi
;
331 assert_return(m
, -EINVAL
);
332 assert_return(m
->hdr
, -EINVAL
);
333 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
334 assert_return(change
, -EINVAL
);
336 ifi
= NLMSG_DATA(m
->hdr
);
338 ifi
->ifi_flags
= flags
;
339 ifi
->ifi_change
= change
;
344 int sd_rtnl_message_link_set_type(sd_netlink_message
*m
, unsigned type
) {
345 struct ifinfomsg
*ifi
;
347 assert_return(m
, -EINVAL
);
348 assert_return(m
->hdr
, -EINVAL
);
349 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
351 ifi
= NLMSG_DATA(m
->hdr
);
353 ifi
->ifi_type
= type
;
358 int sd_rtnl_message_link_set_family(sd_netlink_message
*m
, unsigned family
) {
359 struct ifinfomsg
*ifi
;
361 assert_return(m
, -EINVAL
);
362 assert_return(m
->hdr
, -EINVAL
);
363 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
365 ifi
= NLMSG_DATA(m
->hdr
);
367 ifi
->ifi_family
= family
;
372 int sd_rtnl_message_new_link(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
373 uint16_t nlmsg_type
, int index
) {
374 struct ifinfomsg
*ifi
;
377 assert_return(rtnl_message_type_is_link(nlmsg_type
), -EINVAL
);
378 assert_return(nlmsg_type
!= RTM_DELLINK
|| index
> 0, -EINVAL
);
379 assert_return(ret
, -EINVAL
);
381 r
= message_new(rtnl
, ret
, nlmsg_type
);
385 if (nlmsg_type
== RTM_NEWLINK
)
386 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_CREATE
| NLM_F_EXCL
;
388 ifi
= NLMSG_DATA((*ret
)->hdr
);
390 ifi
->ifi_family
= AF_UNSPEC
;
391 ifi
->ifi_index
= index
;
396 int sd_rtnl_message_addr_set_prefixlen(sd_netlink_message
*m
, unsigned char prefixlen
) {
397 struct ifaddrmsg
*ifa
;
399 assert_return(m
, -EINVAL
);
400 assert_return(m
->hdr
, -EINVAL
);
401 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
403 ifa
= NLMSG_DATA(m
->hdr
);
405 if ((ifa
->ifa_family
== AF_INET
&& prefixlen
> 32) ||
406 (ifa
->ifa_family
== AF_INET6
&& prefixlen
> 128))
409 ifa
->ifa_prefixlen
= prefixlen
;
414 int sd_rtnl_message_addr_set_flags(sd_netlink_message
*m
, unsigned char flags
) {
415 struct ifaddrmsg
*ifa
;
417 assert_return(m
, -EINVAL
);
418 assert_return(m
->hdr
, -EINVAL
);
419 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
421 ifa
= NLMSG_DATA(m
->hdr
);
423 ifa
->ifa_flags
= flags
;
428 int sd_rtnl_message_addr_set_scope(sd_netlink_message
*m
, unsigned char scope
) {
429 struct ifaddrmsg
*ifa
;
431 assert_return(m
, -EINVAL
);
432 assert_return(m
->hdr
, -EINVAL
);
433 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
435 ifa
= NLMSG_DATA(m
->hdr
);
437 ifa
->ifa_scope
= scope
;
442 int sd_rtnl_message_addr_get_family(sd_netlink_message
*m
, int *family
) {
443 struct ifaddrmsg
*ifa
;
445 assert_return(m
, -EINVAL
);
446 assert_return(m
->hdr
, -EINVAL
);
447 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
448 assert_return(family
, -EINVAL
);
450 ifa
= NLMSG_DATA(m
->hdr
);
452 *family
= ifa
->ifa_family
;
457 int sd_rtnl_message_addr_get_prefixlen(sd_netlink_message
*m
, unsigned char *prefixlen
) {
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
);
463 assert_return(prefixlen
, -EINVAL
);
465 ifa
= NLMSG_DATA(m
->hdr
);
467 *prefixlen
= ifa
->ifa_prefixlen
;
472 int sd_rtnl_message_addr_get_scope(sd_netlink_message
*m
, unsigned char *scope
) {
473 struct ifaddrmsg
*ifa
;
475 assert_return(m
, -EINVAL
);
476 assert_return(m
->hdr
, -EINVAL
);
477 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
478 assert_return(scope
, -EINVAL
);
480 ifa
= NLMSG_DATA(m
->hdr
);
482 *scope
= ifa
->ifa_scope
;
487 int sd_rtnl_message_addr_get_flags(sd_netlink_message
*m
, unsigned char *flags
) {
488 struct ifaddrmsg
*ifa
;
490 assert_return(m
, -EINVAL
);
491 assert_return(m
->hdr
, -EINVAL
);
492 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
493 assert_return(flags
, -EINVAL
);
495 ifa
= NLMSG_DATA(m
->hdr
);
497 *flags
= ifa
->ifa_flags
;
502 int sd_rtnl_message_addr_get_ifindex(sd_netlink_message
*m
, int *ifindex
) {
503 struct ifaddrmsg
*ifa
;
505 assert_return(m
, -EINVAL
);
506 assert_return(m
->hdr
, -EINVAL
);
507 assert_return(rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
), -EINVAL
);
508 assert_return(ifindex
, -EINVAL
);
510 ifa
= NLMSG_DATA(m
->hdr
);
512 *ifindex
= ifa
->ifa_index
;
517 int sd_rtnl_message_new_addr(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
518 uint16_t nlmsg_type
, int index
,
520 struct ifaddrmsg
*ifa
;
523 assert_return(rtnl_message_type_is_addr(nlmsg_type
), -EINVAL
);
524 assert_return((nlmsg_type
== RTM_GETADDR
&& index
== 0) ||
526 assert_return((nlmsg_type
== RTM_GETADDR
&& family
== AF_UNSPEC
) ||
527 family
== AF_INET
|| family
== AF_INET6
, -EINVAL
);
528 assert_return(ret
, -EINVAL
);
530 r
= message_new(rtnl
, ret
, nlmsg_type
);
534 if (nlmsg_type
== RTM_GETADDR
)
535 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_DUMP
;
537 ifa
= NLMSG_DATA((*ret
)->hdr
);
539 ifa
->ifa_index
= index
;
540 ifa
->ifa_family
= family
;
541 if (family
== AF_INET
)
542 ifa
->ifa_prefixlen
= 32;
543 else if (family
== AF_INET6
)
544 ifa
->ifa_prefixlen
= 128;
549 int sd_rtnl_message_new_addr_update(sd_netlink
*rtnl
, sd_netlink_message
**ret
,
550 int index
, int family
) {
553 r
= sd_rtnl_message_new_addr(rtnl
, ret
, RTM_NEWADDR
, index
, family
);
557 (*ret
)->hdr
->nlmsg_flags
|= NLM_F_REPLACE
;
562 int sd_rtnl_message_link_get_ifindex(sd_netlink_message
*m
, int *ifindex
) {
563 struct ifinfomsg
*ifi
;
565 assert_return(m
, -EINVAL
);
566 assert_return(m
->hdr
, -EINVAL
);
567 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
568 assert_return(ifindex
, -EINVAL
);
570 ifi
= NLMSG_DATA(m
->hdr
);
572 *ifindex
= ifi
->ifi_index
;
577 int sd_rtnl_message_link_get_flags(sd_netlink_message
*m
, unsigned *flags
) {
578 struct ifinfomsg
*ifi
;
580 assert_return(m
, -EINVAL
);
581 assert_return(m
->hdr
, -EINVAL
);
582 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
583 assert_return(flags
, -EINVAL
);
585 ifi
= NLMSG_DATA(m
->hdr
);
587 *flags
= ifi
->ifi_flags
;
592 int sd_rtnl_message_link_get_type(sd_netlink_message
*m
, unsigned *type
) {
593 struct ifinfomsg
*ifi
;
595 assert_return(m
, -EINVAL
);
596 assert_return(m
->hdr
, -EINVAL
);
597 assert_return(rtnl_message_type_is_link(m
->hdr
->nlmsg_type
), -EINVAL
);
598 assert_return(type
, -EINVAL
);
600 ifi
= NLMSG_DATA(m
->hdr
);
602 *type
= ifi
->ifi_type
;
607 int sd_rtnl_message_get_family(sd_netlink_message
*m
, int *family
) {
608 assert_return(m
, -EINVAL
);
609 assert_return(family
, -EINVAL
);
613 if (rtnl_message_type_is_link(m
->hdr
->nlmsg_type
)) {
614 struct ifinfomsg
*ifi
;
616 ifi
= NLMSG_DATA(m
->hdr
);
618 *family
= ifi
->ifi_family
;
621 } else if (rtnl_message_type_is_route(m
->hdr
->nlmsg_type
)) {
624 rtm
= NLMSG_DATA(m
->hdr
);
626 *family
= rtm
->rtm_family
;
629 } else if (rtnl_message_type_is_neigh(m
->hdr
->nlmsg_type
)) {
632 ndm
= NLMSG_DATA(m
->hdr
);
634 *family
= ndm
->ndm_family
;
637 } else if (rtnl_message_type_is_addr(m
->hdr
->nlmsg_type
)) {
638 struct ifaddrmsg
*ifa
;
640 ifa
= NLMSG_DATA(m
->hdr
);
642 *family
= ifa
->ifa_family
;