]>
Commit | Line | Data |
---|---|---|
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" | |
8041b5ba | 26 | |
1df2a0fc | 27 | #include "ifconf.h" |
8041b5ba | 28 | |
d1ca51b1 TG |
29 | int ifconf_acquire_addresses(struct address **_list, unsigned *_n_list) { |
30 | _cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL; | |
31 | _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL, *reply = NULL; | |
32 | sd_rtnl_message *m; | |
33 | _cleanup_free_ struct address *list = NULL; | |
34 | struct address *new_list = NULL; | |
35 | unsigned n_list = 0; | |
36 | int r; | |
d73c3269 | 37 | |
d1ca51b1 TG |
38 | r = sd_rtnl_open(&rtnl, 0); |
39 | if (r < 0) | |
40 | return r; | |
8041b5ba | 41 | |
d1ca51b1 TG |
42 | r = sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC); |
43 | if (r < 0) | |
44 | return r; | |
8041b5ba | 45 | |
d1ca51b1 TG |
46 | r = sd_rtnl_call(rtnl, req, 0, &reply); |
47 | if (r < 0) | |
48 | return r; | |
49 | m = reply; | |
50 | ||
51 | do { | |
52 | uint16_t type; | |
53 | unsigned char scope; | |
54 | unsigned char flags; | |
55 | unsigned char family; | |
56 | int ifindex; | |
57 | union { | |
58 | struct in_addr in; | |
59 | struct in6_addr in6; | |
60 | } address; | |
61 | ||
62 | r = sd_rtnl_message_get_errno(m); | |
63 | if (r < 0) | |
64 | return r; | |
65 | ||
66 | r = sd_rtnl_message_get_type(m, &type); | |
67 | if (r < 0) | |
68 | return r; | |
69 | ||
70 | if (type != RTM_NEWADDR) | |
8041b5ba LP |
71 | continue; |
72 | ||
d1ca51b1 TG |
73 | r = sd_rtnl_message_addr_get_scope(m, &scope); |
74 | if (r < 0) | |
75 | return r; | |
8041b5ba | 76 | |
d1ca51b1 | 77 | if (scope == RT_SCOPE_HOST || scope == RT_SCOPE_NOWHERE) |
d73c3269 | 78 | continue; |
8041b5ba | 79 | |
d1ca51b1 TG |
80 | r = sd_rtnl_message_addr_get_flags(m, &flags); |
81 | if (r < 0) | |
82 | return r; | |
8041b5ba | 83 | |
d1ca51b1 | 84 | if (flags & IFA_F_DEPRECATED) |
d73c3269 | 85 | continue; |
8041b5ba | 86 | |
d1ca51b1 TG |
87 | r = sd_rtnl_message_addr_get_family(m, &family); |
88 | if (r < 0) | |
89 | return r; | |
90 | ||
91 | switch (family) { | |
92 | case AF_INET: | |
93 | r = sd_rtnl_message_read_in_addr(m, IFA_LOCAL, &address.in); | |
94 | if (r < 0) { | |
95 | r = sd_rtnl_message_read_in_addr(m, IFA_ADDRESS, &address.in); | |
96 | if (r < 0) | |
97 | continue; | |
98 | } | |
99 | break; | |
100 | case AF_INET6: | |
101 | r = sd_rtnl_message_read_in6_addr(m, IFA_LOCAL, &address.in6); | |
102 | if (r < 0) { | |
103 | r = sd_rtnl_message_read_in6_addr(m, IFA_ADDRESS, &address.in6); | |
104 | if (r < 0) | |
105 | continue; | |
106 | } | |
107 | break; | |
108 | default: | |
d73c3269 | 109 | continue; |
d73c3269 | 110 | } |
8041b5ba | 111 | |
d1ca51b1 TG |
112 | r = sd_rtnl_message_addr_get_ifindex(m, &ifindex); |
113 | if (r < 0) | |
114 | return r; | |
8041b5ba | 115 | |
d1ca51b1 TG |
116 | new_list = realloc(list, (n_list+1) * sizeof(struct address)); |
117 | if (!new_list) | |
118 | return -ENOMEM; | |
119 | else | |
120 | list = new_list; | |
8041b5ba | 121 | |
d1ca51b1 | 122 | assert_cc(sizeof(address) <= 16); |
8041b5ba | 123 | |
d1ca51b1 TG |
124 | list[n_list].family = family; |
125 | list[n_list].scope = scope; | |
126 | memcpy(list[n_list].address, &address, sizeof(address)); | |
127 | list[n_list].ifindex = ifindex; | |
8041b5ba | 128 | |
d1ca51b1 | 129 | n_list++; |
7464b33d | 130 | |
d1ca51b1 | 131 | } while ((m = sd_rtnl_message_next(m))); |
8041b5ba | 132 | |
7ff7394d ZJS |
133 | if (n_list) |
134 | qsort(list, n_list, sizeof(struct address), address_compare); | |
d73c3269 | 135 | |
d73c3269 | 136 | *_n_list = n_list; |
d1ca51b1 TG |
137 | *_list = list; |
138 | list = NULL; | |
d73c3269 ZJS |
139 | |
140 | return 0; | |
8041b5ba | 141 | } |