]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-rtnl/local-addresses.c
networkd: fix typo
[thirdparty/systemd.git] / src / libsystemd / sd-rtnl / local-addresses.c
CommitLineData
8041b5ba
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
cbc06dcd 4 This file is part of systemd.
8041b5ba
LP
5
6 Copyright 2008-2011 Lennart Poettering
d1ca51b1 7 Copyright 2014 Tom Gundersen
8041b5ba 8
cbc06dcd
TG
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
8041b5ba 13
cbc06dcd
TG
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
8041b5ba
LP
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
18
cbc06dcd
TG
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
8041b5ba
LP
21***/
22
d1ca51b1
TG
23#include "sd-rtnl.h"
24#include "rtnl-util.h"
25#include "macro.h"
e80af1bd 26#include "local-addresses.h"
8041b5ba 27
5502f0d9 28static int address_compare(const void *_a, const void *_b) {
e80af1bd 29 const struct local_address *a = _a, *b = _b;
5502f0d9
LP
30
31 /* Order lowest scope first, IPv4 before IPv6, lowest interface index first */
32
33 if (a->scope < b->scope)
34 return -1;
35 if (a->scope > b->scope)
36 return 1;
37
38 if (a->family == AF_INET && b->family == AF_INET6)
39 return -1;
40 if (a->family == AF_INET6 && b->family == AF_INET)
41 return 1;
42
43 if (a->ifindex < b->ifindex)
44 return -1;
45 if (a->ifindex > b->ifindex)
46 return 1;
47
48 return 0;
49}
50
ee8c4568 51int local_addresses(sd_rtnl *context, int ifindex, struct local_address **ret) {
d1ca51b1 52 _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL;
5502f0d9 53 _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
e80af1bd 54 _cleanup_free_ struct local_address *list = NULL;
5502f0d9
LP
55 size_t n_list = 0, n_allocated = 0;
56 sd_rtnl_message *m;
d1ca51b1 57 int r;
d73c3269 58
e80af1bd
LP
59 assert(ret);
60
ee8c4568
LP
61 if (context)
62 rtnl = sd_rtnl_ref(context);
63 else {
64 r = sd_rtnl_open(&rtnl, 0);
65 if (r < 0)
66 return r;
67 }
8041b5ba 68
d1ca51b1
TG
69 r = sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
70 if (r < 0)
71 return r;
8041b5ba 72
d1ca51b1
TG
73 r = sd_rtnl_call(rtnl, req, 0, &reply);
74 if (r < 0)
75 return r;
d1ca51b1 76
5502f0d9 77 for (m = reply; m; m = sd_rtnl_message_next(m)) {
e80af1bd 78 struct local_address *a;
d1ca51b1 79 unsigned char flags;
5502f0d9 80 uint16_t type;
ee8c4568 81 int ifi;
d1ca51b1
TG
82
83 r = sd_rtnl_message_get_errno(m);
84 if (r < 0)
85 return r;
86
87 r = sd_rtnl_message_get_type(m, &type);
88 if (r < 0)
89 return r;
90
91 if (type != RTM_NEWADDR)
8041b5ba
LP
92 continue;
93
ee8c4568
LP
94 r = sd_rtnl_message_addr_get_ifindex(m, &ifi);
95 if (r < 0)
96 return r;
97
98 if (ifindex != 0 && ifi != ifindex)
99 continue;
100
5502f0d9 101 r = sd_rtnl_message_addr_get_flags(m, &flags);
d1ca51b1
TG
102 if (r < 0)
103 return r;
8041b5ba 104
5502f0d9 105 if (flags & IFA_F_DEPRECATED)
d73c3269 106 continue;
8041b5ba 107
5502f0d9
LP
108 if (!GREEDY_REALLOC(list, n_allocated, n_list+1))
109 return -ENOMEM;
110
111 a = list + n_list;
112
113 r = sd_rtnl_message_addr_get_scope(m, &a->scope);
d1ca51b1
TG
114 if (r < 0)
115 return r;
8041b5ba 116
ee8c4568 117 if (ifindex == 0 && (a->scope == RT_SCOPE_HOST || a->scope == RT_SCOPE_NOWHERE))
d73c3269 118 continue;
8041b5ba 119
5502f0d9 120 r = sd_rtnl_message_addr_get_family(m, &a->family);
d1ca51b1
TG
121 if (r < 0)
122 return r;
123
5502f0d9
LP
124 switch (a->family) {
125
d1ca51b1 126 case AF_INET:
5502f0d9 127 r = sd_rtnl_message_read_in_addr(m, IFA_LOCAL, &a->address.in);
d1ca51b1 128 if (r < 0) {
5502f0d9 129 r = sd_rtnl_message_read_in_addr(m, IFA_ADDRESS, &a->address.in);
d1ca51b1
TG
130 if (r < 0)
131 continue;
132 }
133 break;
5502f0d9 134
d1ca51b1 135 case AF_INET6:
5502f0d9 136 r = sd_rtnl_message_read_in6_addr(m, IFA_LOCAL, &a->address.in6);
d1ca51b1 137 if (r < 0) {
5502f0d9 138 r = sd_rtnl_message_read_in6_addr(m, IFA_ADDRESS, &a->address.in6);
d1ca51b1
TG
139 if (r < 0)
140 continue;
141 }
142 break;
5502f0d9 143
d1ca51b1 144 default:
d73c3269 145 continue;
d73c3269 146 }
8041b5ba 147
ee8c4568 148 a->ifindex = ifi;
8041b5ba 149
d1ca51b1 150 n_list++;
5502f0d9 151 };
8041b5ba 152
7ff7394d 153 if (n_list)
e80af1bd 154 qsort(list, n_list, sizeof(struct local_address), address_compare);
d73c3269 155
e80af1bd 156 *ret = list;
d1ca51b1 157 list = NULL;
d73c3269 158
e80af1bd 159 return (int) n_list;
8041b5ba 160}