chiark / gitweb /
resolve: fix copy/paste error
[elogind.git] / src / nss-myhostname / netlink.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2008-2011 Lennart Poettering
7   Copyright 2014 Tom Gundersen
8
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.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
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/>.
21 ***/
22
23 #include "sd-rtnl.h"
24 #include "rtnl-util.h"
25 #include "macro.h"
26
27 #include "ifconf.h"
28
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;
37
38         r = sd_rtnl_open(&rtnl, 0);
39         if (r < 0)
40                 return r;
41
42         r = sd_rtnl_message_new_addr(rtnl, &req, RTM_GETADDR, 0, AF_UNSPEC);
43         if (r < 0)
44                 return r;
45
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)
71                         continue;
72
73                 r = sd_rtnl_message_addr_get_scope(m, &scope);
74                 if (r < 0)
75                         return r;
76
77                 if (scope == RT_SCOPE_HOST || scope == RT_SCOPE_NOWHERE)
78                         continue;
79
80                 r = sd_rtnl_message_addr_get_flags(m, &flags);
81                 if (r < 0)
82                         return r;
83
84                 if (flags & IFA_F_DEPRECATED)
85                         continue;
86
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:
109                         continue;
110                 }
111
112                 r = sd_rtnl_message_addr_get_ifindex(m, &ifindex);
113                 if (r < 0)
114                         return r;
115
116                 new_list = realloc(list, (n_list+1) * sizeof(struct address));
117                 if (!new_list)
118                         return -ENOMEM;
119                 else
120                         list = new_list;
121
122                 assert_cc(sizeof(address) <= 16);
123
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;
128
129                 n_list++;
130
131         } while ((m = sd_rtnl_message_next(m)));
132
133         if (n_list)
134                 qsort(list, n_list, sizeof(struct address), address_compare);
135
136         *_n_list = n_list;
137         *_list = list;
138         list = NULL;
139
140         return 0;
141 }